一台工作节点失联后,Deployment 不会立刻在其他节点补副本。控制面要先认定节点无响应,再打上 NoExecute 污点;Pod 默认还能再留 300 秒。一批节点一起失联时,污点有速率限制,小集群甚至会停掉驱逐。这几分钟里少掉的是可用容量,不是监控刷新慢。
kubelet 默认每 10 秒更新一次 kube-node-lease 里、与节点同名的 Lease 的 spec.renewTime。节点 .status 没有变化时默认 5 分钟才写一次,不能拿它判断节点还活着。
--node-monitor-grace-period 当前上游默认 50 秒,--node-monitor-period 默认 5 秒。宽限内没有新续约,Ready 写成 Unknown,污点是 node.kubernetes.io/unreachable:NoExecute,reason 为 NodeStatusUnknown。kubelet 自己报不健康时,Ready 是 False,污点是 node.kubernetes.io/not-ready:NoExecute。两种都要配容忍。控制器改写失联状态时不更新 lastHeartbeatTime,它仍是 kubelet 上次写 status 的时间。
节点状态文档的条件表写 50 秒,同一页心跳一节还留着 40 秒;更早发行版默认也是 40 秒。以该集群 kube-controller-manager 的实际参数为准。
NoSchedule 只挡新 Pod。失联污点是 NoExecute,才会删已经绑定的 Pod。
没显式写对应容忍时,准入控制补上这两条,tolerationSeconds 都是 300。参数是 kube-apiserver 的 --default-not-ready-toleration-seconds 和 --default-unreachable-toleration-seconds。计时从匹配污点出现开始,污点先被清掉就不会删。
单节点、污点没排队时,从最后一次成功续约到开始删 Pod,大约是 50 秒加 300 秒,再加最多一个 5 秒检查周期,接近 6 分钟。调度、拉镜像和就绪探针还不在这 6 分钟里。
DaemonSet 也带这两条 key,但没有 tolerationSeconds,表示一直容忍,失联也不驱逐。抄进 Deployment,故障时副本补不上。1.29 起这条路径在 taint-eviction-controller 里,--controllers=-taint-eviction-controller 会把它关掉。300 秒的语义不变。
加污点有速率限制,避免分区时把大量 Pod 一起删掉。300 秒从污点打上才开始,排队的节点更晚被删。多可用区时按每个 zone 算;不跨区时 zone 就是整个集群。
参数 | 默认 | 含义 |
|---|---|---|
| 0.1 | zone 正常时,大约每 10 秒一个节点 |
| 0.55 | 不健康比例 |
| 50 | 小集群分界;多 zone 时按 zone 内节点数 |
| 0.01 | 大集群部分中断时约 100 秒一个节点 |
部分中断要同时满足:NotReady 多于 2 个,且比例达到 0.55。
4 个节点的单 zone、3 个 NotReady:超过 2 个,比例 0.75,节点数不超过 50,速率是 0。剩下的健康节点不会收到迁来的副本。3 个节点里只有 2 个 NotReady,还没越过「多于 2 个」,仍按 0.1。单 zone 的 3 个节点全不健康,属于所有 zone 都中断,同样不驱逐;若这 3 个只是多 zone 集群里的一个 zone,而别处还有 Ready 节点,则按 0.1 迁走。
TKE 默认把 Service 后端配到节点 NodePort。Service Controller 不把 NotReady 节点挂上去;Unschedulable 的节点仍可以挂,封锁不会自动摘掉。CLB 上这个后端消失,只说明新流量不再从这条 NodePort 路径进该节点,不表示 Pod 已在其他节点重建。直连 Pod 的后端是 Pod 地址,不要套用这句。
节点宕机时,缺口持续到驱逐发生且新 Pod 就绪。网络分区时,API 里已经删除的 Pod,kubelet 在通信恢复前收不到,进程可能还在旧节点上跑。没有选主或 fencing 的写入,会出现旧进程还在写、新 Pod 也起来了的窗口。全集群被看成不可达时则不驱逐,新副本也不会建。
Deployment 在旧 Pod 进入删除后就按期望副本数补新的,不用等进程退出。StatefulSet 同一序号要等旧 Pod 从 API 消失才重建。kubelet 不在时优雅期限跑不完,对象可能停在 Terminating,这会卡住 StatefulSet。
无状态且副本已跨节点的服务,可以把容忍写短。两条都要显式写。只写 not-ready 时,unreachable 仍会被补成 300 秒,心跳丢失走的正是这一条。
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout
namespace: prod
spec:
replicas: 3
selector:
matchLabels:
app: checkout
template:
metadata:
labels:
app: checkout
spec:
tolerations:
- key: node.kubernetes.io/not-ready
operator: Exists
effect: NoExecute
tolerationSeconds: 60
- key: node.kubernetes.io/unreachable
operator: Exists
effect: NoExecute
tolerationSeconds: 60
containers:
- name: checkout
image: example.com/checkout:1.8.0tolerationSeconds: 0 表示污点一出现就删。宽限只有几十秒,控制面短暂卡住也可能让 Lease 续不上,再叠 0 秒就会全量重建。有本地数据或靠选主的服务不要改成 0。
PDB 挡不住节点失联这类非自愿中断,但被删的 Pod 仍计入预算,同时进行的 kubectl drain 可能被拒绝。这和排水卡在 PDB 不是同一条路径。
节点名换成实际值。tolerationSeconds 打印成空是无限容忍,不是 0。控制器改写失联时,Ready 的 reason 应为 NodeStatusUnknown。
kubectl get node 10.0.0.12 -o jsonpath='{.status.conditions[?(@.type=="Ready")].reason} {.status.conditions[?(@.type=="Ready")].lastHeartbeatTime}'
echo
kubectl get lease -n kube-node-lease 10.0.0.12 -o jsonpath='{.spec.renewTime}'
echo
kubectl get pod -n prod -l app=checkout -o jsonpath='{range .items[*]}{.metadata.name} {range .spec.tolerations[*]}{.key}={.tolerationSeconds};{end}{end}'
echo驱逐开始后才有 deletionTimestamp,DisruptionTarget 的 reason 为 DeletionByTaintManager。在这之前 readyReplicas 偏低是正常窗口;该字段为 0 时经常被省略,打出来是空的,不是命令失败。
kubectl get pod -n prod -l app=checkout -o jsonpath='{range .items[*]}{.metadata.name} {.metadata.deletionTimestamp} {.status.conditions[?(@.type=="DisruptionTarget")].reason} {end}'
echo
kubectl get deploy -n prod checkout -o jsonpath='{.spec.replicas} {.status.readyReplicas}'
echo大面积 NotReady 却长时间没有 unreachable 污点,先对照停驱逐条件,不要先改业务重启策略。
NoExecute 要么写了秒数,要么接受默认 300 秒的容量缺口。tolerationSeconds 的写法。renewTime 和 readyReplicas,不要要求节点一红就在 10 秒内补齐。参考文档:Taints and Tolerations、Nodes、Node Status、Disruptions、TKE Service 后端选择。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。