天天看點

Kubernetes之Taints與Tolerations 污點和容忍

        NodeAffinity節點親和性,是Pod上定義的一種屬性,使Pod能夠按我們的要求排程到某個Node上,而Taints則恰恰相反,它可以讓Node拒絕運作Pod,甚至驅逐Pod。

        Taints(污點)是Node的一個屬性,設定了Taints(污點)後,因為有了污點,是以Kubernetes是不會将Pod排程到這個Node上的,

       于是Kubernetes就給Pod設定了個屬性Tolerations(容忍),隻要Pod能夠容忍Node上的污點,那麼Kubernetes就會忽略Node上的污點,就能夠(不是必須)把Pod排程過去。

        是以 Taints(污點)通常與Tolerations(容忍)配合使用。

1、設定污點:

 kubectl taint node [node] key=value[effect]   
      其中[effect] 可取值: [ NoSchedule | PreferNoSchedule | NoExecute ]
       NoSchedule :一定不能被排程。
       PreferNoSchedule:盡量不要排程。
       NoExecute:不僅不會排程,還會驅逐Node上已有的Pod。
  示例:kubectl taint node 10.3.1.16 test=16:NoSchedule      

2、去除污點:

 比如設定污點:
     kubectl taint node 10.3.1.16 test=16:NoSchedule
     kubectl taint node 10.3.1.16 test=16:NoExecute
 去除指定key及其effect:
     kubectl taint nodes node_name key:[effect]-    #(這裡的key不用指定value)
                
 去除指定key所有的effect: 
     kubectl taint nodes node_name key-
 
 示例:
     kubectl taint node 10.3.1.16 test:NoSchedule-
     kubectl taint node 10.3.1.16 test:NoExecute-
     kubectl taint node 10.3.1.16 test-      

3、Pod 容忍污點示例:

    首先給node設定個污點以觀察排程效果:

 kubectl taint node 10.3.1.16 test=16:NoSchedule      

    當pod沒有設定容忍時被排程到10.3.1.17:

apiVersion: v1
kind: Pod
metadata:
  name: pod-taints
  labels:
    os: ubuntu
spec:
  containers:
  - name: pod-tains
    image: 10.3.1.15:5000/ubuntu:16.04      
root@ubuntu:#kubectl create -f pod-taints.yaml
pod "pod-taints" created
###
root@ubuntu# kubectl get pod -o wide
NAME       READY    STATUS  RESTARTS  AGE   IP        NODE
pod-taints    1/1     Running   0     7s 192.168.77.216 10.3.1.17      

   給Pod設定容忍:

apiVersion: v1
kind: Pod
metadata:
  name: pod-taints
  labels:
    os: ubuntu
spec:
  tolerations: #設定容忍性
  - key: "test" 
   operator: "Equal"  #如果操作符為Exists,那麼value屬性可省略,如果不指定operator,則預設為Equal
   value: "16"
   effect: "NoSchedule"
  #意思是這個Pod要容忍的有污點的Node的key是test Equal 16,效果是NoSchedule,
  #tolerations屬性下各值必須使用引号,容忍的值都是設定Node的taints時給的值。
 containers:
   - name: pod-tains
   image: 10.3.1.15:5000/ubuntu:16.04      
root@ubuntu15:/data/yaml# kubectl get pod -o wide
NAME              READY     STATUS    RESTARTS   AGE       IP              NODE
pod-taints        1/1       Running      0       3m    192.168.150.216   10.3.1.16

#容忍後就立即排程到另外一個Node上了。需要在兩個Node的Pod數量不平衡時才能看到效果。      

對于tolerations屬性的寫法:

     其中的key、value、effect 與Node的Taint設定需保持一緻, 還有以下幾點說明:

         1、如果operator的值是Exists,則value屬性可省略。

         2、如果operator的值是Equal,則表示其key與value之間的關系是equal(等于)。

         3、如果不指定operator屬性,則預設值為Equal。

    另外,還有兩個特殊值:

         1、空的key 如果再配合Exists 就能比對所有的key與value ,也是是能容忍所有node的所有Taints。

         2、空的effect 比對所有的effect。

一個node上可以有多個污點:

     比如     test=16:NoScheduler   test2=16:NoSchedule  

而在Pod容忍時隻容忍了其中一個:

tolerations:
  - key: "test"
    operator: "Equal" 
    value: "16"
    effect: "NoSchedule"      

這樣的結果是此Pod無法被排程到key為test的node( 10.3.1.16)上去,因為此Node上設定了兩個污點,

而這個Pod隻比對到了一個污點,也就是隻容忍了一個污點,是以可以再加一個容忍:

 tolerations:
  - key: "test"
    operator: "Exists" 
    effect: "NoSchedule"
  - key: "test2"
    operator: "Equal"
    value: "16"
    effect: "NoSchedule"      

        如果在設定node的Taints(污點)之前,就已經運作了一些Pod,那麼這些Pod是否還能繼續在此Node上運作? 這就要看設定Taints污點時的effect(效果)了。

       如果effect的值是NoSchedule或PreferNoSchedule,那麼已運作的Pod仍然可以運作,隻是新Pod(如果沒有容忍)不會再往上排程。

       而如果effect的值是NoExecute,那麼此Node上正在運作的Pod,隻要沒有容忍的,立刻被驅逐。

       雖然是立刻被驅逐,但是K8S為了彰顯人性化,又給具有NoExecute效果的污點, 在容忍屬性中有一個可選的

          tolerationSeconds字段,用來設定這些Pod還可以在這個Node之上運作多久,給它們一點寬限的時間,到時間才驅逐。

       如果是以Pod來啟動的,那麼Pod被驅逐後, 将不會再被運作,就等于把它删除了。

       如果是deployment/rc,那麼删除的pod會再其它節點運作。

       如果是DaemonSet在此Node上啟動的Pod,那麼也不會再被運作,直到Node上的NoExecute污被去除或者Pod容忍。

#設定Pod的寬限時間
spec:
  tolerations: #設定容忍性
  - key: "test"
    operator: "Equal" #如果操作符為Exists,那麼value屬性可省略
    value: "16"
    effect: "NoExecute"
    tolerationSeconds: 180 
    #如果運作此Pod的Node,被設定了具有NoExecute效果的Taint(污點),這個Pod将在存活180s後才被驅逐。
    #如果沒有設定tolerationSeconds字段,将永久運作。      

       通過對Taints和Tolerations的了解,可以知道,通過它們可以讓某些特定應用,獨占一個Node:

給特定的Node設定一個Taint,隻讓某些特定的應用來容忍這些污點,容忍後就有可能會被排程到此特定Node,