4. Pod 驱逐机制详解:node-lifecycle-controller 与 Taint/Toleration 原理
在 Kubernetes 集群中,节点故障是常态而非例外。当节点发生故障(如网络不可达、磁盘压力、内存不足)时,控制平面需要快速、安全地将受影响的 Pod 从故障节点上驱逐,以保障工作负载的 SLO。这一过程的核心驱动力来自 kube-controller-manager 中的 node-lifecycle-controller,以及 Taint(污点) 与 Toleration(容忍) 机制。
4.1 node-lifecycle-controller:节点状态监控与条件管理
node-lifecycle-controller 是 kube-controller-manager 中的一个核心控制器,负责持续监控集群中每个节点的健康状态,并根据节点条件(Node Conditions)自动添加或移除 Taint。其工作流程如下:
- 心跳检测:每个节点上的 kubelet 定期向 API Server 上报心跳(Node Status),默认间隔为 10 秒(
--node-status-update-frequency)。 - 条件评估:node-lifecycle-controller 检查节点状态中的
Ready、DiskPressure、MemoryPressure、PIDPressure等条件。 - 超时判定:如果节点在
--node-monitor-grace-period(默认 40 秒)内未上报状态,控制器将节点标记为Unknown。 - 自动添加 Taint:根据节点条件,控制器自动为节点添加对应的 Taint(如
node.kubernetes.io/unreachable、node.kubernetes.io/not-ready)。 - Pod 驱逐触发:已存在的 Pod 如果没有对应的 Toleration,将根据 Taint 的
effect被驱逐。
| 参数名 | 默认值 | 作用 |
|---|---|---|
--node-monitor-period |
5s | 控制器轮询节点状态的周期 |
--node-monitor-grace-period |
40s | 节点状态上报超时宽限期 |
--pod-eviction-timeout |
5m | 节点 NotReady 或 Unreachable 后,Pod 被强制驱逐的等待时间 |
--node-startup-grace-period |
1m0s | 节点启动期间的特殊宽限期 |
4.2 Taint 与 Toleration:Pod 调度的“准入与排斥”机制
Taint 是附加在节点上的一组键值对,用于标记节点的“缺陷”或“特殊属性”。Toleration 是附加在 Pod 上的声明,表示 Pod 能够“容忍”某些 Taint。两者共同决定了 Pod 能否被调度到特定节点,以及节点故障时 Pod 是否被驱逐。
4.2.1 Taint 的结构与 Effect
一个 Taint 由三个部分组成:key、value(可选)和 effect。Effect 决定了 Pod 对 Taint 的反应行为:
| Effect 类型 | 行为描述 | 典型场景 |
|---|---|---|
NoSchedule |
新的 Pod 不会被调度到该节点(已存在的 Pod 不受影响) | 节点维护、预留资源 |
PreferNoSchedule |
尽量不调度新 Pod 到该节点(软约束,调度器会尽量避免) | 节点负载较高但未达到硬限制 |
NoExecute |
新的 Pod 不会被调度,且已存在的 Pod 如果没有对应 Toleration 将被驱逐 | 节点故障、磁盘压力、内存压力 |
4.2.2 系统自动添加的 Taint
node-lifecycle-controller 会根据节点条件自动添加以下 Taint(均为 NoExecute 效果):
node.kubernetes.io/not-ready:节点未就绪(Ready 条件为 False)node.kubernetes.io/unreachable:节点不可达(Ready 条件为 Unknown)node.kubernetes.io/memory-pressure:节点内存压力node.kubernetes.io/disk-pressure:节点磁盘压力node.kubernetes.io/pid-pressure:节点 PID 压力node.kubernetes.io/network-unavailable:节点网络不可用node.kubernetes.io/unschedulable:节点被标记为不可调度
node.kubernetes.io/not-ready 和 node.kubernetes.io/unreachable 的 Toleration,并设置合理的 tolerationSeconds,以控制 Pod 在节点故障后的存活时间,避免被立即驱逐。
4.3 Pod 驱逐流程:从节点故障到 Pod 终止
下图展示了当节点发生网络故障时,从节点状态变化到 Pod 被驱逐的完整流程:
4.4 Toleration 的配置与 TolerationSeconds
Pod 通过 spec.tolerations 字段声明对 Taint 的容忍。以下是一个典型的 Toleration 配置示例:
apiVersion: v1
kind: Pod
metadata:
name: slo-job-pod
spec:
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 120
- key: "node.kubernetes.io/not-ready"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 120
containers:
- name: workload
image: my-slo-app:latest
Toleration 字段详解:
| 字段 | 说明 | 示例值 |
|---|---|---|
key |
要容忍的 Taint 的键 | node.kubernetes.io/unreachable |
operator |
匹配操作符:Exists(仅匹配 key)或 Equal(匹配 key+value) |
Exists |
value |
当 operator 为 Equal 时需指定 |
node1 |
effect |
要容忍的 Taint 效果,留空则匹配所有效果 | NoExecute |
tolerationSeconds |
Pod 在节点上容忍 Taint 的最大秒数,超时后将被驱逐 | 120 |
tolerationSeconds 仅对 NoExecute 效果有效。如果不设置该字段,Pod 将永久容忍该 Taint(即永远不会被驱逐)。对于 SLO 作业,建议设置一个合理的超时时间(如 60-300 秒),以便在节点短暂故障时保留 Pod,避免频繁重建。
4.5 节点故障时的 Pod 驱逐时间线
以下时间线展示了从节点故障到 Pod 被驱逐的完整过程(假设使用默认参数):
4.6 驱逐策略对 SLO 作业的影响
对于 SLO 作业(如批处理任务、实时推理服务),Pod 驱逐可能导致作业中断、数据丢失或延迟飙升。以下是针对不同场景的优化建议:
| 场景 | 推荐策略 | 配置示例 |
|---|---|---|
| 短生命周期批处理作业 | 设置较短的 tolerationSeconds(如 30s),快速驱逐并重新调度 |
tolerationSeconds: 30 |
| 长生命周期有状态服务 | 设置较长的 tolerationSeconds(如 300s),等待节点恢复 |
tolerationSeconds: 300 |
| 对延迟敏感的服务 | 使用 PreferNoSchedule 的 Toleration,配合 PDB(PodDisruptionBudget) |
不设置 tolerationSeconds,依赖 PDB 控制 |
| 需要保证数据完整性的作业 | 使用 preStop 钩子 + 优雅关闭,配合 terminationGracePeriodSeconds |
terminationGracePeriodSeconds: 60 |