48、K8S-调度机制-污点、容忍度调度之节点的Traint、Pod的tolerations

发布时间 2023-04-06 15:29:53作者: 小粉优化大师

Kubernetes学习目录

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>