K8s 污点与容忍实战:Pod调度的高级玩法

261 阅读3分钟

一、前言:Node 不是你想上就能上

在 Kubernetes 中,Pod 默认会被调度器随机分配到集群中满足资源条件的节点上。但有些节点是我们不希望普通工作负载随意调度过去的,比如:

  • 专属 GPU 节点
  • 高风险测试节点
  • 存储密集型节点
  • 预留给系统级组件的节点(如 kube-proxy、CoreDNS)

这时候,仅靠 Node Affinity 还不够,因为 Affinity 是**“想去哪儿” ,而不是“不能去哪儿”**。

所以就需要 Kubernetes 提供的Taints(污点)与 Tolerations(容忍)机制,它们是调度控制的“防守型”策略。


二、基本概念:什么是 Taints 与 Tolerations?

名称作用说明
Taint(污点)加在 Node 上,用于拒绝调度普通 Pod
Toleration(容忍)加在 Pod 上,用于允许调度到带有特定污点的 Node 上

简单理解就是:

节点上贴上“我不欢迎你”的标签(taint),只有带“通行证”的 Pod(toleration)才能进去。


三、Taint 配置语法与示例

kubectl taint nodes node1 key=value:NoSchedule

该命令给 node1 添加一个 taint,含义是:

  • key=value 是识别这个污点的标识;
  • NoSchedule 表示 不允许 没有容忍这个污点的 Pod 被调度上来。

Taint 有三种 effect:

Effect含义
NoSchedule明确禁止没有容忍的 Pod 被调度到此节点
PreferNoSchedule尽量避免调度,非强制(调度器会尽量不选,但可以选)
NoExecute不仅不调度,还会驱逐当前没有容忍的 Pod(驱逐机制)

四、Toleration 配置示例

在 Pod 或 Deployment 中加 tolerations:

tolerations:
- key: "key"
  operator: "Equal"
  value: "value"
  effect: "NoSchedule"

这表示该 Pod 容忍了 key=value:NoSchedule 的污点,可以被调度到该 Node。

operator 的两种值:

  • Equal:key/value 必须匹配
  • Exists:只要 key 存在就可以,不关心 value

五、实战应用场景详解

1️⃣ GPU 节点隔离调度

只允许特定模型训练任务调度到 GPU 节点:

kubectl taint nodes gpu-node gpu=true:NoSchedule

然后为模型训练的 Pod 加 toleration:

tolerations:
- key: "gpu"
  operator: "Equal"
  value: "true"
  effect: "NoSchedule"

✅ 普通业务 Pod 无法调度到 GPU 节点
✅ 模型训练任务独享 GPU,避免干扰


2️⃣ 节点维护时驱逐业务 Pod

维护一个节点前,给其打上如下 taint:

kubectl taint node node2 maintenance=true:NoExecute

这会立即驱逐所有没有对应容忍的 Pod!

如果你希望某些系统组件(如监控 Agent)依然能待在此节点,可以加上:

tolerations:
- key: "maintenance"
  operator: "Equal"
  value: "true"
  effect: "NoExecute"
  tolerationSeconds: 3600

tolerationSeconds 表示容忍时长,超时仍会被驱逐。


3️⃣ 与 Affinity 联合调度控制

Taint 是限制调度、Affinity 是引导调度。

比如你想让日志收集 Pod:

  • 只运行在 node-role=logging 的节点;
  • 这些节点对普通 Pod 有污点保护;

你可以这样做:

  1. 给节点打 taint:
kubectl taint nodes log-node log-role=true:NoSchedule
  1. Pod 中加 toleration + affinity:
tolerations:
- key: "log-role"
  operator: "Equal"
  value: "true"
  effect: "NoSchedule"

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: node-role
          operator: In
          values:
          - logging

两者结合,实现了精准的调度意图。


六、常见误区与调试技巧

❌ 误区一:加了 toleration 就一定能调度上去?

不一定。Toleration 只是让 Pod 能“通过门禁”,但最终能不能调度上,还得满足资源条件、NodeSelector、Affinity 等条件。

❌ 误区二:污点没删除,Pod 为什么又调度上来了?

说明 Pod 有匹配的 toleration,或者是 PreferNoSchedule 类型污点,非强制。

✅ 调试技巧:

  • 查看节点 taint:
kubectl describe node <node-name>
  • 查看 Pod 调度失败原因:
kubectl describe pod <pod-name>

关注 Events 信息,调度失败原因会清晰提示。


七、总结:Taint 和 Toleration 是什么样的人设?

如果把调度器比作派送快递的小哥:

  • Taint 是收件人门口贴的告示:“非本小区禁止入内”;
  • Toleration 是你出示的证件:“我是物业授权的快递”;
  • Affinity 是你导航设置的“优先派送到xx小区”。

只有合理使用这三种手段,才能构建出真正稳定、可控的 Kubernetes 集群调度体系。