深色模式
污点 Taint 与容忍 Toleration
摘要:本文面向生产 SRE / 平台工程师,系统讲解 taint(节点排斥)与 toleration(Pod 容忍)的协作机制、三种 effect 的运行时语义、
tolerationSeconds与内置故障污点的行为,并给出专用节点、GPU 隔离、节点排水等生产落地模式。适用 Kubernetes v1.28+。
适用版本与前提
- Kubernetes:v1.28+(基于污点的节点驱逐自 v1.18 稳定)
- 工具:
kubectl taint、kubectl cordon/drain - 前提:对目标节点有写权限(taint 修改需
updatenode 权限)
背景与问题
亲和性解决"把 Pod 吸引到哪些节点",而 taint 解决"把 Pod 排斥出哪些节点"。两者互补:用 taint 给节点打上"排斥标记",只有显式声明了对应 toleration 的 Pod 才被允许(或不被驱逐)。典型诉求:
- 专用节点:一组 GPU / 高内存节点只给特定团队用,避免被普通 Pod 占满。
- 隔离故障节点:节点 NotReady / 内存压力时,自动排斥并驱逐其上 Pod。
- 节点维护:临时标记节点不可调度并安全排空。
核心概念
一个 taint 由 key=value:effect 三段组成;一个 toleration 由 key/operator/value/effect/tolerationSeconds 描述匹配规则。
三种 effect:
| Effect | 对新建 Pod | 对已在运行 Pod |
|---|---|---|
NoSchedule | 不容忍则不调度到这里 | 不驱逐 |
PreferNoSchedule | 软约束,尽量不调度 | 不驱逐 |
NoExecute | 不容忍则不调度 | 立即驱逐;容忍可带 tolerationSeconds 宽限 |
记忆法
NoSchedule = "别新来";NoExecute = "现在就走"(除非你 tolerant 且带宽限);PreferNoSchedule = "最好别来"。
架构与原理
当一个 Pod 带有 tolerations,调度器按"过滤"逻辑处理:列出节点上所有 taint,忽略掉被 Pod toleration 匹配掉的;剩下的未忽略 taint 决定最终结果(见上表)。注意:多个 taint 之间是叠加过滤,不是取最严——只要还剩一个 NoSchedule 未被容忍,就无法调度。
匹配规则
toleration 与 taint 匹配需 key 相同、effect 相同,且:
operator: Exists:无需value,只要 key+effect 匹配即容忍;operator: Equal(默认):value也必须相等。
两个特例:
key为空 +operator: Exists:匹配所有 key 与 value(仍须effect匹配)。effect为空:匹配该 key 下的所有 effect。
生产实践一:专用 GPU 节点
bash
# 给 GPU 节点打 taint
kubectl taint nodes gpu-node-1 nvidia.com/gpu=true:NoSchedule1
2
2
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: trainer
spec:
replicas: 1
selector:
matchLabels:
app: trainer
template:
metadata:
labels:
app: trainer
spec:
tolerations:
- key: "nvidia.com/gpu"
operator: "Equal"
value: "true"
effect: "NoSchedule"
containers:
- name: trainer
image: trainer:1.0.0
resources:
limits:
nvidia.com/gpu: 11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
更省心的做法
使用 Extended Resource 表达 GPU,并启用 ExtendedResourceToleration admission controller:提交 resources.limits.nvidia.com/gpu 时,控制器会自动为 Pod 加上对应 toleration,无需手写。详见官方文档"Nodes with Special Hardware"用例。
生产实践二:节点维护与排水
bash
# 标记不可调度(等价于加 NoSchedule 类内部标记)
kubectl cordon node-07
# 安全驱逐(尊重 PDB,忽略 DaemonSet,清空 emptyDir)
kubectl drain node-07 --ignore-daemonsets --delete-emptydir-data --grace-period=1201
2
3
4
2
3
4
drain 内部会先 cordon,再驱逐 Pod。恢复:
bash
kubectl uncordon node-071
生产危险
kubectl drain 会真实驱逐业务 Pod。执行前确认:① 目标节点非控制面关键组件所在;② 已评估副本跨域冗余;③ 配合 kubectl get pdb 确认不会突破 PodDisruptionBudget。在共享/生产集群中应先小范围灰度。
生产实践三:tolerationSeconds 宽限驱逐
yaml
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 3001
2
3
4
5
2
3
4
5
当节点变为 Unreachable(如网络分区),默认 node.kubernetes.io/unreachable:NoExecute 会被加上。若 Pod 的 toleration 带 tolerationSeconds: 300,该 Pod 会在节点不可达 300 秒后才被驱逐——给网络抖动留出自愈窗口,避免误杀。
注意
控制面会对新增 taint 做速率限制,避免大规模节点同时不可达时引发雪崩式驱逐。这是有意的保护机制,不要为了提高"灵敏"去调高速率。
内置故障污点
以下 taint 由节点控制器 / kubelet 自动添加(稳定自 v1.18):
node.kubernetes.io/not-ready:节点未就绪(Ready=False)node.kubernetes.io/unreachable:节点不可达(Ready=Unknown)node.kubernetes.io/memory-pressure/disk-pressure/pid-pressurenode.kubernetes.io/network-unavailablenode.kubernetes.io/unschedulable
默认 not-ready 与 unreachable 带 NoExecute effect(含默认宽限,通常 300s,由 DefaultTolerationSeconds admission 控制)。
故障排查
bash
# 看节点上的 taint
kubectl describe node node-07 | grep -i taint
# 看 Pod 为何未被驱逐 / 未被调度
kubectl describe pod <pod> | grep -i -A3 taint
# 看污点导致的驱逐事件
kubectl get events --field-selector reason=TaintManagerEviction1
2
3
4
5
6
2
3
4
5
6
| 现象 | 根因 | 处理 |
|---|---|---|
Pod 不调度,had untolerated taint | 缺对应 toleration | 加 toleration 或 kubectl taint ...- 移除 |
| Pod 被驱逐 | 节点加了 NoExecute 且未容忍 | 加 tolerationSeconds 或 toleration |
| 驱逐过慢 | 默认宽限 300s | 调整 tolerationSeconds 或 DefaultTolerationSeconds |
回滚与清理
bash
# 移除某 taint(末尾加 '-')
kubectl taint nodes node-07 nvidia.com/gpu=true:NoSchedule-
# 验证已移除
kubectl describe node node-07 | grep -i taint1
2
3
4
2
3
4
安全与合规
- taint 只影响调度与驱逐,并不提供安全边界;隔离敏感负载必须用
Namespace+PodSecurity+NetworkPolicy+ 受限nodeName写入的 admission 控制。 system-*前缀的 PriorityClass 由系统保留(值 ≤ 10 亿区间之外),普通用户不应伪造。
性能、容量与成本
- taint 匹配是 O(taint 数 × toleration 数) 的轻量过滤,几乎不增加调度开销,可放心在大规模集群使用。
- 通过 taint 做专用节点池能显著提升硬件利用率(避免被低优 Pod 占满 GPU),是成本治理的关键手段。
替代方案与权衡
| 需求 | taint/toleration | 替代 |
|---|---|---|
| 排斥某类节点 | ✅ 本职 | nodeAffinity 的 NotIn |
| 专用硬件池 | ✅ + ExtendedResource | 手写 admission |
| 软排斥 | PreferNoSchedule | preferred nodeAffinity |
FAQ
Q:toleration 能保证 Pod "一定"调度到带 taint 的节点吗? A:不能。toleration 只解除"排斥",不提供"吸引"。要让 Pod 落到专用节点,还需配合 nodeAffinity/nodeSelector(官方"Dedicated Nodes"用例即如此)。
Q:移除 taint 后正在运行的 Pod 会怎样? A:无影响;只在新增 taint 时 NoExecute 才会触发驱逐逻辑。
参考资料
- Kubernetes 官方文档 - Taints and Tolerations,访问日期:2026-10-08。
- Kubernetes 官方文档 - Assigning Pods to Nodes,访问日期:2026-10-08。
- Kubernetes 官方文档 - Kubernetes Scheduler,访问日期:2026-10-08。