kubernetes 节点污点调度与pod容忍度(42)

2023年 7月 16日 87.4k 0

在前面的两种方式中,都是由pod去选择的,节点被动选择运行。而污点调度方式就给了节点的选择权。让节点可以选择让那些pod运行在节点上。总的来说,污点就是定义在节点上的键值属性数据。

  • 此前,我们知道,键值属性有三类,第一类叫标签,第二类叫注解,第三类便是污点。污点用在节点之上,而前两类所有资源对象都可以使用。
  • pod亲和性和node亲和性都是pod的属性,而污点是节点的属性

污点也是一种键值属性,主要用来让节点拒绝那些不能容忍的pod,因此需要在pod对象上定义容忍度。而容忍度也是pod对象上的第三类键值数据,并且是一个列表。

kubernetes分别有一个预选策略PodToleratesNodeTaints和优选函数taint_toleration,分别完成基于所谓的污点和容忍度的调用逻辑,并且作为选择中标准的一种来进行定义。

污点定义在node.spec.taints:

  • effect

定义当pod不能容忍这个污点时, 采取的行为是什么。这种排斥的效果有三种,分别是:

Noschedule: 仅仅影响调度过程,对现存的pod对象不产生影响。如果不能容忍,就不进行调度。

NoExecute: 不仅影响调度,也影响现存pod对象; 如果不能容忍的pod将会被驱逐。

PreferNoschedule:不能容忍就不能调度,但是如果没有其他地方运行,那也可以。

  • key
  • timeAdded
  • value 可以为空

在pod对象上定义容忍度的时候,还支持两种操作,等值比较,存在性判断

等值比较

容忍度与污点必须在key,value和effect上完全匹配,

存在性判断

表示二者的key,timeAdded必须匹配,value 可以为空

另外一个节点可以配置多个污点,一个pod也可以有多个容忍度,只不过两者匹配的时候需要遵循以下逻辑:

1,检查每个有着容忍匹配容忍度的污点,不能匹配到的污点如果存在,如果有一个使用Noschedule标识,pod就无法调度

  • 我们在pod上定义三个容忍度,在节点之上定义两个污点。如果容忍度中只包含了容忍了一个污点,那将只会匹配一个污点,这样的情况是存在的!所以我们要检查这种匹配度有多高!事实上这个pod不一定会运行在这个节点之上的。如下图:

高级调度方式-污点-4.png

逐一检查容忍度和对方的污点相匹配,节点上的每一个污点都需要被容忍,如果存在一个不被容忍,就需要看这个污点的条件。如果污点是effect.PreferNoschedule,那就可以运行的。如果是Noschedule就不能调度成功。如上图。

如果至少有一个污点不匹配,如果是NoExecute,且节点已经运行有此pod,此pod将被驱逐。

总结:如果一个节点定义了污点,一个pod能否调度上来。首先检查能够被匹配到的污点和容忍度,检查完能够被容忍的污点后,检查不能够被容忍度容忍的污点,检查不能够被容忍度容忍污点,就检查effect 排斥的三种行为,如果是PreferNoschedule就可以继续调度,如果是Noschedule,且pod尚未调度到节点,就不能被调度到节点,Noschedule调度之前已经运行在节点的的pod仍然能够运行。如果是NoExecute,且pod尚未调度到节点,就不能被调度到节点,而且此前调度过来的已经运行的pod,如果被修改了污点,就意味着运行的这个pod也会被驱逐。

在master节点上,就是有污点的.NoSchedule.如果pod不能够容忍这个污点,pod就不能够调度到master节点上

[root@linuxea schedule]# kubectl describe node linuxea.master-1.com|grep Taints
Taints:             node-role.kubernetes.io/master:NoSchedule

并且master这个污点在启动的时候就被打上去。如果pod不能够容忍这个污点,就不会调度到master这个节点上,而一些其他的kubernetes组件肯定是容忍这个污点的。否则将调度不到master上,像api server就是NoExecute

