kubernete污点和容忍Taint&Toleration
[TOC]
一、前言
在K8S中,如果Pod能容忍某个节点上的污点,那么Pod就可以调度到该节点。如果不能容忍,那就无法调度到该节点。污点和容忍度就像谈恋爱的小情侣,你情我愿,女生知道男生的缺点,却依然选择容忍,这样他们可以生活在一起。如果女生容忍不了男生的缺点,那就没法生活在一起。二话不说“分手”
污点它让Node拒绝Pod的运行。简单地说,被标记为Taint的节点就是存在问题的节点,比如磁盘要满、资源不足、存在安全隐患要进行升级维护,希望新的Pod不会被调度过来,但被标记为Taint的节点并非故障节点,仍是有效的工作节点,所以仍需将某些Pod调度到这些节点上时,可以通过使用Toleration属性来实现。 在默认情况下,在Node上设置一个或多个Taint之后,除非Pod明确声明能够容忍这些污点,否则无法在这些Node上运行。

二、简介
污点(Taint): 它使节点能够排斥一类特定的 Pod。定义在节点上,用于拒绝Pod调度到此节点,除非该Pod具有该节点上的污点容忍度。被标记有Taints的节点并不是故障节点。
容忍度(Toleration): 是应用于 Pod 上的。容忍度允许调度器调度带有对应污点的 Pod。用于配置Pod可容忍的节点污点,K8S调度器只能将Pod调度到该Pod能够容忍的污点的节点上。
污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod, 是不会被该节点接受的。Taint在一类服务器上打上污点,让不能容忍这个污点的Pod不能部署在打了污点的服务器上。Toleration是让Pod容忍节点上配置的污点,可以让一些需要特殊配置的Pod能够调用到具有污点和特殊配置的节点上。Taint是作用在节点上;Toleration是作用在Pod上,Taint相当于一把“锁”,Toleration相当于一把“钥匙”。
官网:Taints and Tolerations | Kubernetes

