3. Taint 基础概念:定义、Effect 类型与组成结构

在 Kubernetes 集群中,Taint(污点) 是施加在 Node(节点) 上的一种属性标记,用于排斥不符合条件的 Pod 调度到该节点上。它与 Toleration(容忍) 共同构成 Kubernetes 的“污点-容忍”调度控制机制,是保障集群资源隔离、节点安全、故障迁移的核心手段。

3.1 Taint 的定义与作用

Taint 的本质是一个键值对 + 效果(Effect)的组合,附加在 Node 对象上。当 Node 被打上 Taint 后,Kubernetes 调度器默认不会将任何 Pod 调度到该节点,除非 Pod 显式声明了能够容忍该 Taint。

核心作用:
  • 节点独占:将特定节点(如 GPU 节点、高内存节点)保留给特定工作负载。
  • 故障隔离:节点出现硬件故障、内核异常时自动添加 Taint,驱逐已有 Pod。
  • 维护窗口:节点计划内维护时添加 Taint,避免新 Pod 调度上来。
  • 节点分组:按功能(如 frontend/backend/storage)对节点进行逻辑隔离。

3.2 Taint 的组成结构

一个完整的 Taint 由三个字段组成,使用 kubectl taint 命令或 YAML 声明时遵循以下格式:

kubectl taint nodes <node-name> <key>=<value>:<Effect>
字段 说明 示例 约束
Key 污点的键,用于标识污点类别 gpu、node.kubernetes.io/unreachable 最长 253 个字符,只能包含字母、数字、-、_、.,不能为空
Value 污点的值,可选字段,用于细分污点 true、nvidia-tesla 最长 63 个字符,可为空字符串
Effect 污点的效果,决定调度器如何处理不匹配的 Pod NoSchedule 仅允许三种预定义值(见 3.3 节)
实战建议:Key 的命名建议使用域名格式(如 dedicated.kubernetes.io/gpu)以避免冲突。Value 字段通常用于区分同一 Key 下的不同子类型,例如 gpu=nvidia-tesla-v100 与 gpu=nvidia-a100。

3.3 Effect 类型详解

Kubernetes 定义了三种 Effect,它们对 Pod 调度和运行状态的影响逐级增强:

Effect 类型 调度影响 对已有 Pod 的影响 典型场景
NoSchedule 拒绝新 Pod 调度到该节点 不影响已在运行的 Pod 节点预留、资源隔离
PreferNoSchedule 尽量不调度,但不强制 不影响已在运行的 Pod 软性偏好、成本优化
NoExecute 拒绝新 Pod 调度 驱逐不匹配的已有 Pod 节点故障、安全隔离

3.3.1 NoSchedule

最常用的 Effect。调度器在调度新 Pod 时,如果节点存在 Pod 未容忍的 NoSchedule 污点,则直接跳过该节点。已在节点上运行的 Pod 不受影响。适用于将特定节点保留给特定工作负载,例如 GPU 节点只运行 AI 训练任务。

3.3.2 PreferNoSchedule

软性版本。调度器会尽量避免将 Pod 调度到该节点,但如果集群中没有其他可用节点,调度器仍可能将 Pod 调度上去。适用于成本优化场景,例如将低优先级的批处理任务尽量调度到廉价节点上,但不强制。

3.3.3 NoExecute

最严格的 Effect。它不仅拒绝新 Pod 调度,还会驱逐节点上所有不匹配该污点的已有 Pod。如果 Pod 设置了 tolerationSeconds,则可以在指定时间内继续运行,超时后被驱逐。适用于节点故障、安全隔离、节点下线等场景。

注意:使用 NoExecute 污点时要格外谨慎,因为它会立即驱逐节点上的 Pod,可能导致服务中断。建议先使用 NoSchedule 观察影响,再升级为 NoExecute。

3.4 Taint 组成结构示意图

下图展示了 Taint 在 Node 对象中的存储结构,以及调度器如何根据 Taint 与 Pod 的 Toleration 进行匹配决策:

Taint 组成结构与调度匹配流程 Node 对象 metadata.name: node-01 spec.taints: - key: gpu value: nvidia effect: NoSchedule 读取 调度器 1. 检查 Node Taint 2. 检查 Pod Toleration 3. 匹配决策 4. 调度/跳过/驱逐 匹配 Pod A(有容忍) tolerations: - key: gpu, operator: Equal Pod B(无容忍) tolerations: [] 匹配结果 Pod A 容忍 gpu=NoSchedule → 允许调度到 node-01 Pod B 未容忍 gpu=NoSchedule → 被拒绝调度到 node-01 三种 Effect 对比 NoSchedule 拒绝新 Pod,不影响已有 Pod PreferNoSchedule 尽量不调度,但不强制 NoExecute 拒绝新 Pod + 驱逐已有 Pod

3.5 操作 Taint 的常用命令

以下命令用于在集群中管理 Taint:

操作 命令示例 说明
添加 Taint kubectl taint nodes node01 gpu=nvidia:NoSchedule 为 node01 添加一个 Key=gpu, Value=nvidia, Effect=NoSchedule 的污点
查看 Taint kubectl describe node node01 | grep Taints 查看 node01 上的所有 Taint
删除 Taint kubectl taint nodes node01 gpu=nvidia:NoSchedule- 删除 node01 上 Key=gpu, Effect=NoSchedule 的污点(末尾加 -)
删除所有 Taint kubectl taint nodes node01 gpu- 删除 node01 上所有 Key=gpu 的污点(不指定 Effect)
快速验证:添加 Taint 后,可以立即使用 kubectl get pods -o wide 观察是否有新 Pod 被调度到该节点。如果节点上已有 Pod 且未设置 Toleration,NoExecute 污点会触发 Pod 驱逐,可通过 kubectl get events --watch 实时查看驱逐事件。

3.6 系统自动添加的 Taint

Kubernetes 控制面在某些条件下会自动为 Node 添加 Taint,这些 Taint 的 Key 通常以 node.kubernetes.io/ 为前缀:

系统 Taint Key 触发条件 默认 Effect
node.kubernetes.io/not-ready 节点状态变为 NotReady NoExecute
node.kubernetes.io/unreachable 节点控制器无法访问节点 NoExecute
node.kubernetes.io/out-of-disk 节点磁盘空间不足 NoSchedule
node.kubernetes.io/memory-pressure 节点内存压力过高 NoSchedule
node.kubernetes.io/disk-pressure 节点磁盘 I/O 压力过高 NoSchedule
node.kubernetes.io/network-unavailable 节点网络不可用 NoSchedule
node.kubernetes.io/unschedulable 节点被标记为不可调度 NoSchedule
注意:系统自动添加的 Taint 通常会被 kube-controller-manager 自动管理。当节点恢复正常后,对应的 Taint 会被自动移除。不要手动删除这些系统 Taint,否则可能导致调度器做出错误决策。