[root@linuxea schedule]# kubectl describe pods kube-apiserver-linuxea.master-1.com  -n kube-system|grep Tolerations
Tolerations:       :NoExecute

另外还有flannel,flannel就更清楚地标记容忍度,包含master 污点node-role.kubernetes.io/master,并且是NoSchedule。这些信息就影响这调度

[root@linuxea schedule]# kubectl describe pods kube-flannel-ds-amd64-mnrwp -n kube-system
Node-Selectors:  beta.kubernetes.io/arch=amd64
Tolerations:     node-role.kubernetes.io/master:NoSchedule
                 node.kubernetes.io/disk-pressure:NoSchedule
                 node.kubernetes.io/memory-pressure:NoSchedule
                 node.kubernetes.io/not-ready:NoExecute
                 node.kubernetes.io/unreachable:NoExecute
Events:          <none>

管理节点污点

NoSchedule

此刻有三个节点,将node1标记为线上,容忍行为效果是NoSchedule。pod不运行在node1,node1只会运行生产pod

[root@linuxea schedule]# kubectl taint node linuxea.node-1.com node_type=produce:NoSchedule
node/linuxea.node-1.com tainted
  • 随意apply几个pod,不设置容忍度
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dpment-linuxea
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: linuxea_app
      version: v0.1.32
  template:
    metadata:
      labels:
        app: linuxea_app
        version: v0.1.32
    spec:
      containers:
      - name: nginx-a
        image: marksugar/nginx:1.14.b
        ports:
        - name: http
          containerPort: 80

apply

[root@linuxea schedule]# kubectl apply -f demo.yaml 
deployment.apps/dpment-linuxea created

在查看,pod运行在node2和node3,跳过了node1

[root@linuxea schedule]# kubectl get pods -o wide
NAME                              READY     STATUS    RESTARTS   AGE       IP            NODE                 NOMINATED NODE
dpment-linuxea-648d599b5f-j68cb   1/1       Running   0          5s        172.16.5.20   linuxea.node-3.com   <none>
dpment-linuxea-648d599b5f-sh2tn   1/1       Running   0          5s        172.16.4.26   linuxea.node-2.com   <none>
dpment-linuxea-648d599b5f-vrjtl   1/1       Running   0          5s        172.16.5.21   linuxea.node-3.com   <none>

甚至,我们可以删掉在apply一次

[root@linuxea schedule]# kubectl delete -f demo.yaml 
deployment.apps "dpment-linuxea" deleted

这些pod没有设置node上的容忍度,仍然不会调度到node1,说明污点是有效的。

[root@linuxea schedule]# kubectl get pods -o wide
NAME                              READY     STATUS    RESTARTS   AGE       IP            NODE                 NOMINATED NODE
dpment-linuxea-648d599b5f-hc9n6   1/1       Running   0          5s        172.16.4.27   linuxea.node-2.com   <none>
dpment-linuxea-648d599b5f-kjsgd   1/1       Running   0          5s        172.16.5.22   linuxea.node-3.com   <none>
dpment-linuxea-648d599b5f-wp4pz   1/1       Running   0          5s        172.16.4.28   linuxea.node-2.com   <none>

NoExecute

此刻,尝试NoExecute。现在node2节点上运行了一个pod,我们在node2上在打一个污点node_type=dev:NoExecute,并且是容忍的行为是NoExecute,也就是说,如果node2上的pod不是污点dev的,并且此前运行不是dev的pod,也会被驱逐

[root@linuxea schedule]# kubectl taint node linuxea.node-2.com node_type=dev:NoExecute
node/linuxea.node-2.com tainted

node2上的pod没有容忍这个污点,被驱逐了,但是还有node3没有任何污点,所以运行在node3之上

