摘要:它是给节点打标签,专门用来“拒绝”不符合要求的Pod,和亲和性(Pod主动找节点)正好相反:亲和性是“Pod挑节点”,Taint是“节点挑Pod”(总结的很好!!)。只有Pod带了“Toleration”,能跨过节点的门槛,才能被调度过去。
Taint和Toleration这里使用英文,不然过不了审核。
Taint简单说就是节点给Pod立的“门槛”——节点会说:“想调度到我这儿?得满足我这几个条件,不然别来!”
它是给节点打标签,专门用来“拒绝”不符合要求的Pod,和亲和性(Pod主动找节点)正好相反:亲和性是“Pod挑节点”,Taint是“节点挑Pod”(总结的很好!!)。只有Pod带了“Toleration”,能跨过节点的门槛,才能被调度过去。
例子:
比如集群里有几台服务器带GPU(专门跑AI、深度学习任务),你肯定不想让普通的Web服务(比如Nginx、whoami)占用GPU资源。这时候就给GPU节点打个Taint:kubectl taint nodes special=gpu:NoSchedule,意思:节点说“我这是GPU特殊节点,没带‘能容忍special=gpu’的Pod,别往我这儿调度!”
只有需要GPU的Pod(比如TensorFlow容器),在yaml里加“Toleration”,才能调度到这台节点上;普通Web服务没这个Toleration,就会被拒绝,自动调度到其他没有这个Taint的节点。
下面看下具体怎么实现。
在这个实验中,将k8s-node1添加一个Taint,然后再使用whoami分别创建有Toleration和无Toleration的两个Pod进行部署,查看结果。
第一步:将k8s-node1添加Taint
#k8s-node1添加Taintkubectl taint nodes k8s-node1 env=special:NoSchedule#查看是否生效 kubectl describe node k8s-node1 | grep Taint -A 5##结果:Taints: env=special:NoSchedule#如果要删除Taint,命令:kubectl taint nodes k8s-node1 env=special:NoSchedule-其中,key为env,值为special。那么没有这个Toleration的Pod不能够调度到此节点中,主要是后面的这个关键词NoSchedule,称为效果。这样的效果有三种,分别是:
NoSchedule给节点设一道“新Pod禁止入内”的门槛,只有带对应Toleration的新Pod才能进来;已经在节点上的旧Pod(没Toleration也没关系)可以继续运行,不会被赶走。Execute
最严厉的规则——新Pod绝对进不来,已经在节点上的旧Pod如果没有对应Toleration,会被立刻“驱逐”(强制删除并调度到其他节点)。PreferNoSchedule(尽量不调度新Pod,特殊情况可以通融)
“软限制”——调度器会尽量避免把新Pod调度到这个节点,但如果其他节点都满了(实在没地方去),也允许新Pod进来。已经在节点上的旧Pod不受影响。
第二步:创建无Toleration的whoami
#文件名:whoami-normal.yamlcat whoami-normal.yamlapiVersion: apps/v1kind: Deploymentmetadata:name: whoami-deploymentspec:replicas: 10selector:matchLabels:app: whoamitemplate:metadata:labels:app: whoamispec:containers:- name: whoamiimage: crpi-gj5arn39i861t1eu.cn-hangzhou.personal.cr.aliyuncs.com/dev-team-sz/whoamiports:- containerPort: 80# 注意:这里没有配置TolerationEOF#部署kubectl apply -f whoami-normal.yaml#查看状态kubectl get pod whoami-normal -owide可以看到,它不会被调度到k8s-node1节点上。
第三步:创建有Toleration的whoami
#文件名:whoami-toleration.yamlcat whoami-toleration.yamlapiVersion: v1kind: Podmetadata:name: whoami-toleration # 带Toleration的Podspec:containers:- name: whoamiimage: crpi-gj5arn39i861t1eu.cn-hangzhou.personal.cr.aliyuncs.com/dev-team-sz/whoami# 核心:添加Toleration,匹配node-1的Tainttolerations:- key: "env" # 要容忍的Taint的键(和node-1的Taint键一致)operator: "Equal" # 匹配方式:等于value: "special" # 要容忍的Taint的值(和node-1的Taint值一致)effect: "NoSchedule" # 要容忍的Taint效果(和node-1的Taint效果一致)EOF#部署kubectl apply -f whoami-toleration.yaml#查看状态kubectl get pod whoami-toleration -owide可以看到,它被调度到k8s-node1节点上。这里主要强调的是能够,而不是说一定能调度到该节点。
kubectl delete -f whoami-toleration.yamlrm -rf whoami-toleration.yamlkubectl delete -f whoami-normal.yamlrm -rf whoami-normal.yaml属性路径图示如下:
一共有五个字段
key要容忍的Taint的键。此字段为空意味着匹配所有的Taint键。如果key为空,则operator必须为Exists;这种组合意味着匹配所有值和所有键。operator
operator表示key与value之间的关系。有效的operator取值是Exists和Equal。默认为Equal。Exists相当于value为某种通配符,因此Pod可以容忍特定类别的所有Taint。value
value是Toleration所匹配的Taint值。如果operator为Exists,则此value值应该为空,否则value值应该是一个正常的字符串。effect
effect指示要匹配的Taint效果。空值意味著匹配所有Taint效果。如果要设置此字段,允许的值为NoSchedule、PreferNoSchedule和NoExecute之一。tolerationSeconds
表示Toleration(effect必须是NoExecute,否则此字段被忽略)容忍Taint的时间长度。默认情况下,此字段未被设置,这意味着会一直能够容忍对应Taint(不会发生驱逐操作)。零值和负值会被系统当做0值处理(立即触发驱逐)。
总结的几条有用规则:
空的key配合Exists操作符能够匹配所有的键和值。空的effect匹配所有的effect。规则还是比较多,需要的时候查阅一下就好了。
这个比较绕一些,当Node有多个Taint时,那么Pod相应的就需要一个一个的抵消,下面用一个故事来解释,了解原理即可。
小区保安的故事节点(Node)=一个小区(比如叫“Node小区”)节点上的多个Taint=小区门口贴的多个“禁止入内”规则(比如“没门禁卡不准进”“不是住户不准进”“带宠物不准进”)Pod的多个Toleration=你手里的多个“特殊通行证”(比如“我有门禁卡”“我是住户家属”“我带的是导盲犬”)调度器=小区门口的保安(负责判断你能不能进)第1步:节点先“亮规矩”——列出所有Taint
保安先把小区所有“禁止入内”的规则都摆出来,明确告诉你:“想进?得先过这几关,这几条规矩你只要碰一条,没特殊理由就不让进。”
比如Node小区列出3个Taint(3条规矩):
Taint1:“没门禁卡(key=card,effect=NoSchedule)”Taint2:“不是住户(key=resident,effect=NoSchedule)”Taint3:“带宠物(key=pet,effect=NoSchedule)”第2步:Pod“掏通行证”——用Toleration抵消能匹配的Taint
你(Pod)拿出自己的“通行证”(Toleration),跟保安的规则一一对应:你有“门禁卡通行证”(Toleration1:key=card,effect=NoSchedule)→能抵消“没门禁卡”的规矩(Taint1),这关过了;你有“住户家属通行证”(Toleration2:key=resident,effect=NoSchedule)→能抵消“不是住户”的规矩(Taint2),这关也过了;你没“宠物特殊通行证”(没对应Toleration3)→“带宠物”的规矩(Taint3)没抵消,还在。第3步:看“剩下的规矩”——没抵消的Taint才会影响Pod保安最后看:“你抵消了2条规矩,但还剩1条‘带宠物不准进’的规矩你没抵消——那这条规矩就真的能拦住你了。”
也就是说:
被PodToleration“抵消”的Taint(比如Taint1、Taint2),相当于“作废了”,对Pod没影响;没被抵消的Taint(比如Taint3),才是真正有效的,会按照Taint的“效果”(比如NoSchedule=不让调度进来)处理Pod。抵消之后,如果还有剩余的Taint怎么办?下面是三种情况。
如果在剩余的Taint中存在effect=NoSchedule,则调度器不会把 该Pod调度到这一节点上。如果在剩余的Taint中没有NoSchedule效果,但是有 PreferNoSchedule效果,则调度器会尝试不把这个Pod指派给这个节点。如果在剩余的Taint中有NoExecute效果,并且这个Pod已经在该节点上运行,则会被驱逐;如果没有在该节点上运行,则也不会再被调度到该节点上。情况1:剩余Taint中有NoSchedule→“硬拦,绝对不让进”
假设节点剩下的Taint是带宠物:NoSchedule(没被Pod的Toleration抵消),就相当于小区门口最后剩一条“带宠物绝对不准进”的规矩。这时候保安(调度器)会直接拦住Pod:“这条规矩你没抵消,不管你是谁,今天就是不让进!”
结果:Pod100%不会被调度到这个节点,哪怕其他节点都满了,它也只能Pending。
情况2:剩余Taint中只有PreferNoSchedule,没有NoSchedule→“软拦,能不让进就不让进”
假设节点剩下的Taint是快递员:PreferNoSchedule(没被抵消),相当于小区规矩是“尽量别让快递员进,特殊情况也可以通融”。
保安会想:“虽然你没抵消这条规矩,但也不是绝对不能进——先看看其他小区(节点)有没有空位,有就安排去其他地方;实在没地方了,让你进来也行。”
结果:调度器会优先把Pod安排到没有这个Taint的节点,只有迫不得已时才会调度到这个节点。
情况3:剩余Taint中有NoExecute→“赶人+拦新,既不让进也不让待”
分两种场景:
Pod还没进节点:剩下的Taint是外来车辆:NoExecute,保安会说:“这条规矩你没抵消,不仅现在不让进,以后也别想进!”→Pod永远不会被调度到这个节点。Pod已经在节点上:比如之前Pod凭通行证进了小区,但后来小区加了外来车辆:NoExecute规矩,而Pod的通行证没更新(没抵消这个新Taint)。保安会说:“你现在不符合规矩了,必须马上离开!”→正在运行的Pod会被强制驱逐(从节点上删掉)。NoExecute是最严厉的规则,一般有这种Taint可能意味着节点出现严重问题,那么没有相应Toleration的Pod会立即被驱逐,而具有Toleration的Pod永远不会被驱逐。比如下面的Pod就有免死金牌,永远不会被驱逐。
tolerations:- key: "key1"operator: "Equa1"value: "value1"effect: "NoExecute"但是服务器不愿意让这个不被驱逐的Pod永远呆在这里,毕竟服务器都崩溃了,最好所有的Pod都被移走,那么就可以给这个Toleration加上时间,如下:
tolerations:- key: "key1"operator: "Equa1"value: "value1"effect: "NoExecute"tolerationSeconds: 3600它设计的很巧秒,下面是解释:
如果节点彻底宕机,被打上key1=value1:NoExecuteTaint。如果Pod有永久Toleration(没有tolerationSeconds),就会一直卡在“运行中”状态(实际已经无法提供服务),K8s也不会重新调度它——这显然不合理。
给节点3600秒时间修复(比如重启恢复、网络重连)修复了(Taint移除)→Pod继续留着没修复(Taint还在)→时间一到就驱逐,让K8s重新调度一个健康的Pod所以,NoExecute类型的Toleration本质是“有限度的容忍”,tolerationSeconds就是这个“限度”,既给临时故障留了修复时间,又防止永久故障时Pod被“卡死”。考虑的很周全!!
来源:恋爱脑一点号