【Kubernetes】污点(Taints)与容忍(Tolerations):节点调度的“门禁系统”
污点是添加在节点上的“排斥规则”,用于阻止 Pod 被调度到该节点。如果一个节点被添加了污点,默认情况下,所有 Pod 都会被这个节点“排斥”,无法调度到该节点上。污点的核心作用是保护节点,让节点只接受“被允许”的 Pod。给_master 节点添加污点,避免普通 Pod 占用 master 资源;给带有特殊硬件(如 GPU)的节点添加污点,只允许需要 GPU 的 Pod 调度过来。
在 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
:匹配方式(Equal
或Exists
);Equal
:默认值,要求key
和value
都与污点完全匹配;Exists
:只需key
与污点匹配,忽略value
(即容忍所有 key 为指定值的污点,无论 value 是什么);
effect
:要容忍的污点的 effect(需与节点污点的 effect 一致,可选,若不指定则容忍所有 effect)。
常见容忍配置示例
假设节点有一个污点:key=example:NoSchedule
,则以下 Pod 容忍均可匹配:
- 完全匹配(
operator=Equal
):
tolerations:
- key: "example"
value: "key" # 与污点的 value 一致(若污点 value 为空,这里也需为空)
operator: "Equal"
effect: "NoSchedule" # 与污点的 effect 一致
- 只匹配 key(
operator=Exists
):
tolerations:
- key: "example"
operator: "Exists" # 忽略 value,只要 key 匹配即可
effect: "NoSchedule"
- 匹配所有 effect(不指定 effect):
tolerations:
- key: "example"
operator: "Exists"
# 不指定 effect,即容忍该 key 下所有 effect 的污点(NoSchedule、NoExecute 等)
- 匹配所有污点(万能容忍,不推荐在生产环境使用):
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-
五、常见使用场景
-
保护 master 节点
Kubernetes 集群的 master 节点默认被添加了node-role.kubernetes.io/master:NoSchedule
污点,避免普通 Pod 调度到 master 上,保证 master 节点的稳定性。只有 kube-system 命名空间的系统组件(如 kube-proxy)因为有对应的容忍,才能运行在 master 上。 -
专用节点(如 GPU 节点)
给带有 GPU 的节点添加污点(如gpu=true:NoSchedule
),然后给需要使用 GPU 的 Pod 配置对应容忍,确保 GPU 资源只被特定 Pod 使用,避免资源浪费。 -
节点维护时驱逐 Pod
当需要维护节点(如升级内核)时,可以给节点添加NoExecute
污点,此时没有容忍的 Pod 会被自动驱逐到其他节点,实现“优雅下线”。 -
基于节点状态的动态调度
Kubernetes 某些插件(如node-problem-detector
)会根据节点状态(如磁盘压力、内存压力)自动添加污点(如node.kubernetes.io/disk-pressure:NoSchedule
),避免将 Pod 调度到状态异常的节点。
要点知识:污点和容忍是“节点主动排斥,Pod 被动适应”的机制,核心用途是控制 Pod 与节点的调度关系,实现资源的精细化管理。
六、注意事项
-
NoExecute 污点的驱逐行为
当节点添加NoExecute
污点时,已运行的 Pod 若没有容忍,会被立即驱逐;若 Pod 有tolerationSeconds
字段(可选),则会等待指定秒数后再驱逐(例如:tolerationSeconds: 300
表示等待 5 分钟)。 -
污点的优先级
一个节点可以有多个污点,Pod 只需容忍其中“阻碍调度的污点”即可。例如:节点有两个污点A:NoSchedule
和B:NoSchedule
,Pod 只要容忍A
或B
,就不会被A
或B
排斥(但需注意:若两个污点都阻碍调度,Pod 需同时容忍才能调度)。 -
避免过度使用“万能容忍”
operator: Exists
且不指定 key 的容忍(tolerations: [{operator: "Exists"}]
)会匹配所有污点,可能导致 Pod 被调度到不合适的节点(如 master 节点、状态异常的节点),生产环境需谨慎使用。 -
与节点亲和性的区别
污点和容忍是“节点排斥 Pod,Pod 被动容忍”;而节点亲和性是“Pod 主动选择节点”(如 Pod 声明“只运行在带有gpu=true
标签的节点上”)。两者可以配合使用,实现更灵活的调度策略。
更多推荐
所有评论(0)