[root@linuxea schedule]# kubectl get pods -o wide -w
NAME                              READY     STATUS        RESTARTS   AGE       IP            NODE                 NOMINATED NODE
dpment-linuxea-648d599b5f-87jhp   1/1       Running       0          12s       172.16.5.23   linuxea.node-3.com   <none>
dpment-linuxea-648d599b5f-fgwhd   1/1       Running       0          12s       172.16.5.25   linuxea.node-3.com   <none>
dpment-linuxea-648d599b5f-hc9n6   1/1       Terminating   0          31m       172.16.4.27   linuxea.node-2.com   <none>
dpment-linuxea-648d599b5f-kjsgd   1/1       Running       0          31m       172.16.5.22   linuxea.node-3.com   <none>
dpment-linuxea-648d599b5f-wp4pz   1/1       Terminating   0          31m       172.16.4.28   linuxea.node-2.com   <none>
dpment-linuxea-648d599b5f-hc9n6   0/1       Terminating   0         31m       172.16.4.27   linuxea.node-2.com   <none>
dpment-linuxea-648d599b5f-hc9n6   0/1       Terminating   0         31m       172.16.4.27   linuxea.node-2.com   <none>
dpment-linuxea-648d599b5f-hc9n6   0/1       Terminating   0         31m       172.16.4.27   linuxea.node-2.com   <none>
dpment-linuxea-648d599b5f-hc9n6   0/1       Terminating   0         31m       172.16.4.27   linuxea.node-2.com   <none>
dpment-linuxea-648d599b5f-wp4pz   0/1       Terminating   0         31m       <none>    linuxea.node-2.com   <none>
dpment-linuxea-648d599b5f-wp4pz   0/1       Terminating   0         31m       <none>    linuxea.node-2.com   <none>
dpment-linuxea-648d599b5f-wp4pz   0/1       Terminating   0         31m       <none>    linuxea.node-2.com   <none>

而后都运行在node3之上,如果node3也有污点,且pod不能容忍,那就会pending.

[root@linuxea schedule]# kubectl get pods -o wide 
NAME                              READY     STATUS    RESTARTS   AGE       IP            NODE                 NOMINATED NODE
dpment-linuxea-648d599b5f-87jhp   1/1       Running   0          1m        172.16.5.23   linuxea.node-3.com   <none>
dpment-linuxea-648d599b5f-fgwhd   1/1       Running   0          1m        172.16.5.25   linuxea.node-3.com   <none>
dpment-linuxea-648d599b5f-kjsgd   1/1       Running   0          32m       172.16.5.22   linuxea.node-3.com   <none>

管理Pod容忍度

在pods.spec.tolerations字段中

  • tolerationSeconds 表示,如果被驱逐,驱逐前等待时间。默认0秒 ,立即被驱逐
  • key 列表
  • operator 操作符

    Exists : 判断污点存在与否,存在就可以,且不管是什么值都匹配

    Equal: 容忍度必须能够精确容忍对方的污点值

在上述中,使用Exists ,只要是node_type在就容忍,如果是Equal,只要是node_type且要么容忍dev污点值,元要么produce的污点值,需要明确指定

  • 我们先将linuxea.node-3.com添加污点node_type=Pre-production:NoSchedule,容忍行为NoSchedule
[root@linuxea schedule]# kubectl taint node linuxea.node-3.com node_type=Pre-production:NoSchedule
node/linuxea.node-3.com tainted

此刻在apply 刚才没有容忍度的pod就会pending

[root@linuxea schedule]# kubectl get pods
NAME                              READY     STATUS    RESTARTS   AGE
dpment-linuxea-648d599b5f-cxfv6   0/1       Pending   0          3s
dpment-linuxea-648d599b5f-ghphv   0/1       Pending   0          3s
dpment-linuxea-648d599b5f-rvpw2   0/1       Pending   0          3s

NoExecute

此刻使用NoExecute也会pending.因为污点和容忍度不完全等。如下:

  • 首先操作符为Equal,精确容忍,而node1的污点node_type:produce的容忍行为是NoSchedule,而在文件中定义的是容忍行为是NoExecute,唯一的键值匹配produce也不符合NoExecute
  • tolerationSeconds表示,一旦容忍将在30秒后进行驱逐

