主题
第 2 章:Taints 污点详解
2.1 污点的数据结构
污点定义在 Node 对象的 spec.taints 中,每个污点由三部分组成:
key=value:effectyaml
apiVersion: v1
kind: Node
metadata:
name: node1
spec:
taints:
- key: "dedicated" # 键:1-63 字符,可带 DNS 前缀如 example.com/dedicated
value: "gpu" # 值:可选,0-63 字符
effect: "NoSchedule" # 效果:NoSchedule / PreferNoSchedule / NoExecute- key 必填,命名规则与 label 相同。
- value 可省略:
kubectl taint nodes node1 key1:NoSchedule是合法的(此时容忍端通常用Exists运算符匹配)。 - 同一个节点可以有多个污点,key+effect 组合唯一。
2.2 kubectl taint 命令大全
添加污点
bash
# 完整形式:key=value:effect
kubectl taint nodes node1 dedicated=gpu:NoSchedule
# 不带 value
kubectl taint nodes node1 maintenance:NoSchedule
# 给所有节点打污点(谨慎!)
kubectl taint nodes --all env=prod:NoSchedule
# 按 label 选择器批量打污点
kubectl taint nodes -l hardware=gpu dedicated=gpu:NoSchedule
# 覆盖已存在的同 key+effect 污点
kubectl taint nodes node1 dedicated=gpu:NoSchedule --overwrite查看污点
bash
# 方式一:describe(最直观)
kubectl describe node node1 | grep -A5 Taints
# 方式二:jsonpath(适合脚本)
kubectl get node node1 -o jsonpath='{.spec.taints}'
# 查看集群所有节点的污点
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints删除污点
bash
# 删除指定 key+effect 的污点(注意末尾的减号)
kubectl taint nodes node1 dedicated=gpu:NoSchedule-
# 删除该 key 的所有 effect 污点
kubectl taint nodes node1 dedicated:NoSchedule- # 只删 NoSchedule 效果
kubectl taint nodes node1 dedicated- # 删除 key 为 dedicated 的所有污点
# 删除所有节点上的污点
kubectl taint nodes --all dedicated-⚠️ 删除语法是新手最易错点:减号
-紧跟在 effect(或 key)之后,中间不能有空格。
修改污点
污点没有"原地修改"命令,用 --overwrite 重新打,或先删后加:
bash
kubectl taint nodes node1 dedicated=gpu:PreferNoSchedule --overwrite2.3 三种 Effect 深入对比
2.3.1 NoSchedule —— 硬调度约束
- 新 Pod 没有对应容忍 → 绝不调度到该节点。
- 已在节点上运行的 Pod 不受影响,继续运行。
bash
kubectl taint nodes node1 dedicated=backend:NoSchedule典型场景:Master 节点保护(K8s 默认给 control-plane 打 node-role.kubernetes.io/control-plane:NoSchedule)、专用节点池。
2.3.2 PreferNoSchedule —— 软调度约束
- 调度器尽量避免把没有容忍的 Pod 调度上来,但实在没地方去时仍会调度上来。
- 这是"柔性"版本,用于不希望硬隔离、只做倾向性引导的场景。
bash
kubectl taint nodes node1 env=staging:PreferNoSchedule常见误区:以为 PreferNoSchedule 能完全挡住 Pod。它挡不住,集群资源紧张时 Pod 照样会上来。
2.3.3 NoExecute —— 调度约束 + 驱逐
最强力的效果,两层作用:
- 调度层面:等同于 NoSchedule,没容忍的新 Pod 不能上来。
- 驱逐层面:已经在该节点运行、且没有对应容忍的 Pod 会被驱逐(Evict)。
bash
kubectl taint nodes node1 maintenance=true:NoExecute
# 结果:node1 上没有容忍此污点的 Pod 会被立即驱逐,重新调度到其他节点配合 Pod 容忍里的 tolerationSeconds 字段,还可以实现"延迟驱逐"(见第 3、4 章)。
2.4 驱逐过程详解(NoExecute)
管理员执行:kubectl taint nodes node1 maintenance:NoExecute
│
▼
┌──────────────────┐
│ node1 上的 Pod │
│ 逐个检查容忍 │
└──────────────────┘
│ │
│ 无容忍 │ 有容忍
▼ ▼
立即驱逐 ┌─────────────────────┐
(Evicted) │ tolerationSeconds? │
│ 未设置 → 永久容忍 │
│ = 300 → 300秒后驱逐 │
└─────────────────────┘被驱逐的 Pod 状态变为 Failed,原因 Evicted;如果由 Deployment 管理,控制器会在其他节点重建新副本。
2.5 多污点叠加:AND 语义
节点上的多个污点之间是"与(AND)"关系:Pod 必须容忍节点上的每一个污点,才能调度上来。
bash
kubectl taint nodes node1 dedicated=gpu:NoSchedule
kubectl taint nodes node1 team=ai:NoSchedulePod 需要同时容忍 dedicated=gpu:NoSchedule 和 team=ai:NoSchedule 才能调度到 node1。
注意:Pod 的容忍可以比节点的污点多(多余的容忍无害),但不能少。
2.6 污点的命名规范建议
| 前缀/键 | 用途 |
|---|---|
node-role.kubernetes.io/control-plane | 控制面节点(内置) |
node.kubernetes.io/* | K8s 内置污点(not-ready、unreachable 等,见第 4 章) |
自定义如 dedicated、team、hardware | 业务自定义,建议加公司域名前缀如 example.com/dedicated 避免冲突 |
本章小结
- 污点格式
key=value:effect,value 可省略,effect 三选一。 kubectl taint增删查:删除用结尾减号-。- NoSchedule 硬拒、PreferNoSchedule 软拒、NoExecute 硬拒 + 驱逐。
- 多污点是 AND 关系,Pod 必须全部容忍。
动手练习
- 给一个节点打
NoSchedule污点,部署一个 3 副本的 Deployment(不带容忍),观察 Pod 的分布和 Pending 情况。 - 把污点改为
NoExecute,观察该节点上原有 Pod 被驱逐的过程(kubectl get pods -o wide -w)。 - 练习删除污点,验证 Pod 恢复正常调度。