一、认识污点
污点(taints)是定义在节点之上的键值型属性数据,用于让节点拒绝将Pod调度运行于其上除非该Pod对象具有接纳节点污点的容忍度。而容忍度(tolerations)是定义在Pod对象上的键值型属性数据,用于配置其可容忍的节点污点,而且调度器仅能将Pod对象调度至其能够容忍该节点污点的节点之上,如下图所示:
节点选择器(nodeSelector)和节点亲和性(nodeAffinity)两种调度方式都是通过在Pod对象上添加标签选择器来完成对特定类型节点标签的匹配,它们实现的是由Pod选择节点的机制。而污点和容忍度则是通过向节点添加污点信息来控制Pod对象的调度结果,从而赋予了节点控制器何种Pod对象能够调度于其上的主控权。简单来说,节点亲和性使得Pod对象被吸引到一类特定的节点,而污点则相反,它提供了让节点排斥特定Pod对象的能力。
Kubernetes使用PodToleratesNodeTains预选策略和TaintTolerationPriority优选函数来完成此种类型的高级调度机制。
二、定义污点和容忍度
污点定义在节点的nodeSpec中,而容忍度则定义在Pod的podSpec中,它们都是键值型数据,但又都额外支持一个效果(effect)标记,语法格式为"key=value:effect",其中key和value的用法及格式与资源注解信息相似,而effect则用于定义对Pod对象的排斥等级,它主要包含以下三种类型:
NodeSchedule:不能容忍此污点的新Pod对象不可调度至当前节点,数据强制型约束关系,节点上现存的Pod对象不受影响。
PreferNoScheduke:NoSchedule的柔性约束版本,即不能容忍此污点的新Pod对象尽量不要调度至当前节点,不过无其他节点可供调度时也会允许接受相应的Pod对象。节点上现存的Pod对象不受影响。
NoExecute:不能容忍此污点的新Pod对象不可调度至当前节点,属于强制型约束关系,而且节点上现存的Pod对象因节点污点变动或Pod容忍度变动而不再满足匹配规则时,Pod对象将被驱逐。
在Pod对象上定义容忍度时,它支持两种操作符:一种是等值比较(Equal),表示容忍度与污点必须在key、value和effect三者之上完全匹配;另一种是存在性判断(Exists),表示二者的key和effect必须完全匹配,而容忍度中的value字段要使用空值。
另外,一个节点可以配置使用多个污点,而一个Pod对象也可以由多个容忍度,不过二者在进行匹配检查时应遵循如下逻辑:
1)首先处理每个有着与之匹配的容忍度的污点。
2)对于不能匹配到的污点,如果存在一个污点使用了NoSchedule效用标识,则拒绝调度Pod对象至此节点;若没有任何一个使用了NoSchedule效用标识,但至少有一个使用看PreferNoScheduler,则应该尽量避免将Pod对象调度至此节点。
3)如果至少有一个不匹配的污点使用了NoExecute效用标识,则节点将立即驱逐Pod对象,或者不予调度至给定节点;另外,即便容忍度可以匹配到使用了NoExecute效用标识的污点,若在定义了容忍度时还同时使用了tolerationSeconds属性定义了容忍时限,则超出时限后其也将被节点驱逐。
使用kubeadm部署的Kubernetes集群,其Master节点将自动添加污点信息以阻止不能容忍此污点的Pod对象调度至此节点之上,实现反允许Master的相关组件的Pod才能允许与此节点,因此,用户手动创建的未特意添加容忍此污点容忍度的Pod对象将不会被调度至此节点:
]# kubectl describe node master
Name: master
Roles: master
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=master
kubernetes.io/os=linux
node-role.kubernetes.io/master=
Annotations: flannel.alpha.coreos.com/backend-data: {
"VtepMAC":"8a:cc:22:e3:28:53"}
flannel.alpha.coreos.com/backend-type: vxlan
flannel.alpha.coreos.com/kube-subnet-manager: true
flannel.alpha.coreos.com/public-ip: 172.16.2.200
kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Wed, 15 Jul 2020 16:26:00 +0800
Taints: node-role.kubernetes.io/master:NoSchedule
Unschedulable: false
Lease:
HolderIdentity: master
AcquireTime: <unset>
RenewTime: Tue, 22 Sep 2020 09:49:42 +0800
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
NetworkUnavailable False Tue, 22 Sep 2020 09:47:34 +0800 Tue, 22 Sep 2020 09:47:34 +0800 FlannelIsUp Flannel is running on this node
MemoryPressure False Tue, 22 Sep 2020 09:47:21 +0800 Wed, 15 Jul 2020 16:25:59 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Tue, 22 Sep 2020 09:47:21 +0800 Wed, 15 Jul 2020 16:25:59 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False Tue, 22 Sep 2020 09:47:21 +0800 Wed, 15 Jul 2020 16:25:59 +0800 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Tue, 22 Sep 2020 09:47:21 +0800 Wed, 15 Jul 2020 17:16:52 +0800 KubeletReady kubelet is posting ready status
Addresses:
InternalIP: 172.16.2.200
Hostname: master
Capacity:
cpu: 4
ephemeral-storage: 51175Mi
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 7990076Ki
pods: 110
Allocatable:
cpu: 4
ephemeral-storage: 48294789041
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 7887676Ki
pods: 110
System Info:
Machine ID: edc36d4e55854bb8a47f6baaa3669426
System UUID: FA864D56-406F-6A4E-3DAA-42759CDE496A
Boot ID: 4d2a5087-67b4-4d5f-a89d-ae3eaa20e0bc
Kernel Version: 3.10.0-1127.el7.x86_64
OS Image: CentOS Linux 7 (Core)
Operating System: linux
Architecture: amd64
Container Runtime Version: docker://19.3.12
Kubelet Version: v1.18.5
Kube-Proxy Version: v1.18.5
PodCIDR: 10.244.0.0/24
PodCIDRs: 10.244.0.0/24
Non-terminated Pods: (13 in total)
Namespace