主题
第 3 章:Tolerations 容忍详解
3.1 Toleration 的完整字段结构
Toleration 定义在 Pod 的 spec.tolerations 中,完整字段如下:
yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
tolerations:
- key: "dedicated" # 要匹配的污点 key
operator: "Equal" # 运算符:Equal(默认)或 Exists
value: "gpu" # 仅 Equal 时有效;Exists 时必须省略
effect: "NoSchedule" # 要匹配的污点 effect;省略表示匹配所有 effect
tolerationSeconds: 3600 # 仅对 NoExecute 有效:被驱逐前可存活的秒数
containers:
- name: app
image: nginx3.2 匹配规则(核心!)
一个 Toleration 能"容忍"一个 Taint,需满足:
- key 相同
- effect 相同(或 toleration 省略 effect,匹配所有 effect)
- value 匹配:
operator: Equal→ toleration 的 value 必须等于 taint 的 value(默认值,此时 value 省略等价于空字符串)operator: Exists→ 不关心 value,只要 key 存在即匹配(此时不能写 value)
匹配示例速查表
节点污点:dedicated=gpu:NoSchedule
| Toleration 写法 | 是否匹配 | 说明 |
|---|---|---|
key: dedicated, operator: Equal, value: gpu, effect: NoSchedule | ✅ | 完全匹配(标准写法) |
key: dedicated, operator: Exists, effect: NoSchedule | ✅ | Exists 忽略 value |
key: dedicated, operator: Exists(无 effect) | ✅ | 匹配该 key 的所有 effect |
key: dedicated, operator: Equal, value: cpu, effect: NoSchedule | ❌ | value 不相等 |
key: dedicated, operator: Equal, value: gpu(无 effect) | ✅ | 省略 effect 匹配所有 effect |
key: dedicated, operator: Equal, value: gpu, effect: NoExecute | ❌ | effect 不匹配 |
空的 toleration {}(key、effect 都省略 + Exists) | ✅ 匹配一切 | 容忍所有污点(慎用!) |
"万能容忍"(危险但有用)
yaml
tolerations:
- operator: "Exists" # key、value、effect 全省略 = 容忍所有污点常见于:监控 Agent、日志采集等需要"无处不在"的 DaemonSet。业务 Pod 不要这么写,会绕过所有节点隔离保护。
3.3 operator 详解
Equal(默认值)
yaml
tolerations:
- key: "dedicated"
operator: "Equal" # 可省略,默认就是 Equal
value: "gpu"
effect: "NoSchedule"精确匹配 dedicated=gpu:NoSchedule。
Exists
yaml
tolerations:
- key: "dedicated"
operator: "Exists"
effect: "NoSchedule"匹配 key 为 dedicated、effect 为 NoSchedule 的污点,不管 value 是什么(dedicated=gpu、dedicated=cpu 都匹配)。
⚠️ 使用 Exists 时写 value 会报错:
value must be empty when operator is Exists。
3.4 effect 省略的含义
yaml
tolerations:
- key: "dedicated"
operator: "Exists"
# 没有 effect 字段匹配 key 为 dedicated 的所有污点,无论 effect 是 NoSchedule、PreferNoSchedule 还是 NoExecute。
特例:如果 key 也省略、operator 为 Exists,则容忍一切污点(3.2 节的"万能容忍")。
3.5 tolerationSeconds —— NoExecute 专属
tolerationSeconds 只在 effect 为 NoExecute 时有效(其他 effect 写了也没意义),表示:节点被加上 NoExecute 污点后,Pod 还能继续存活多少秒才被驱逐。
yaml
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 300 # 节点失联后,Pod 最多再活 300 秒- 不设置 → 永久容忍(永远不被该污点驱逐)。
- 设置为 0 → 立即驱逐(等同没有容忍)。
- 典型用途:有状态应用希望节点短暂故障时不要立刻被赶走(避免不必要的迁移抖动),故障持续超过阈值再迁移。
K8s 自动添加的默认容忍
从 1.6 起,API Server 的 DefaultTolerationSeconds 准入控制器会自动给每个 Pod 添加:
yaml
tolerations:
- key: "node.kubernetes.io/not-ready"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 300
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 300这就是为什么节点宕机后,上面的 Pod 默认 5 分钟才被驱逐重建。你可以在自己的 Pod spec 里显式覆盖这两个容忍来缩短/延长这个时间(详见第 4 章)。
3.6 在各类工作负载中配置容忍
Deployment
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gpu-app
spec:
replicas: 3
selector:
matchLabels:
app: gpu-app
template:
metadata:
labels:
app: gpu-app
spec:
tolerations: # 写在 Pod template 的 spec 里
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
containers:
- name: app
image: mygpuapp:latestDaemonSet
DaemonSet 通常需要跑在所有节点(包括 Master),所以系统自动给它加一堆容忍(见第 4 章),手动也可以补充:
yaml
spec:
template:
spec:
tolerations:
- key: "dedicated"
operator: "Exists"
effect: "NoSchedule"Job / CronJob / StatefulSet
同理,都写在 spec.template.spec.tolerations 中,不再赘述。
3.7 一个常见误区:容忍 ≠ 定向调度
yaml
# ❌ 错误认知:加了容忍,Pod 就会调度到 GPU 节点
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"这个 Pod 只是"可以"去 GPU 节点,调度器也可能把它放到普通节点!如果业务要求"必须在 GPU 节点",要加 nodeAffinity:
yaml
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: dedicated
operator: In
values: ["gpu"]
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"口诀:NodeAffinity 负责"吸引"(往哪儿去),Taint/Toleration 负责"排斥"(谁能来)。专用节点方案 = 节点打 label + 打污点,Pod 配 nodeAffinity + toleration。 详见第 6 章。
本章小结
- Toleration 五字段:key / operator(Equal|Exists) / value / effect / tolerationSeconds。
- Exists 忽略 value 且不能写 value;effect 省略 = 匹配所有 effect;全省略 + Exists = 容忍一切。
- tolerationSeconds 只对 NoExecute 有效,控制延迟驱逐时长。
- K8s 默认给 Pod 加 not-ready/unreachable 的 300 秒容忍。
- 容忍只是通行证,定向调度要配 nodeAffinity。
动手练习
- 写两个 Pod:一个用 Equal 精确容忍,一个用 Exists 容忍,验证它们都能调度到打了
dedicated=gpu:NoSchedule的节点。 - 给一个运行中的 Pod 所在节点打 NoExecute 污点,对比"无容忍 / 容忍但 tolerationSeconds=30 / 永久容忍"三种 Pod 的不同命运。
kubectl get pod <任意pod> -o yaml | grep -A12 tolerations,观察系统自动注入的默认容忍。