在 Kubernetes 中,污点(Taint) 和 容忍(Toleration) 是用于控制 Pod 调度到特定节点的重要机制。污点允许节点拒绝某些 Pod 的调度,而容忍则允许 Pod 忽略节点的污点,从而调度到特定节点上。
1. 污点(Taint)
1.1.污点的作用
污点是节点上的一个标记,用于限制哪些 Pod 可以调度到该节点。通常用于以下场景:
- 专用节点:某些节点专门用于运行特定类型的 Pod(如 GPU 节点)。
- 节点维护:标记节点为不可调度状态,以便进行维护。
- 故障隔离:将故障节点标记为不可调度,避免 Pod 调度到该节点。
1.2.污点的组成
每个污点由以下三部分组成:
- Key: 污点的键(必填)。
- Value: 污点的值(可选)。
- Effect : 污点的效果(必填),有以下三种:
NoSchedule
: 禁止调度新的 Pod 到该节点(已运行的 Pod 不受影响)。PreferNoSchedule
: 尽量不调度新的 Pod 到该节点(非强制)。NoExecute
: 禁止调度新的 Pod 到该节点,并且驱逐已运行但不满足容忍的 Pod。
1.3.污点的配置
通过 kubectl taint
命令为节点添加污点。
查看帮助文档
bash
[root@master ~]# kubectl taint --help
语法:
bash
kubectl taint nodes <节点名称> <key>=<value>:<effect>
示例:
-
为节点
node-1
添加一个污点带有值的,禁止调度新的 Pod:bash[root@master ~]# kubectl taint nodes node-1 dedicated=special:NoSchedule node/node-1 tainted [root@master ~]# kubectl describe node node-1 | grep Taint Taints: dedicated=special:NoSchedule
-
为节点
node-2
添加一个污点,尽量不调度新的 Pod:bash[root@master ~]# kubectl taint nodes node-2 gpu:PreferNoSchedule node/node-2 tainted [root@master ~]# kubectl describe node node-2 | grep Taint Taints: gpu:PreferNoSchedule
-
为节点
node-3
添加一个污点,禁止调度并驱逐不满足容忍的 Pod:bash[root@master ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-server-1-79776bf47-h9zvh 1/1 Running 0 20m 10.244.3.14 node-3 <none> <none> [root@master ~]# kubectl taint nodes node-3 maintenance=true:NoExecute node/node-3 tainted [root@master ~]# kubectl describe node node-3 | grep Taint Taints: maintenance=true:NoExecute [root@master ~]# kubectl get pod -o wide #node-3的pod已经被驱离,会被重新调度到其它节点
删除污点:
语法:
bash
kubectl taint nodes <节点名称> <key>[:<effect>]-
示例 :
删除节点 node-1与node-2
上的污点:
bash
[root@master ~]# kubectl taint nodes node-1 dedicated-
node/node-1 untainted
[root@master ~]# kubectl describe node node-1 | grep Taint
Taints: <none>
bash
[root@master ~]# kubectl taint nodes node-2 gpu-
node/node-2 untainted
[root@master ~]# kubectl describe node node-2 | grep Taint
Taints: <none>
2. 容忍(Toleration)
2.1.容忍的作用
容忍是 Pod 的一个属性,允许 Pod 调度到带有特定污点的节点上。通过容忍,Pod 可以忽略节点的污点限制。
2.2.容忍的配置
容忍可以在 Pod 的 YAML 文件中通过 tolerations
字段配置。
示例:
bash
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: nginx
image: nginx
tolerations:
- key: "dedicated"
operator: "Equal"
value: "special"
effect: "NoSchedule"
字段说明:
key
: 污点的键。operator
: 匹配操作符,可以是Equal
(精确匹配)或Exists
(存在即可)。value
: 污点的值(当operator
为Equal
时必填)。effect
: 污点的效果(如NoSchedule
、NoExecute
等)。
示例场景:
-
允许 Pod 调度到带有
dedicated=special:NoSchedule
污点的节点:bashtolerations: - key: "dedicated" operator: "Equal" value: "special" effect: "NoSchedule"
-
允许 Pod 调度到带有任意
gpu=true
污点的节点:此时operator为Exists,可以不指定污点的值
bashtolerations: - key: "gpu" operator: "Exists" effect: "NoSchedule"
-
允许 Pod 调度到带有任意
NoExecute
污点的节点:bashtolerations: - operator: "Exists" effect: "NoExecute"
2.3. 污点与容忍的常见使用场景
场景 1:专用节点
-
为 GPU 节点添加污点:
bash[root@master ~]# kubectl taint nodes node-1 gpu=true:NoSchedule node/node-1 tainted
-
在需要调度到 GPU 节点的 Pod 中添加容忍:
bash[root@master ~]# cat create_pod.yml apiVersion: v1 kind: Pod metadata: name: test-pod-1 namespace: default labels: app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent ports: - containerPort: 80 tolerations: - key: gpu operator: Exists effect: NoSchedule [root@master ~]# kubectl apply -f create_pod.yml pod/test-pod-1 created [root@master ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pod-1 1/1 Running 0 5s 10.244.2.85 node-1 <none> <none>
场景 2:节点维护
-
为维护节点添加污点:
bash[root@master ~]# kubectl taint nodes node-2 maintenance=true:NoExecute node/node-2 tainted
-
在需要继续运行的 Pod 中添加容忍:
需要注意:对已经运行在该节点的pod将会被驱离,自动调度到其他节点,除非在创建的时候提前指定容忍该污点的作用。
bash[root@master ~]# cat create_pod.yml apiVersion: v1 kind: Pod metadata: name: test-pod-1 namespace: default labels: app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent ports: - containerPort: 80 tolerations: - key: maintenance operator: Equal value: "true" effect: NoExecute [root@master ~]# kubectl apply -f create_pod.yml pod/test-pod-1 created [root@master ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pod-1 1/1 Running 0 5s 10.244.1.135 node-2 <none> <none>
场景 3:故障隔离
-
为故障节点添加污点:
bashkubectl taint nodes node-2 failure=true:NoExecute
-
在需要继续运行的 Pod 中添加容忍:
bashtolerations: - key: "failure" operator: "Equal" value: "true" effect: "NoExecute"
3. 总结
- 污点:用于限制 Pod 调度到特定节点。
- 容忍:允许 Pod 忽略节点的污点,调度到特定节点。
- 通过污点和容忍,可以实现节点的专用化、维护和故障隔离等场景。
通过合理使用污点和容忍,可以更灵活地控制 Kubernetes 集群中 Pod 的调度行为,提升集群的稳定性和资源利用率。
4.污点的优先级
4.1. 污点的效果与 nodeName与nodeSelector
的关系
情况 1:污点效果为 NoSchedule
- 如果节点上有
NoSchedule
污点,而 Pod 没有配置相应的容忍:- 即使 Pod 使用了
nodeName
指定了该节点,Pod 仍然不会被调度到该节点。 - Kubernetes 会忽略
nodeName
的指定,因为污点的优先级更高。
- 即使 Pod 使用了
情况 2:污点效果为 NoExecute
- 如果节点上有
NoExecute
污点,而 Pod 没有配置相应的容忍:- 如果 Pod 已经运行在该节点上,它会被驱逐。
- 如果 Pod 尚未调度到该节点,即使使用了
nodeName
,Pod 也不会被调度到该节点。
情况 3:Pod 配置了容忍
- 如果 Pod 配置了与节点污点匹配的容忍:
- 无论污点的效果是
NoSchedule
还是NoExecute
,Pod 都可以正常调度到该节点。 nodeName
的指定会生效,Pod 会被调度到指定的节点。
- 无论污点的效果是
4.2.总结
- 污点的优先级高于
nodeName与nodeSelector
:即使 Pod 使用了nodeName或者nodeSelector
指定节点,污点仍然会生效。 - 污点的效果决定行为 :
NoSchedule
:阻止 Pod 调度到该节点。NoExecute
:驱逐已运行的 Pod 或阻止新 Pod 调度。
- 容忍的作用:如果 Pod 配置了与污点匹配的容忍,则可以忽略污点的限制,正常调度到指定节点。
因此,在使用 nodeName或者nodeSelector
时,需要确保 Pod 配置了与节点污点匹配的容忍,否则 Pod 可能无法调度到指定节点。