在 Kubernetes 集群中,节点(Node)是运行 Pod 的载体。默认情况下,Pod 会被调度到任意可用节点,但实际场景中,我们可能需要对节点进行“特殊管控”——比如某些节点只允许特定 Pod 运行,或者拒绝所有普通 Pod 运行。这就需要用到 Kubernetes 中的污点(Taints)容忍(Tolerations) 机制。

一、什么是污点和容忍?

1. 污点(Taints):节点的“排斥标签”

污点是添加在节点上的“排斥规则”,用于阻止 Pod 被调度到该节点。如果一个节点被添加了污点,默认情况下,所有 Pod 都会被这个节点“排斥”,无法调度到该节点上。

污点的核心作用是保护节点,让节点只接受“被允许”的 Pod。例如:

  • 给_master 节点添加污点,避免普通 Pod 占用 master 资源;
  • 给带有特殊硬件(如 GPU)的节点添加污点,只允许需要 GPU 的 Pod 调度过来。

2. 容忍(Tolerations):Pod 的“准入许可”

容忍是添加在Pod上的“允许规则”,用于表示该 Pod 可以“容忍”节点上的某些污点。如果一个 Pod 对节点的污点有容忍,那么这个节点就会允许该 Pod 调度到自己身上。

容忍的核心作用是让 Pod 获得进入特定节点的权限,与节点的污点形成“匹配机制”。

要点知识:污点(Taints)是节点的“主动排斥”,容忍(Tolerations)是 Pod 的“被动接受”。只有当 Pod 的容忍与节点的污点匹配时,Pod 才有可能被调度到该节点(还需满足其他调度条件)。

二、污点的组成与类型

1. 污点的组成结构

一个污点由三部分组成,格式为:key=value:effect,其中:

  • key:污点的名称(字符串,如 node-role.kubernetes.io/master);
  • value:污点的附加信息(字符串,可选,可空);
  • effect:污点的“作用效果”,决定了如何排斥 Pod,是污点的核心。

2. 污点的三种作用效果(effect)

effect 类型 作用说明
NoSchedule 仅影响调度决策,不影响已运行在节点上的 Pod。即:
- 新 Pod 若没有容忍,无法调度到该节点;
- 已运行的 Pod 不受影响,会继续留在节点上。
NoExecute 既影响调度决策,也影响已运行的 Pod。即:
- 新 Pod 若没有容忍,无法调度到该节点;
- 已运行的 Pod 若没有容忍,会被从节点上驱逐。
PreferNoSchedule 调度器会“尽量避免”将没有容忍的 Pod 调度到该节点,但不是绝对禁止(属于“软限制”)。

例如:key=gpu:NoSchedule 表示:带有 key=gpu 污点且作用为 NoSchedule 的节点,会拒绝所有没有对应容忍的新 Pod 调度,但已在节点上的 Pod 可以继续运行。

三、容忍的配置规则

Pod 的容忍需要与节点的污点“匹配”才能生效。容忍的配置格式在 Pod 的 spec.tolerations 中,主要包含以下字段:

  • key:要容忍的污点的 key(需与节点污点的 key 一致);
  • value:要容忍的污点的 value(需与节点污点的 value 一致,可选,若不指定则匹配任意 value);
  • operator:匹配方式(EqualExists);
    • Equal:默认值,要求 keyvalue 都与污点完全匹配;
    • Exists:只需 key 与污点匹配,忽略 value(即容忍所有 key 为指定值的污点,无论 value 是什么);
  • effect:要容忍的污点的 effect(需与节点污点的 effect 一致,可选,若不指定则容忍所有 effect)。

常见容忍配置示例

假设节点有一个污点:key=example:NoSchedule,则以下 Pod 容忍均可匹配:

  1. 完全匹配(operator=Equal):
tolerations:
- key: "example"
  value: "key"  # 与污点的 value 一致(若污点 value 为空,这里也需为空)
  operator: "Equal"
  effect: "NoSchedule"  # 与污点的 effect 一致
  1. 只匹配 key(operator=Exists):
tolerations:
- key: "example"
  operator: "Exists"  # 忽略 value,只要 key 匹配即可
  effect: "NoSchedule"
  1. 匹配所有 effect(不指定 effect):
tolerations:
- key: "example"
  operator: "Exists"
  # 不指定 effect,即容忍该 key 下所有 effect 的污点(NoSchedule、NoExecute 等)
  1. 匹配所有污点(万能容忍,不推荐在生产环境使用):
tolerations:
- operator: "Exists"  # 不指定 key,匹配所有污点

要点知识:容忍只是让 Pod“不被节点排斥”,但不保证 Pod 一定会被调度到该节点。Pod 最终调度到哪个节点,还需满足节点资源充足、标签选择器匹配等其他条件。

