Kubernetes官方文档:污点和容忍度
kubernetes污点和容忍度测试用例
Taint(污点),它使节点能够排斥一类特定的 Pod。
容忍度(Tolerations)是应用于 Pod 上的,允许(但并不要求)Pod 调度到带有与之匹配的污点的节点上。
污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod,是不会被该节点接受的。
NoSchedule
如果新创建pod没有设置容忍度的话,那么该pod不会被调度,但是不会影响之前已经调度的pod。
NoExecute
既影响调度过程,又影响现存的pod,如果已经存在的pod不能容忍节点后来加的污点,这个pod就会被驱逐。
PreferNoSchedule
尽量避免将Pod调度到具有污点的节点上,如果集群中有没有污点的节点则优先调度到干净节点,如果所有工作节点都被打上污点,则也可以正常调度到这些有污点的工作节点上。
问题一:为什么master节点的污点排斥等级为Noschedule,却有pod可以被调度呢?
原因:因为这些可以被调度的pod都设置了容忍度NoExecute,而NoExecute排斥等级高于Noschedule,可以向下包容的,所以可以被调度。如下所示:
1、k8s集群worker节点默认是没有污点的,如下图所示:
2、使用命令kubectl taint给节点k8s-worker-16增加一个污点,如下图所示:
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-16 deploy=nginx:NoSchedule
node/k8s-worker-16 tainted
[root@k8s-client-17 yaml]# kubectl describe nodes k8s-worker-16 | grep Taints
Taints: deploy=nginx:NoSchedule
#移除污点
kubectl taint node k8s-worker-16 deploy=nginx:NoSchedule-
3、创建Deployment,观察pod调度情况,如下所示:
vim taintNoSchedule.yaml
apiVersion: apps/v1 #apiVersion是当前配置格式的版本
kind: Deployment #kind是要创建的资源类型,这里是Deploymnet
metadata: #metadata是该资源的元数据,name是必须的元数据项
name: nginx-deployment
labels:
app: nginx
spec: #spec部分是该Deployment的规则说明
replicas: 3 #relicas指定副本数量,默认为1
selector:
matchLabels:
app: nginx
template: #template定义Pod的模板,这是配置的重要部分
metadata: #metadata定义Pod的元数据,至少要顶一个label,label的key和value可以任意指定
labels:
app: nginx
spec: #spec描述的是Pod的规则,此部分定义pod中每一个容器的属性,name和image是必需的
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
如下图所示:
结论:由于k8s-worker-16节点有污点,且没有配置pod容忍度,所以pod无法被调度到k8s-worker-16节点,而当前k8s集群工作节点只有k8s-worker-16和k8s-worker-21,所以pod全部被调度到另外一台工作节点,即k8s-worker-21节点上。
4、使用命令kubectl taint给节点k8s-worker-21增加一个污点,如下图所示:
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-21 deploy=nginx:NoSchedule
node/k8s-worker-16 tainted
[root@k8s-client-17 yaml]# kubectl describe nodes k8s-worker-21 | grep Taints
Taints: deploy=nginx:NoSchedule
5、创建Deployment,观察pod调度情况
[root@k8s-client-17 yaml]# kubectl delete -f taintNoSchedule.yaml
deployment.apps "nginx-deployment" deleted
[root@k8s-client-17 yaml]# kubectl apply -f taintNoSchedule.yaml
deployment.apps/nginx-deployment created
[root@k8s-client-17 yaml]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-845d4d9dff-4hp4h 0/1 Pending 0 5s <none> <none> <none> <none>
nginx-deployment-845d4d9dff-6shr8 0/1 Pending 0 5s <none> <none> <none> <none>
nginx-deployment-845d4d9dff-fxk2s 0/1 Pending 0 5s <none> <none> <none> <none>
如下所示:
结论:由于k8s-worker-16节点和k8s-worker-21节点都被打上污点,且没有配置pod容忍度,所以新创建的pod无法被调度到这两个节点,而当前k8s集群工作节点只有k8s-worker-16和k8s-worker-21,无其他工作节点,所以新创建的pod无法调度到合适的节点,pod会一直处于Pending状态。
6、k8s-worker-21移除污点
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-21 deploy=nginx:NoSchedule-
node/k8s-worker-21 untainted
[root@k8s-client-17 yaml]# kubectl describe node k8s-worker-21 | grep Taints
Taints: <none>
7、创建Deployment,观察pod调度情况
结论:k8s-worker-21移除污点,重新创建pod,则该pod可以正常调度到k8s-worker-21节点上。
1、k8s集群worker节点默认是没有污点的,如下图所示:
2、使用命令kubectl taint给节点k8s-worker-21增加一个污点,排斥等级为NoExecute,如下图所示:
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-21 deploy=nginx:NoExecute
node/k8s-worker-21 tainted
[root@k8s-client-17 yaml]# kubectl describe nodes k8s-worker-21 | grep Taints
Taints: deploy=nginx:NoExecute
若要移除上述命令所添加的污点,你可以执行:
#移除污点
kubectl taint node k8s-worker-21 deploy=nginx:NoExecute-
3、创建Deployment,观察pod调度情况,如下所示:
vim taintNoSchedule.yaml
apiVersion: apps/v1 #apiVersion是当前配置格式的版本
kind: Deployment #kind是要创建的资源类型,这里是Deploymnet
metadata: #metadata是该资源的元数据,name是必须的元数据项
name: nginx-deployment
labels:
app: nginx
spec: #spec部分是该Deployment的规则说明
replicas: 3 #relicas指定副本数量,默认为1
selector:
matchLabels:
app: nginx
template: #template定义Pod的模板,这是配置的重要部分
metadata: #metadata定义Pod的元数据,至少要顶一个label,label的key和value可以任意指定
labels:
app: nginx
spec: #spec描述的是Pod的规则,此部分定义pod中每一个容器的属性,name和image是必需的
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
如下图所示:
结论:k8s-worker-21工作节点被打上污点,排斥等级为NoExecute,且没有配置pod容忍度的话,会自动删除该节点上已经存在的pod。
1、k8s集群worker节点默认是没有污点的,如下图所示:
2、使用命令kubectl taint给节点k8s-worker-21增加一个污点,排斥等级为NoExecute,如下图所示:
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-21 deploy=nginx:PreferNoSchedule
node/k8s-worker-21 tainted
[root@k8s-client-17 yaml]# kubectl describe nodes k8s-worker-21 | grep Taints
Taints: deploy=nginx:PreferNoSchedule
若要移除上述命令所添加的污点,你可以执行:
#移除污点
kubectl taint node k8s-worker-21 deploy=nginx:PreferNoSchedule-
3、创建Deployment,观察pod调度情况,如下所示:
vim taintNoSchedule.yaml
apiVersion: apps/v1 #apiVersion是当前配置格式的版本
kind: Deployment #kind是要创建的资源类型,这里是Deploymnet
metadata: #metadata是该资源的元数据,name是必须的元数据项
name: nginx-deployment
labels:
app: nginx
spec: #spec部分是该Deployment的规则说明
replicas: 8 #relicas指定副本数量,默认为1
selector:
matchLabels:
app: nginx
template: #template定义Pod的模板,这是配置的重要部分
metadata: #metadata定义Pod的元数据,至少要顶一个label,label的key和value可以任意指定
labels:
app: nginx
spec: #spec描述的是Pod的规则,此部分定义pod中每一个容器的属性,name和image是必需的
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
如下图所示:
结论:k8s-worker-16和k8s-worker-21工作节点被打上污点,排斥等级为PreferNoSchedule,且没有配置pod容忍度的话,经观察pod可以正常调度到k8s-worker-16和k8s-worker-21工作节点上。
1、k8s集群worker节点默认是没有污点的,如下图所示:
2、使用命令kubectl taint给节点k8s-worker-16和k8s-worker-21增加污点,如下图所示:
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-16 deploy=nginx:NoSchedule
node/k8s-worker-16 tainted
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-21 deploy=nginx:NoSchedule
node/k8s-worker-21 tainted
[root@k8s-client-17 yaml]# kubectl describe nodes k8s-worker-16 | grep Taints
Taints: deploy=nginx:NoSchedule
[root@k8s-client-17 yaml]# kubectl describe nodes k8s-worker-21 | grep Taints
Taints: deploy=nginx:NoSchedule
若要移除上述命令所添加的污点,你可以执行:
#移除污点
kubectl taint node k8s-worker-16 deploy=nginx:NoSchedule-
kubectl taint node k8s-worker-21 deploy=nginx:NoSchedule-
3、创建Deployment,观察pod调度情况,如下所示:
vim tolerations-1.yaml
apiVersion: apps/v1 #apiVersion是当前配置格式的版本
kind: Deployment #kind是要创建的资源类型,这里是Deploymnet
metadata: #metadata是该资源的元数据,name是必须的元数据项
name: nginx-deployment
labels:
app: nginx
spec: #spec部分是该Deployment的规则说明
replicas: 8 #relicas指定副本数量,默认为1
selector:
matchLabels:
app: nginx
template: #template定义Pod的模板,这是配置的重要部分
metadata: #metadata定义Pod的元数据,至少要顶一个label,label的key和value可以任意指定
labels:
app: nginx
spec: #spec描述的是Pod的规则,此部分定义pod中每一个容器的属性,name和image是必需的
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
tolerations: #容忍度属性
- key: "deploy" #label标签名称,对等于app: nginx中左边的app
operator: "Exists" #表示等值关系,只要对应的键是存在的,exists,其值被自动定义成通配符
value: "" #label标签名称,对等于app: nginx中有右边的nginx,为空的话表示比配nginx="任意值",可以是app: nginx1或app: nginx2等
effect: "" #effect表示要匹配的排斥等级,NoSchedule、NoExecute、PreferNoSchedule,空意味着匹配所有的排斥等级
如下图所示:
结论:k8s-worker-16节点和k8s-worker-21节点都被打上污点,排斥等级为NoExecute,yaml文件中定义的tolerations属性,operator等值关系为Exists,其值被自动定义成通配符value和effect对应的值为空,表示匹配value和effect值为任意值,即被打上污点的节点key对应的值为deploy,value的值为任意值,effect排斥等级为NoSchedule或NoExcuete或PreferNoschedule均可被容忍,即可正常调度到该节点。
1、k8s集群worker节点默认是没有污点的,如下图所示:
2、使用命令kubectl taint给节点k8s-worker-16和k8s-worker-21增加污点,如下图所示:
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-16 deploy=nginx:NoExecute
node/k8s-worker-16 tainted
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-21 deploy=nginx:NoExecute
node/k8s-worker-21 tainted
[root@k8s-client-17 yaml]# kubectl describe nodes k8s-worker-16 | grep Taints
Taints: deploy=nginx:NoExecute
[root@k8s-client-17 yaml]# kubectl describe nodes k8s-worker-21 | grep Taints
Taints: deploy=nginx:NoExecute
若要移除上述命令所添加的污点,你可以执行:
#移除污点
kubectl taint node k8s-worker-16 deploy=nginx:NoExecute-
kubectl taint node k8s-worker-21 deploy=nginx:NoExecute-
3、创建Deployment,观察pod调度情况,如下所示:
vim tolerations-2.yaml
apiVersion: apps/v1 #apiVersion是当前配置格式的版本
kind: Deployment #kind是要创建的资源类型,这里是Deploymnet
metadata: #metadata是该资源的元数据,name是必须的元数据项
name: nginx-deployment
labels:
app: nginx
spec: #spec部分是该Deployment的规则说明
replicas: 8 #relicas指定副本数量,默认为1
selector:
matchLabels:
app: nginx
template: #template定义Pod的模板,这是配置的重要部分
metadata: #metadata定义Pod的元数据,至少要顶一个label,label的key和value可以任意指定
labels:
app: nginx
spec: #spec描述的是Pod的规则,此部分定义pod中每一个容器的属性,name和image是必需的
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
tolerations: #容忍度属性
- key: "deploy" #label标签名称,对等于app: nginx中左边的app
operator: "Equal" #表示等值关系,即必须完全匹配,effect字段、value值必须与节点保持一致
value: "nginx" #label标签名称,对等于app: nginx中有右边的nginx,为空的话表示比配nginx="任意值",可以是app: nginx1或app: nginx2等,不能为空
effect: "NoExecute" #effect表示要匹配的排斥等级,NoSchedule、NoExecute、PreferNoSchedule,不能为空
tolerationSeconds: 30 #表示容忍的时间周期,必须是NoExecute,否则该字段将被忽略,没有设置,这意味着永远容忍污染,不会驱逐,0和负值将被视为0表示立即驱逐
如下图所示:
等待30秒后,如下图所示:
说明:这里设置为30秒,符合污点的节点创建并且运行1分钟后进入回收状态,新的pod又调度到此节点,一分钟后再次删除,创建、删除…一直下去。
结论:k8s-worker-16节点和k8s-worker-21节点都被打上污点,排斥等级为NoExecute,yaml文件中定义了pod的容忍度为NoExecute,与当前k8s-worker-16节点和k8s-worker-21节点污点排斥等级一致,则是可以正常调度的。这里要注意的是tolerationSeconds: 30,表示容忍的时间周期,必须是NoExecute,否则该字段将被忽略,没有设置,这意味着永远容忍污染,不会驱逐,0和负值将被视为0表示立即驱逐。
1、k8s集群worker节点默认是没有污点的,如下图所示:
2、使用命令kubectl taint给节点k8s-worker-16和k8s-worker-21增加污点,如下图所示:
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-16 deploy=nginx:NoSchedule
node/k8s-worker-16 tainted
[root@k8s-client-17 yaml]# kubectl taint node k8s-worker-21 deploy=nginx:NoSchedule
node/k8s-worker-21 tainted
[root@k8s-client-17 yaml]# kubectl describe nodes k8s-worker-16 | grep Taints
Taints: deploy=nginx:NoSchedule
[root@k8s-client-17 yaml]# kubectl describe nodes k8s-worker-21 | grep Taints
Taints: deploy=nginx:NoSchedule
若要移除上述命令所添加的污点,你可以执行:
#移除污点
kubectl taint node k8s-worker-16 deploy=nginx:NoSchedule-
kubectl taint node k8s-worker-21 deploy=nginx:NoSchedule-
3、创建Deployment,观察pod调度情况,如下所示:
vim tolerations-3.yaml
apiVersion: apps/v1 #apiVersion是当前配置格式的版本
kind: Deployment #kind是要创建的资源类型,这里是Deploymnet
metadata: #metadata是该资源的元数据,name是必须的元数据项
name: nginx-deployment
labels:
app: nginx
spec: #spec部分是该Deployment的规则说明
replicas: 8 #relicas指定副本数量,默认为1
selector:
matchLabels:
app: nginx
template: #template定义Pod的模板,这是配置的重要部分
metadata: #metadata定义Pod的元数据,至少要顶一个label,label的key和value可以任意指定
labels:
app: nginx
spec: #spec描述的是Pod的规则,此部分定义pod中每一个容器的属性,name和image是必需的
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
tolerations: #容忍度属性
- key: "deploy" #label标签名称,对等于app: nginx中左边的app
operator: "Equal" #表示等值关系,即必须完全匹配,effect字段、value值必须与节点保持一致
value: "nginx" #label标签名称,对等于app: nginx中有右边的nginx,为空的话表示比配nginx="任意值",可以是app: nginx1或app: nginx2等,不能为空
effect: "NoSchedule" #effect表示要匹配的排斥等级,NoSchedule、NoExecute、PreferNoSchedule,不能为空
如下图所示:
结论:k8s-worker-16节点和k8s-worker-21节点都被打上污点,排斥等级为NoSchedule,按照规则新创建的pod是调度不了的,但是在yaml文件中定义了pod的容忍度为NoSchedule,与当前k8s-worker-16节点和k8s-worker-21节点污点排斥等级一致,则是可以正常调度的。
更多详细内容请参考:企业级K8s集群运维实战