==注意:生产环境的调度并非随便调用,需要结合服务器配置,pod资源信息等情况考虑==
三、Taint配置解析
==注意:一个节点可以配置多个污点;key名相同但是effect不一致也可以使用,代表不同的污点==
1 | #>>> 创建一个污点: |
污点是以key=value的形式配置,但是生产环境中也可以使用单独key的形式配置;value可以为空,例如ssd:PreferNoSchedule。
四、Taint排斥等级
- NoExecute:没有配置此污点容忍度的新Pod对象不能调度到此节点,节点上现存的Pod会被驱逐。 如果 Pod 不能忍受这类污点,Pod 会马上被驱逐。如果 Pod 能够忍受这类污点,但是在容忍度定义中没有指定
tolerationSeconds(容忍时间), 则 Pod 还会一直在这个节点上运行。如果 Pod 能够忍受这类污点,而且指定了tolerationSeconds, 则 Pod 还能在这个节点上继续运行这个指定的时间长度。 - NoSchedule:没有配置此污点容忍度的新Pod不能调度到此节点,节点上现存的Pod不受影响。
- PreferNoSchedule:没有配置此污点容忍度的新Pod尽量不要调度到此节点,如果找不到合适的节点,依然会调度到此节点。
五、Toleration配置解析
配置在Pod中和containers同一级别
方式一 :精准匹配
key名和value值必须和节点设置的污点内容一致,才可调度到该节点。
1 | tolerations: |
方式二:非精准匹配
当多个节点都存在GPU但是有的效率高,有的效率低时,且pod没有硬性要求部署在那个GPU的节点,只要是GPU的节点都可以容忍该节点的污点,就会用到非精准匹配。只需要匹配Key和effect的值就行,value不用设置(需要为空)。
1 | tolerations: |
方式三:大范围匹配(不推荐key为内置Taint)
不需要匹配effect的值,只需要匹配Key值就行,不管该节点的污点effect设置的什么类型,我都可以部署上边。
1 | - key: "GPU" |
方式四:匹配所有(不推荐)
1 | tolerations: |
停留时间配置:
当你部署pod的该节点故障了,系统默认是300s后开始迁移。可以通过tolerationSeconds设置pod迁移时间,达到节点故障pod快速迁移和故障恢复;如果不设置时间且该节点的污点effect值设置的NoExecute。pod则不迁移,因为pod容忍该污点。
1 | tolerations: |
==注意事项==:
注意:当创建一个pod的时候,该节点打了一个GPU=true的label标签,并且该节点也打了GPU=true: NoSchedule的污点。且在pod的yaml文件中没有设置Toleration的容忍设置,则不会部署到该节点上。此外,yaml中只设置了node的标签选择器,且没有设置容忍该节点的污点也不会部署到该节点,pod会一直处于pending状态,describe该pod会提示该节点存在污点,该pod没有容忍该污点。nodeSelector是强制性部署到该节点上,而Toleration是累加在该基础上的,并非强制性。同样有两台节点,一台没有打任何污点,另外一台则打了GPU=true: NoSchedule的污点,yaml文件中设置了容忍该污点的相关信息。但是pod在创建的时候不一定会部署在有污点的节点上。一般生产环境Tains配合label标签一起使用。
==注意:DaemonSet类型的pod,在创建时默认容忍所有污点,因为它是在每一个节点都部署一个pod,就算驱逐了,也无法迁移在其他的节点上。==
DaemonSet 控制器自动为所有守护进程添加如下
NoSchedule容忍度,以防 DaemonSet 崩溃:
node.kubernetes.io/memory-pressure
node.kubernetes.io/disk-pressure
node.kubernetes.io/pid-pressure(1.14 或更高版本)
node.kubernetes.io/unschedulable(1.10 或更高版本)
node.kubernetes.io/network-unavailable(只适合主机网络配置)
六、集群内置污点
- node.kubernetes.io/not-ready:节点未准备好,相当于节点状态Ready的值为False。
- node.kubernetes.io/unreachable:Node Controller访问不到节点,相当于节点状态Ready的值为Unknown。
- node.kubernetes.io/out-of-disk:节点磁盘耗尽。
- node.kubernetes.io/memory-pressure:节点存在内存压力。
- node.kubernetes.io/disk-pressure:节点存在磁盘压力。
- node.kubernetes.io/network-unavailable:节点网络不可达。
- node.kubernetes.io/unschedulable:节点不可调度。
示例:节点不健康,6000秒后再驱逐(默认是300秒)
为 Pod 设置 tolerationSeconds,以指定当节点失效或者不响应时, Pod 维系与该节点间绑定关系的时长。比如,你可能希望在出现网络分裂事件时,对于一个与节点本地状态有着深度绑定的应用而言, 仍然停留在当前节点上运行一段较长的时间,以等待网络恢复以避免被驱逐。 你为这种 Pod 所设置的容忍度看起来可能是这样:
1 | tolerations: |
==注意:==
当大范围匹配时,不能使用内置污点的key值,因为当节点故障时,系统会自动默认给该节点打上故障污点,此时,如果yaml文件设置的key值和内置污点的key值一致,系统判定pod会容忍这个故障污点;当该节点出现故障时,则pod不会被驱逐,导致业务容器宕机。此外,设置容忍时间,要根据实际生产情况。因为有时候会有突发因素导致网络波动,节点会处于短暂的故障,无法通信。这时容忍时间设置过短会导致该节点的pod瞬间被迁移走。而且实际生产的容忍时间肯定大于yaml文件设置的容忍时间,因为节点在故障时,系统先给故障节点打上内置污点,然后容忍时间才开始计时。==在节点被驱逐时,节点控制器或者 kubelet 会添加带有
NoExecute效果的相关污点。 如果异常状态恢复正常,kubelet 或节点控制器能够移除相关的污点。==
七、案例
- 一个节点是纯GPU节点,现需要只有一些需要计算的Pod调度到此节点。
1 | #>>> 给节点打上污点和标签 |
1 | #>>> 配置Pod资源清单 |




/02-Kubernetes容器编排工具部署(adm)/1.png)
/kubernetes 二进制高可用安装部署(v1.23+)/1.png)

