10.容忍和污点
1.Taint 污点 1.1.什么是污点 Taint作用在节点上,能够使节点排斥一类特定的Pod,也就是不能“兼容”该节点的污点的Pod。 注意:一个节点可以部署多个污点 1.2.污点出现背景 之所以出现污点,是因为要避免Pod被分配到不合适的节点,比如有一批GPU服务器只能部署要使用GPU的Pod
1.Taint 污点 1.1.什么是污点 Taint作用在节点上,能够使节点排斥一类特定的Pod,也就是不能“兼容”该节点的污点的Pod。 注意:一个节点可以部署多个污点 1.2.污点出现背景 之所以出现污点,是因为要避免Pod被分配到不合适的节点,比如有一批GPU服务器只能部署要使用GPU的Pod
Taint作用在节点上,能够使节点排斥一类特定的Pod,也就是不能“兼容”该节点的污点的Pod。
注意:一个节点可以部署多个污点!!!
之所以出现污点,是因为要避免Pod被分配到不合适的节点,比如有一批GPU服务器只能部署要使用GPU的Pod。每个节点上都可以应用一个或多个Taint,这表示对于那些不能容忍这些Taint的Pod是不能部署在该服务器上的。如果Pod配置了Toleration,则表示这些Pod可以被调度到设置了Taint的节点上,当然没有设置Taint的节点也是可以部署的。
污点分为外置污点和内置污点,主要说明如下:
当某种条件为真时,节点控制器会自动给节点添加一个污点。当前内置的污点包括:
node.kubernetes.io/not-ready:节点未准备好。这相当于节点状况 Ready 的值为 "False"。node.kubernetes.io/unreachable:节点控制器访问不到节点. 这相当于节点状况 Ready 的值为 "Unknown"。node.kubernetes.io/memory-pressure:节点存在内存压力。node.kubernetes.io/disk-pressure:节点存在磁盘压力。node.kubernetes.io/pid-pressure: 节点的 PID 压力。node.kubernetes.io/network-unavailable:节点网络不可用。node.kubernetes.io/unschedulable: 节点不可调度。node.cloudprovider.kubernetes.io/uninitialized:如果 kubelet 启动时指定了一个“外部”云平台驱动, 它将给当前节点添加一个污点将其标志为不可用。在 cloud-controller-manager 的一个控制器初始化这个节点后,kubelet 将删除这个污点。在节点被驱逐时,节点控制器或者 kubelet 会添加带有 NoExecute 效果的相关污点。 如果异常状态恢复正常,kubelet 或节点控制器能够移除相关的污点。但是被驱逐的Pod需要手动进行删除。
污点一般用于调度Pod部署的节点,常用调度场景如下:
创建一个污点(一个节点可以有多个污点),格式如下
# kubectl taint nodes NODE_NAME TAINT_KEY=TAINT_VALUE:EFFECT创建一个污点(一个节点可以有多个污点),示例如下
# kubectl taint nodes k8s-node01 ssd=true:PreferNoScheduleEFFECT规则如下:
针对NoExecute,我们可以自定义驱逐时间(默认300s),下面配置示例是3600秒:
污点的使用一般涉及到四个方面,分别是增、删、改、查。
在k8s-master01节点上给k8s-node01节点打上污点
# kubectl taint nodes k8s-node01 ssd=true:NoSchedule这里删除污点涉及两种方式:
第一种基于Key删除:
在k8s-master01节点上给k8s-node01节点删除指定污点
[root@k8s-master01 ~]# kubectl taint nodes k8s-node01 ssd=true:NoSchedule-
node/k8s-node01 untainted第二种基于Key+Effect删除:
在k8s-master01节点上给k8s-node01节点删除全部污点
[root@k8s-master01 ~]# kubectl taint nodes k8s-node01 ssd-
node/k8s-node01 untainted小结:第二种方式相对于第一种方式删除范围更大
在k8s-master01节点上给k8s-node01节点修改污点,这里注意原来的不删除
[root@k8s-master01 ~]# kubectl taint nodes k8s-node01 ssd=false:PreferNoSchedule --overwrite
node/k8s-node01 modified在k8s-master01节点上以命令的方式查看污点
[root@k8s-master01 ~]# kubectl describe node k8s-node01 | grep Taint
Taints: ssd=false:NoSchedule在k8s-master01节点上查看污点使用了 kubectl 的 get 命令,结合 -o(或 --output)选项和 go-template 模板来指定输出格式
[root@k8s-master01 ~]# kubectl get node k8s-node01 -o go-template --template '{{.spec.taints}}'
[map[effect:NoExecute key:ssd value:true] map[effect:NoSchedule key:ssd value:true]]容忍度(Toleration)是应用于 Pod 上的。容忍度允许调度器调度带有对应污点的 Pod。 容忍度允许调度但并不保证调度。
污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod, 是不会被该节点接受的。
当我们给节点打上污点后,此时如果我们想让某些Pod部署在已经打过污点的节点,这就需要涉及到容忍了。我们可以把污点比喻成锁,容忍相当于其对应的钥匙,要想打开锁,我们需要配置锁的钥匙才能打开。
容忍配置在Pod里面,一般有四种方式:
方式一:完全匹配
方式二:不完全匹配
方式三:大范围匹配(不推荐key为内置Taint)
方式四:匹配所有(不推荐)
tolerations:
-
下面我们先在k8s-master01节点打上指定标签,再在Pod里面添加容忍配置,查看容忍有无配置对Pod状态的影响。
1.在k8s-master01节点上给k8s-node01节点打上标签和污点
2.在k8s-master01节点上查看ssd标签的节点
3.在k8s-masTer01节点上定义一个yaml文件
4.部署
[root@k8s-master01 Taint]# kubectl create -f toleration.yaml
pod/nginx created5.查看pod状态,观察状态为Running
6.在k8s-masTer01节点上删除Pod
[root@k8s-master01 Taint]# kubectl delete -f toleration.yaml
pod "nginx" deleted7.在k8s-masTer01节点上修改yaml文件,取消容忍
8.在k8s-masTer01节点上重新部署
[root@k8s-master01 Taint]# kubectl create -f toleration.yaml
pod/nginx created9.在k8s-masTer01节点上查看Pod状态,发现一直为Pending
10.在k8s-masTer01节点上详细查看Pod状态
11.修改yaml文件设置完全匹配
12.在k8s-masTer01节点上重新部署,观察到Pod节点重新变回Running
如果想将某些节点专门分配给特定的一组用户使用,可以给这些节点添加一个Taint
# kubectl taint nodes nodename ssd=true:NoSchedule然后给这组用户的Pod添加一个相对应的Toleration,那么拥有上述Toleration的Pod就能够被分配到上述专用节点,同时也能够被分配到集群中的其他节点。
查看
如果希望这些Pod只能分配到上述专用节点中,那么还需要给这些专用节点另外添加一个和上述Taint类似的Label(例如dedicated=groupName)
[root@k8s-master01 ~]# kubectl label node k8s-node01 ssd=true:NoSchedule
node/k8s-node01 labeled然后给Pod增加节点亲和性要求或者使用NodeSelector,就能将Pod只分配到添加了dedicated=groupName标签的节点上。
查看
在部分节点上配备了特殊硬件(比如GPU)的集群中,我们只允许特定的Pod才能部署在这些节点上。这时可以使用Taint进行控制,添加Taint,如kubectl taint nodes nodename special=true:NoSchedule或者kubectl taint nodes nodename special=true:PreferNoSchedule
# kubectl taint nodes nodename special=true:NoSchedule然后给需要部署在这些节点上的Pod添加相匹配的Toleration即可。
Taint的effect值NoExecute,它会影响已经在节点上运行的Pod。如果Pod不能忍受effect值为NoExecute的Taint,那么Pod将会被马上驱逐。如果能够忍受effect值为NoExecute的Taint,但是在Toleration定义中没有指定tolerationSeconds,则Pod还会一直在这个节点上运行。
针对NoExecute,我们可以自定义驱逐时间(默认300s),下面配置示例是3600秒:
创建
root@k8s-master01:~/hhh# kubectl create -f toleration.yaml
deployment.apps/tolerations-second created去node-01
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600tolerations:
- key: "taintKey"
operator: "Equal"
value: "taintValue"
effect: "NoSchedule"
key: "taintKey":表示要容忍的污点的键为 "taintKey"。
operator: "Equal":表示要容忍的污点的操作符为等于。
value: "taintValue":表示要容忍的污点的值为 "taintValue"。
effect: "NoSchedule":表示当节点上存在匹配的污点时,不会进行调度。
这意味着只有具有键为 "taintKey"、值为 "taintValue" 的污点的节点上不会调度 Pod。其他节点仍然可以调度 Pod。tolerations:
- key: "taintKey"
operator: "Exists"
effect: "NoSchedule"
key: "taintKey":表示要容忍的污点的键为 "taintKey"。
operator: "Exists":表示要容忍的污点的操作符为存在(即只要节点上存在指定键的污点即可)。
effect: "NoSchedule":表示当节点上存在匹配的污点时,不会进行调度。
这意味着只要节点上存在键为 "taintKey" 的污点,无论其值是什么,都不会调度 Pod 到该节点上。- key: "taintKey"
operator: "Exists"
key: "taintKey":表示要容忍的污点的键为 "taintKey"。
operator: "Exists":表示要容忍的污点的操作符为存在(即只要节点上存在指定键的污点即可)。
这意味着只要节点上存在键为 "taintKey" 的污点,无论其值是什么,都会被容忍。这将允许 Pod 调度到具有该污点的节点上。[root@k8s-master01 ~]# kubectl label node k8s-node01 ssd=true
node/k8s-node01 labeled
root@k8s-master01:~/hhh# kubectl taint node node-01 ssd=true:NoSchedule
node/node-01 taintedroot@k8s-master01:~/hhh# kubectl get nodes -l ssd
NAME STATUS ROLES AGE VERSION
node-01 Ready node 32d v1.28.2[root@k8s-master01 Taint]# vim toleration.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
ssd: "true"
tolerations:
- key: "ssd"
operator: "Exists"root@k8s-master01:~/hhh# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 6s 10.200.85.239 node-01 <none> <none>[root@k8s-master01 Taint]# vim toleration.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
ssd: "true"
#tolerations:
#- key: "ssd"
# operator: "Exists"root@k8s-master01:~/hhh# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 0/1 Pending 0 2s <none> <none> <none> <none>root@k8s-master01:~/hhh# kubectl describe po nginx
Name: nginx
Namespace: default
Priority: 0
Service Account: default
Node: <none>
Labels: env=test
Annotations: <none>
Status: Pending
IP:
IPs: <none>
Containers:
nginx:
Image: nginx
Port: <none>
Host Port: <none>
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-4k4x8 (ro)
Conditions:
Type Status
PodScheduled False
Volumes:
kube-api-access-4k4x8:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: ssd=true
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 37s default-scheduler 0/6 nodes are available: 1 node(s) had untolerated taint {ssd: true}, 2 node(s) didn't match Pod's node affinity/selector, 3 node(s) were unschedulable. preemption: 0/6 nodes are available: 6 Preemption is not helpful for scheduling..[root@k8s-master01 Taint]# vim toleration.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
ssd: "true"
#以下是主要修改的参数
tolerations:
- key: "ssd"
operator: "Equal"
value: "true"[root@k8s-master01 Taint]# kubectl delete -f toleration.yaml
pod "nginx" deleted
[root@k8s-master01 Taint]# kubectl create -f toleration.yaml
pod/nginx created
[root@k8s-master01 Taint]# kubectl get -f toleration.yaml -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 3s 10.200.85.240 node-01 <none> <none>...
...
...
tolerations:
- key: "ssd"
operator: "Equal"
value: "true"
effect: "NoSchedule"root@k8s-master01:~/hhh# cat toleration.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15.12
ports:
- containerPort: 80
tolerations:
- key: "ssd"
operator: "Equal"
value: "true"
effect: "NoSchedule"
root@k8s-master01:~/hhh# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-7c678d89c-88hx6 1/1 Running 0 13s 10.200.58.220 node-02 <none> <none>
nginx-deployment-7c678d89c-bsk67 1/1 Running 0 13s 10.200.135.148 node-03 <none> <none>
nginx-deployment-7c678d89c-h9l69 1/1 Running 0 13s 10.200.85.242 node-01 <none> <none>...
...
...
nodeSelector:
ssd:"true"
...
...
...root@k8s-master01:~/hhh# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-5dbb598666-84shc 1/1 Running 0 4s 10.200.85.245 node-01 <none> <none>
nginx-deployment-5dbb598666-lbgjt 1/1 Running 0 4s 10.200.85.243 node-01 <none> <none>
nginx-deployment-5dbb598666-xcrmb 1/1 Running 0 4s 10.200.85.244 node-01 <none> <none>
...
...
...
tolerations:
- key: "special"
operator: "Equal"
value: "true"
effect: "NoSchedule"tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: tolerations-second
name: tolerations-second
spec:
replicas: 1
selector:
matchLabels:
app: tolerations-second
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: tolerations-second
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx
name: nginx
resources:
requests:
cpu: 10m
nodeSelector:
ssd: "true"
tolerations:
- key: ssd
operator: Equal
value: "true"
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 10
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
labels:
app: tolerations-second
name: tolerations-second
spec:
ports:
- name: web
port: 80
protocol: TCP
targetPort: 80
selector:
app: tolerations-secondtolerations 字段定义了三个容忍规则:
第一个容忍规则:
key: ssd:指定要容忍的污点的键为 ssd。
operator: Equal:指定操作符为等于。
value: "true":指定要容忍的污点的值为 "true"。
第二个容忍规则:
effect: NoExecute:指定要容忍的污点的效果为 NoExecute。
key: node.kubernetes.io/unreachable:指定要容忍的污点的键为 node.kubernetes.io/unreachable。
operator: Exists:指定操作符为存在。
tolerationSeconds: 10:指定容忍的时间为 10 秒。
第三个容忍规则:
effect: NoExecute:指定要容忍的污点的效果为 NoExecute。
key: node.kubernetes.io/not-ready:指定要容忍的污点的键为 node.kubernetes.io/not-ready。
operator: Exists:指定操作符为存在。
tolerationSeconds: 10:指定容忍的时间为 10 秒。root@k8s-master01:~/hhh# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
tolerations-second-758757945f-7zv8m 1/1 Running 0 37s 10.200.85.246 node-01 <none> <none>root@k8s-node01:~# systemctl stop kubelet.service
root@k8s-master01:~/hhh# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master-01 Ready,SchedulingDisabled master 33d v1.28.2
master-02 Ready,SchedulingDisabled master 32d v1.28.2
master-03 Ready,SchedulingDisabled master 33d v1.28.2
node-01 NotReady node 33d v1.28.2
node-02 Ready node 33d v1.28.2
node-03 Ready node 33d v1.28.2
root@k8s-master01:~/hhh# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
tolerations-second-758757945f-6t7gh 0/1 Pending 0 8s <none> <none> <none> <none>
tolerations-second-758757945f-7zv8m 1/1 Terminating 0 6m12s 10.200.85.246 node-01 <none> <none>
开始漂移 Pending的原因是只配置了一个nodeSelector