48、K8S-调度机制-污点、容忍度调度之节点的Traint、Pod的tolerations
1、基础知识
1.1、回顾
我们之前所学的所有调度策略,都是基于节点调度和pod调度选择我们新的pod资源应该如何创建,而实际的生产角度上,
往往会出现基于node节点的属性来选择是否让新的pod资源进行创建,但是对于节点来说,没有所谓的节点反亲和性,但是有一种类似的策略:污点和容忍度。
1.2、术语解析
1.2.1、污点(taints)
是定义在node节点上的键值属性数据。主要作用是让节点拒绝pod,尤其是不符合node规则的pod。
1.2.2、容忍度(tolerations)
是定义在Pod上的键值属性数据,用于配置可容忍的污点,调度器将其调度至容忍污点的节点上或无污点的节点
1.3、污点与容忍关系
1.3.1、关系说明
Taint(污点)和 Toleration(容忍)是相互配合的,可以用来避免 pod 被分配到不合适的节点上,每个节点上都可以应用一个或多个 taint ,
这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。
1.3.2、场景
比如:A节点是集群中很重要的节点,不要将无关的pod来我这里运行,那么我们就可以在A上面添加一些污点标识。
1.3.3、污点调度流程图
我们可以看出来,节点打了污点,pod的容忍度只能调度到相同污点或无污点上调度
1.3.4、作用来源
1.4、污点功能
Kubernetes自1.6起支持使用污点自动标识问题节点,它通过节点控制器在特定条件下自动为节点添加 污点信息实现。它们都使用NoExecute效用标识,因此非能容忍此类污点的现在Pod对象也会遭到驱逐。目前,内建使用的此类污点有如下几个。
node.kubernetes.io/not-ready:节点进入NotReady状态时被自动添加的污点。 node.alpha.kubernetes.io/unreachable:节点进入NotReachable状态时被自动添加的污点。 node.kubernetes.io/out-of-disk:节点进入OutOfDisk状态时被自动添加的污点。 node.kubernetes.io/memory-pressure:节点内存资源面临压力。 node.kubernetes.io/disk-pressure:节点磁盘资源面临压力。 node.kubernetes.io/network-unavailable:节点网络不可用。 node.cloudprovider.kubernetes.io/uninitialized:kubelet由外部的云环境程序启动时,
它自动为节点添加此污点,待到云控制器管理器中的控制器初始化此节点时再将其删除。 不过,Kubernetes的核心组件通常都要容忍此类的污点,以确保其相应的DaemonSet控制器能够无视此类污点于节点上部署相应的关键Pod对象,例如kube-proxy或kube-flannel等。
1.5、查询kube组件容忍、污点的设置
1.5.1、查看kube-apiserver的容忍设置
master1 ~]# kubectl -n kube-system describe pod kube-apiserver-master1 | grep -i tolerations Tolerations: :NoExecute op=Exists
1.5.2、查看kube-proxy的容忍设置
master1 ~]# kubectl -n kube-system describe pod kube-proxy-ppzmt | grep -i tolerations Tolerations: op=Exists
1.5.3、查看master1节点的污点设置
]# kubectl get nodes master1 -o yaml taints: - effect: NoSchedule key: node-role.kubernetes.io/control-plane
1.6、节点-Traint-污点
1.6.1、属性解析
Taint是节点上属性。 kubectl explain node.spec.taints effect # pod不能容忍这个污点时,他的行为是什么,它有三个值:NoSchedule、PreferNoSchedule、NoExecute key # 定义一个key=value:effect value # 定义一个值,这是一个必选项timeAdded
1.6.2、effect属性值
1、NoSchedule 不能容忍此污点的Pod对象,不可调度至当前节点,属于强制型约束关系,但添加污点对节点上现存的Pod对象不产生影响 2、PreferNoSchedule NoSchedule的柔性约束版本,即调度器尽量确保不会将那些不能容忍此污点的Pod对象调度至当前节点, 除非不存在其他任何能够容忍此污点的节点可用;添加该类效用的污点同样对节点上现存的Pod对象不产生影响。 3、NoExecute 不能容忍此污点的新Pod对象不可调度至当前节点,属于强制型约束关系,而且节点上现存的Pod对象因节点污点变动或Pod容忍度变动而不再满足匹配条件时,Pod对象将会被驱逐。
1.7、Pod-Tolerations-容忍度
1.7.1、属性解析
Tolerations 是Pod上属性,我们看一下Tolerations如何定义
kubectl explain pod.spec.tolerations
effect # 节点调度后的操作
key # 被容忍的key
operator # Exists只要key在就可以调度,Equal(等值比较)必须是值要相同
tolerationSeconds # 被驱逐的宽限时间,默认是0 就是立即被驱逐
value # 被容忍key的值
1.7.2、容忍度的判断方式
在Pod对象上定义容忍度时,它支持两种操作符。
一种是等值比较,表示容忍度与污点必须在key、value和effect三者之上完全匹配,
一种是存在性判断(Exists),表示二者的key和effect必须完全匹配,而容忍度中的value字段要用空值。
1.7.3、容忍度的匹配原则
一个节点可以配置使用多个污点,而一个Pod对象也可以有多个容忍度,将一个Pod对象的容忍度套用到特定节点的污点之上进行匹配度检测时,时将遵循如下逻辑: 1)、首先处理每个有着与之匹配的容忍度的污点; 2)、对于不能匹配到容忍度的所有污点,若存在一个污点使用了NoSchedule效用标识,则拒绝调度当前Pod至该节点; 3)、对于不能匹配到容忍度的所有污点,若都不具有NoSchedule效用标识,但至少有一个污点使用了PreferNoScheduler效用标准,则调度器会尽量避免将当前Pod对象调度至该节点。 4)、如果至少有一个不能匹配容忍度的污点使用了NoExecute效用标识,节点将立即驱逐当前Pod对象,或者不允许该Pod调度至给定的节点;而且,即便容忍度可以匹配到使用了NoExecute效用标识的污点,若在 Pod上定义容忍度时同时使用tolerationSeconds属性定义了容忍时限,则在超出时限后当前脚Pod也将会被节点所驱逐。
2、节点-Traint-污点-实践
2.1、污点管理
2.1.1、查询污点
kubectl get nodes master1 -o jsonpath='{.spec.taints}' kubectl describe nodes | grep -i taints
2.1.2、增加污点
kubectl taint node node1 node-type=production:NoSchedule
2.1.3、删除污点
kubectl patch nodes node1 -p '{"spec":{"taints":[]}}' kubectl taint node node1 node-type-
2.2、污点-实践
2.2.1、需求
1、node1节点,打上污点。效果:NoSchedule 2、创建一个pod,使用节点标签选择器,并使用调度到node1看看是否能调度成功 主要验证当节点不能调度时候,创建pod又有NoSchedule,分析状态是否一直pending。
2.2.2、给node1节点打上污点
kubectl taint node node1 node-type=production:NoSchedule
2.2.3、给node1打上标签
kubectl label nodes node1 env=dev
2.2.4、定义资源配置清单且应用【创建pod】
kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: pod-test spec: containers: - name: pod-test image: 192.168.10.33:80/k8s/pod_test:v0.1 imagePullPolicy: IfNotPresent nodeSelector: env: dev EOF
2.2.5、查询结果
]# kubectl get pods -w NAME READY STATUS RESTARTS AGE pod-test 0/1 Pending 0 9s
2.2.6、为什么pod状态一直Pending
排查点: 1、节点标签是存在的,所以不关节点标签的问题 ]# kubectl get node node1 --show-labels NAME STATUS ROLES AGE VERSION LABELS node1 Ready <none> 3d14h v1.25.7 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env=dev,kubernetes.io/arch=amd64
,kubernetes.io/hostname=node1,kubernetes.io/os=linux 2、检查是否是污点的问题 ]# kubectl get nodes node1 -o jsonpath='{.spec.taints}' [{"effect":"NoSchedule","key":"node-type","value":"production"}] # NoSchedule 表示不让调度 总结: 当节点调度和污点冲突时,状态就一直pending.
2.2.7、删除污点观察是否调度正常
# 删除污点 kubectl taint node node1 node-type- # 马上自动调度到node1,状态由pending转为running ]# kubectl get pods -o wide --show-labels NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS pod-test 1/1 Running 0 9m31s 10.244.3.64 node1 <none> <none> <none>
2.3、驱逐节点的pod
2.3.1、为node1添加驱离污点
kubectl taint node node1 diskfull=true:NoExecute 注意: 一旦打上这个标签,当前节点上的所有pod都会被驱离
2.3.2、查看驱逐效果
]# kubectl get pod -o wide -w NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-tol 1/1 Running 0 4m27s 10.244.3.65 node1 <none> <none> pod-tol 1/1 Terminating 0 5m5s 10.244.3.65 node1 <none> <none> pod-tol 1/1 Terminating 0 5m36s 10.244.3.65 node1 <none> <none> pod-tol 0/1 Terminating 0 5m36s 10.244.3.65 node1 <none> <none> pod-tol 0/1 Terminating 0 5m36s 10.244.3.65 node1 <none> <none> pod-tol 0/1 Terminating 0 5m36s 10.244.3.65 node1 <none> <none>
2.3.3、清理污点继续学习下面小节
kubectl taint node node1 node-type-
kubectl taint node node1 diskfull-
3、Pod-Tolerations-容忍度-实践
3.1、给正常运行pod节点增加污点的分析
3.3.1、给 node1增加污点
master1 ~]# kubectl taint node node1 node-type=production:NoSchedule # 查询创建的结果 master1 ~]# kubectl get nodes node1 -o jsonpath="{.spec.taints}" [{"effect":"NoSchedule","key":"node-type","value":"production"} # 此时节点,已经打上污点 master1 ~]# kubectl get nodes node1 -o yaml taints: - effect: NoSchedule key: node-type value: production
3.3.2、查询当前pod节点是否还在node1节点上
因为effect是NoSchedule,所以对当前运行的pod不会影响,不会做驱逐pod的动作
3.2、定义资源配置清单并且应用【给pod配置容忍度】
kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: pod-tol spec: containers: - name: pod-test image: 192.168.10.33:80/k8s/pod_test:v0.1 imagePullPolicy: IfNotPresent nodeSelector: env: dev tolerations: - key: "node-type" operator: "Equal" value: "production" effect: "NoSchedule" EOF # env: dev AND key: "node-type" == value: "production" AND effect: "NoSchedule" 表示可容忍,直接调度到node1
3.3、查看运行效果
master2 ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-tol 1/1 Running 0 4m25s 10.244.3.65 node1 <none> <none>