综上所述,pod没有容忍任何node的污点,所以pending

      tolerations: 
      - key: "node_type"
        operator: "Equal"
        value: "produce"
        effect: "NoExecute"
        tolerationSeconds: 30

完整yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dpment-linuxea
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: linuxea_app
      version: v0.1.32
  template:
    metadata:
      labels:
        app: linuxea_app
        version: v0.1.32
    spec:
      containers:
      - name: nginx-a
        image: marksugar/nginx:1.14.b
        ports:
        - name: http
          containerPort: 80
      tolerations: 
      - key: "node_type"
        operator: "Equal"
        value: "produce"
        effect: "NoExecute"
        tolerationSeconds: 30          

NoSchedule

使用NoSchedule就不需要指定tolerationSeconds的驱逐时间,因为NoSchedule只会拒绝不能容忍的,对于在上一次已经运行的pod不驱逐

  • 操作符精确匹配具有污点为node_type为produce的节点
  • 而node_type为produce污点的节点是node1

精确满足容忍度的节点是node1,这三个pod将会调度到node1上。如下:

      tolerations: 
      - key: "node_type"
        operator: "Equal"
        value: "produce"
        effect: "NoSchedule"
#        tolerationSeconds: 10

yaml如下

[root@linuxea schedule]# cat demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dpment-linuxea
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: linuxea_app
      version: v0.1.32
  template:
    metadata:
      labels:
        app: linuxea_app
        version: v0.1.32
    spec:
      containers:
      - name: nginx-a
        image: marksugar/nginx:1.14.b
        ports:
        - name: http
          containerPort: 80
      tolerations: 
      - key: "node_type"
        operator: "Equal"
        value: "produce"
        effect: "NoSchedule"
#        tolerationSeconds: 10

apply

[root@linuxea schedule]# kubectl apply -f demo.yaml 
deployment.apps/dpment-linuxea configured

而后就调度到具有kye是node_type:produce,行为是NoSchedule污点的node1之上,因为yaml文件中容忍了node1的污点

[root@linuxea schedule]# kubectl get pods -o wide -w
NAME                             READY     STATUS    RESTARTS   AGE       IP           NODE                 NOMINATED NODE
dpment-linuxea-df4b6f749-5jlcb   1/1       Running   0          5s        172.16.3.4   linuxea.node-1.com   <none>
dpment-linuxea-df4b6f749-rzndk   1/1       Running   0          4s        172.16.3.5   linuxea.node-1.com   <none>
dpment-linuxea-df4b6f749-wwpck   1/1       Running   0          3s        172.16.3.6   linuxea.node-1.com   <none>

Exists

我们在改改,修改成污点只要键是node_type的就容忍,也就是只要键是node_type的污点都调度到上面,将操作符改成Exists,我们知道Exists,只要是匹配到的就可以被容忍,如果没有其他的条件的话

上述中,node污点分别是:

  • linuxea.node-1.com node_type=produce:NoSchedule
  • linuxea.node-2.com node_type=dev:NoExecute
  • linuxea.node-3.com node_type=Pre-production:NoSchedule

yaml修改后如下

      tolerations: 
      - key: "node_type"
        operator: "Exists"
        value: ""
        effect: "NoSchedule"

注意:尽管污点的键值在三个节点都是node_type。但是node1和node3的行为效果是NoSchedule,而node2行为效果是NoExecute,因为行为效果不同,所以也只会调度在node1和node3的污点节点上

yaml完整如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dpment-linuxea
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: linuxea_app
      version: v0.1.32
  template:
    metadata:
      labels:
        app: linuxea_app
        version: v0.1.32
    spec:
      containers:
      - name: nginx-a
        image: marksugar/nginx:1.14.b
        ports:
        - name: http
          containerPort: 80
      tolerations: 
      - key: "node_type"
        operator: "Exists"
        value: ""
        effect: "NoSchedule"

apply

[root@linuxea schedule]# kubectl  apply -f demo.yaml 
deployment.apps/dpment-linuxea configured

apply后会进行重新调度,调度后到了node1和node3之上