四、实战:污点与容忍的配置步骤

环境准备

假设集群中有两个节点:node-1(普通节点)和 node-2(计划设置为“专用节点”)。

步骤 1:给节点添加污点

node-2 添加一个 key=special:NoSchedule 的污点,拒绝没有容忍的 Pod 调度:

kubectl taint nodes node-2 special=key:NoSchedule

查看节点污点(检查是否添加成功):

kubectl describe node node-2 | grep Taint

输出类似:

Taints:             special=key:NoSchedule

步骤 2:创建没有容忍的 Pod

创建一个普通 Pod(normal-pod.yaml):

apiVersion: v1
kind: Pod
metadata:
  name: normal-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.23

创建 Pod:

kubectl apply -f normal-pod.yaml

查看 Pod 调度结果:

kubectl get pod normal-pod -o wide

结果:Pod 会被调度到 node-1(因为 node-2 有污点,而该 Pod 没有容忍)。

步骤 3:创建有容忍的 Pod

创建一个带有容忍的 Pod(tolerant-pod.yaml),容忍 node-2 的污点:

apiVersion: v1
kind: Pod
metadata:
  name: tolerant-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.23
  tolerations:  # 添加容忍配置
  - key: "special"
    value: "key"
    operator: "Equal"
    effect: "NoSchedule"

创建 Pod:

kubectl apply -f tolerant-pod.yaml

查看 Pod 调度结果:

kubectl get pod tolerant-pod -o wide

结果:Pod 可以被调度到 node-2(因为容忍匹配了 node-2 的污点)。

步骤 4:测试 NoExecute 效果(可选)

node-2 添加一个 NoExecute 污点:

kubectl taint nodes node-2 special=key:NoExecute --overwrite  # --overwrite 覆盖原有污点

此时,查看 normal-pod(如果之前调度到 node-2 会被驱逐,但在本案例中它在 node-1,不受影响),而 tolerant-pod 因为有容忍,会继续留在 node-2

步骤 5:移除节点污点

如果需要取消节点的排斥规则,可以移除污点:

kubectl taint nodes node-2 special:NoSchedule-  # 末尾加“-”表示移除该污点
kubectl taint nodes node-2 special:NoExecute-

五、常见使用场景

  1. 保护 master 节点
    Kubernetes 集群的 master 节点默认被添加了 node-role.kubernetes.io/master:NoSchedule 污点,避免普通 Pod 调度到 master 上,保证 master 节点的稳定性。只有 kube-system 命名空间的系统组件(如 kube-proxy)因为有对应的容忍,才能运行在 master 上。

  2. 专用节点(如 GPU 节点)
    给带有 GPU 的节点添加污点(如 gpu=true:NoSchedule),然后给需要使用 GPU 的 Pod 配置对应容忍,确保 GPU 资源只被特定 Pod 使用,避免资源浪费。

  3. 节点维护时驱逐 Pod
    当需要维护节点(如升级内核)时,可以给节点添加 NoExecute 污点,此时没有容忍的 Pod 会被自动驱逐到其他节点,实现“优雅下线”。

  4. 基于节点状态的动态调度
    Kubernetes 某些插件(如 node-problem-detector)会根据节点状态(如磁盘压力、内存压力)自动添加污点(如 node.kubernetes.io/disk-pressure:NoSchedule),避免将 Pod 调度到状态异常的节点。

要点知识:污点和容忍是“节点主动排斥,Pod 被动适应”的机制,核心用途是控制 Pod 与节点的调度关系,实现资源的精细化管理。

六、注意事项

  1. NoExecute 污点的驱逐行为
    当节点添加 NoExecute 污点时,已运行的 Pod 若没有容忍,会被立即驱逐;若 Pod 有 tolerationSeconds 字段(可选),则会等待指定秒数后再驱逐(例如:tolerationSeconds: 300 表示等待 5 分钟)。

  2. 污点的优先级
    一个节点可以有多个污点,Pod 只需容忍其中“阻碍调度的污点”即可。例如:节点有两个污点 A:NoScheduleB:NoSchedule,Pod 只要容忍 AB,就不会被 AB 排斥(但需注意:若两个污点都阻碍调度,Pod 需同时容忍才能调度)。

  3. 避免过度使用“万能容忍”
    operator: Exists 且不指定 key 的容忍(tolerations: [{operator: "Exists"}])会匹配所有污点,可能导致 Pod 被调度到不合适的节点(如 master 节点、状态异常的节点),生产环境需谨慎使用。

  4. 与节点亲和性的区别
    污点和容忍是“节点排斥 Pod,Pod 被动容忍”;而节点亲和性是“Pod 主动选择节点”(如 Pod 声明“只运行在带有 gpu=true 标签的节点上”)。两者可以配合使用,实现更灵活的调度策略。


Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