Kubernetes中的Taint和Toleration

参考

Taint 和 toleration 相互配合,可以用来避免 pod 被分配到不合适的节点上。每个节点上都可以应用一个或多个 taint ,这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。如果将 toleration 应用于 pod 上,则表示这些 pod 可以(但不要求)被调度到具有匹配 taint 的节点上。可使用节点污点来控制允许工作负载在哪些节点上运行。

添加taint

查看节点taint在返回的节点说明中,查找 Taints 字段

1
kubectl  describe nodes  rancher-k8s-m1

可以使用命令 kubectl taint 给节点增加一个 taint。比如

1
kubectl taint nodes [NODE_NAME] [KEY]=[VALUE]:[EFFECT]

还可以向具有特定标签的节点添加污点:

1
2
kubectl taint node -l  node-role.kubernetes.io/etcd=tru dedicated=foo:PreferNoSchedule
#kubectl taint nodes dev-k8s-m1 node-role.kubernetes.io/controlplane=true:NoSchedule 给节点 dev-k8s-m1 增加一个 taint,它的 key 是 role.kubernetes.io/controlplane,value 是 true,effect 是 NoSchedule。除非pod有符合的容忍(toleration),否则不会被调度到dev-k8s-m1这个节点

删除taint

1
kubectl taint nodes dev-k8s-m1 role.kubernetes.io/controlplane:NoSchedule-

点污点是与“effect”相关联的键值对。以下是可用的effect:

1
2
3
NoSchedule:不会将不能容忍此污点的 Pod 调度到节点上。
PreferNoSchedule:Kubernetes 会避免将不能容忍此污点的 Pod 调度到节点上。这是一个优先选择或者软性版本的NoSchedule,调度系统会尽量避免调度不容忍这种污点的pod到带有此污点的节点上,但是并不是硬性要求
NoExecute:如果 Pod 已在节点上运行,则会将该 Pod 从节点中逐出;如果尚未在节点上运行,则不会将其调度到节点上。

toleration

可以在 PodSpec 中定义 pod 的 toleration。下面两个 toleration 均与上面例子中使用 kubectl taint 命令创建的 taint 相匹配,因此如果一个 pod 拥有其中的任何一个 toleration 都能够被分配到 dev-k8s-m1

1
2
3
4
5
tolerations:
- key: "role.kubernetes.io/controlplane"
operator: "Equal"
value: "true"
effect: "NoSchedule"

1
2
3
4
tolerations:
- key: "role.kubernetes.io/controlplane"
operator: "Exists"
effect: "NoSchedule"

只有pod的key和effect都和某一个污点的key与effect匹配,才被认为是匹配,并且要符合以下情形:
operator是Exists(这种情况下value不应当指定)
operator是 Equal 并且value相同
如果operator没有指定,则默认是Equal

1
2
3
4
5
6
tolerations:
- operator: "Exists"

tolerations:
- key: "role.kubernetes.io/controlplane"
operator: "Exists"

以上会匹配所有key为role.kubernetes.io/controlplane的所有taint节点
可以为一个节点(node)添加多个污点,也可以为一个pod添加多个容忍(toleration).kubernetes处理多个污点(taint)或者多个容忍(toleration)类似于过滤器:起初包含所有污点,然后忽略掉pod匹配的污点,剩下不可被忽略的污点决定此节点对pod的效果,特别地:
1 如果至少有一个不可忽略的NoSchedule类型的效果(effect),kubernetes不会调度pod到此节点上来.
2 如果没有不可忽略的NoSchedule类型的效果(effect),但是至少有一个PreferNoSchedule类型的效果,则kubernetes会尝试调度pod到此节点上
3 如果至少有一个NoExecute类型的效果(effect),则此pod会被驱离此节点(当然,前提此pod在此节点上),并且如果pod不在此节点上,也不会被调度到此节点上
假如你有一个以下类型的节点

1
2
3
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule

类型的pod

1
2
3
4
5
6
7
8
9
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"

这种情况下,pod不会被调度到node1上,因为没有容忍(toleration)来匹配第三个taint.但是如果它运行在此节点上,它仍然可以继续运行在此节点上,因为它仅仅不匹配第三个taint.(而第三个taint的效果是NoSchedule,指示不要被调度到此节点)

tolerationSeconds

通常情况下,一个效果类型为NoExecute的taint被添加到一个节点上后,所有不容忍此taint的pod会被马上驱离,容忍的永远不会被驱离.但是效果类型NoExecute可以指定一个tolerationSeconds字段来指示当NoExecute效果类型的污点被添加到节点以后,pod仍然可以继续在在指定时间内留存在此节点上,优雅驱离

1
2
3
4
5
6
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600

在此段时间内如果污点被移除,则pod不会被驱离