[root@linuxea schedule]# kubectl get pods -o wide
NAME                              READY     STATUS        RESTARTS   AGE       IP            NODE                 NOMINATED NODE
dpment-linuxea-798ff6bc87-8kpw2   1/1       Running       0          12s       172.16.5.33   linuxea.node-3.com   <none>
dpment-linuxea-798ff6bc87-9fgn4   1/1       Running       0          14s       172.16.3.7    linuxea.node-1.com   <none>
dpment-linuxea-798ff6bc87-fgpcr   1/1       Running       0          15s       172.16.5.32   linuxea.node-3.com   <none>
dpment-linuxea-df4b6f749-5jlcb    1/1       Terminating   0          19m       172.16.3.4    linuxea.node-1.com   <none>
dpment-linuxea-df4b6f749-rzndk    1/1       Terminating   0          19m       172.16.3.5    linuxea.node-1.com   <none>
dpment-linuxea-df4b6f749-wwpck    1/1       Terminating   0          19m       172.16.3.6    linuxea.node-1.com   <none>

那如果要调度到node2的污点上,改成NoExecute即可

但是这样一来,就只有node2有污点的行为效果是NoExecute,而node1和node3没有,就只能调度到Node2了。

      tolerations: 
      - key: "node_type"
        operator: "Exists"
        value: ""
        effect: "NoExecute"

而后apply

[root@linuxea schedule]# kubectl apply -f demo.yaml 
deployment.apps/dpment-linuxea configured

就都调度到node2上了。

[root@linuxea schedule]# kubectl get pods -o wide -w
NAME                              READY     STATUS        RESTARTS   AGE       IP            NODE                 NOMINATED NODE
dpment-linuxea-798ff6bc87-8kpw2   1/1       Terminating   0          14m       172.16.5.33   linuxea.node-3.com   <none>
dpment-linuxea-798ff6bc87-9fgn4   1/1       Terminating   0          14m       172.16.3.7    linuxea.node-1.com   <none>
dpment-linuxea-798ff6bc87-fgpcr   1/1       Terminating   0          14m       172.16.5.32   linuxea.node-3.com   <none>
dpment-linuxea-7b54d565c7-2md6h   1/1       Running       0          2s        172.16.4.31   linuxea.node-2.com   <none>
dpment-linuxea-7b54d565c7-5pmth   1/1       Running       0          3s        172.16.4.30   linuxea.node-2.com   <none>
dpment-linuxea-7b54d565c7-v6bdq   1/1       Running       0          5s        172.16.4.29   linuxea.node-2.com   <none>

那如果我想在三个节点都想被容忍,我们在修改下,将effect制空,如下:

      tolerations: 
      - key: "node_type"
        operator: "Exists"
        value: ""
        effect: ""

这样一来,value值为空,effect的容忍效果也为空,那就只有键生效,相同为node_type的键有node1,node2,node3三个node都符合。就会调度到三个节点上

[root@linuxea schedule]# kubectl apply -f demo.yaml 
deployment.apps/dpment-linuxea configured
[root@linuxea schedule]# kubectl get pods -o wide -w
NAME                              READY     STATUS        RESTARTS   AGE       IP            NODE                 NOMINATED NODE
dpment-linuxea-7748786749-4s2qv   1/1       Running       0          5s        172.16.4.32   linuxea.node-2.com   <none>
dpment-linuxea-7748786749-6llcz   1/1       Running       0          6s        172.16.5.34   linuxea.node-3.com   <none>
dpment-linuxea-7748786749-dv4nf   1/1       Running       0          4s        172.16.3.8    linuxea.node-1.com   <none>

相关文章

LeaferJS 1.0 重磅发布:强悍的前端 Canvas 渲染引擎
10分钟搞定支持通配符的永久有效免费HTTPS证书
300 多个 Microsoft Excel 快捷方式
一步步配置基于kubeadmin的kubevip高可用
istio全链路传递cookie和header灰度
REST Web 服务版本控制

发布评论