什么是 Taints (污点) 和 Tolerations (容忍度)?
在 Kubernetes 中,Taints(污点) 和 Tolerations(容忍度) 是一对协同工作的机制,用于控制 Pod(容器组) 如何被调度到 Node(节点) 上。
用一句话概括:Taints 是 Node 拒绝 Pod 的属性,而 Tolerations 是 Pod以此能够进入该 Node 的“通行证”。
以下是详细的通俗解释和技术细节:
1. 核心概念与比喻
为了方便理解,我们可以打个比方:
- Taint (污点) -> “生化禁区”标识
- 这是打在 Node(节点) 上的。
- 这就好比在一个房间门口贴了张条子:“这里有毒气,严禁入内”。默认情况下,没有任何人(Pod)愿意进去。
- Toleration (容忍度) -> “防毒面具”
- 这是定义在 Pod 上的。
- 如果一个 Pod 佩戴了对应的“防毒面具”(配置了 Toleration),它就可以无视那个警告,进入那个房间。
关键点: 它们的主要作用是 “排斥”。Taint 使得 Node 排斥没有对应 Toleration 的 Pod。
2. Taint (污点) - Node 端
当你在一个节点上设置了 Taint,你是在告诉调度器:“除非 Pod 明确表示能容忍这个污点,否则不要把 Pod 放到我这里。”
一个 Taint 包含三个部分:Key=Value:Effect
- Key: 污点的键(例如
special-hardware)。 - Value: 污点的值(例如
gpu)。 - Effect: 污点产生的效果(这是最重要的部分)。
Effect 的三种类型:
NoSchedule: 严禁调度。如果 Node 有这个污点,新的 Pod 只要没有对应的 Toleration,就绝对不会被调度上来。但已经运行在该节点上的 Pod 不受影响。PreferNoSchedule: 尽量不调度。这是软策略。Kubernetes 会尽量避免把没有 Toleration 的 Pod 调度上来,但如果集群资源非常紧张,实在没地方去了,也可以勉强调度上来。NoExecute: 驱逐。这是最强的策略。- 新的 Pod 没 Toleration 进不来。
- 正在运行的 Pod 如果没有对应的 Toleration,会被立刻踢出(Evict)该节点。
3. Toleration (容忍度) - Pod 端
Toleration 是 Pod 的属性,声明它“可以接受”某种 Taint。
在 Pod 的 YAML 文件中,你需要配置 Toleration 来匹配 Node 上的 Taint。匹配规则主要看 Key、Value 和 Effect。
示例 YAML:
apiVersion: v1
kind: Pod
metadata:
name: my-gpu-pod
spec:
containers:
- name: my-container
image: nginx
tolerations:
- key: "special-hardware" # 匹配 Node 污点的 Key
operator: "Equal" # 匹配方式 (Equal 或 Exists)
value: "gpu" # 匹配 Node 污点的 Value
effect: "NoSchedule" # 匹配 Node 污点的 Effect
- Operator:
Equal: Key 和 Value 必须完全匹配。Exists: 只要 Key 存在即可,不关心 Value 是什么(相当于通配符)。
4. 常见使用场景
场景一:专用节点(Dedicated Nodes)
假设你买了几台非常昂贵的 GPU 机器,你只希望运行 AI 计算任务的 Pod 跑在上面,不希望普通的 Web 服务(如 Nginx)占用资源。
- 做法: 给 GPU 节点打上 Taint
gpu=true:NoSchedule。 - 结果: 普通 Pod 进不来;只有配置了 Toleration 的 AI 任务 Pod 才能调度上去。
场景二:节点维护
管理员需要对某个节点进行升级或维修。
- 做法:
kubectl drain <node-name>命令会自动给节点打上NoSchedule甚至NoExecute的 Taint。 - 结果: 新 Pod 进不来,旧 Pod 被赶走,节点变空,可以安全维护。
场景三:Master/Control-plane 节点保护
Kubernetes 默认会给 Master 节点打上 Taint。
- 原因: 防止用户的业务 Pod 抢占了 Master 节点的资源,导致集群管理组件崩溃。
- 结果: 只有系统级的组件(或者你特意配置了 Toleration 的 Pod)才能跑在 Master 上。
场景四:基于节点状态的自动驱逐
当节点出现问题(如磁盘满了、内存不够了、网络断了),Kubernetes 控制器会自动给节点打上 Taint(例如 node.kubernetes.io/memory-pressure)。
- 结果: 调度器停止向该节点发送新 Pod,甚至驱逐现有 Pod。
5. Taints 与 Node Affinity (节点亲和性) 的区别
这是初学者最容易混淆的地方:
- Node Affinity (亲和性) 是 “吸引”。
- Pod 说:“我想去那个节点(因为它有 SSD)。”
- Taints/Tolerations (污点/容忍) 是 “排斥”。
- Node 说:“我拒绝所有 Pod,除非你有通行证。”
最佳实践:
如果你想让某些 Pod 独占 某些节点,通常需要两者结合使用:
- 用 Taint 阻止其他不相关的 Pod 进来。
- 用 Node Affinity 确保你的 Pod 能够被吸引到这些特定的节点上。
总结
- Taint 是 Node 上的“锁”,用来拒绝 Pod。
- Toleration 是 Pod 上的“钥匙”,用来打开 Node 的锁。
- 它们共同保证了 Pod 不会被调度到不合适的节点上(例如普通应用不调度到 GPU 节点,或者业务应用不调度到故障节点)。