Kubernetes使用節點污點和pod容忍度阻止節點調度到特定節點


  Kubernetes允許你去影響pod被調度到哪個節點。起初,只能通過在pod規范里指定節點選擇器來實現,后面其他的機制逐漸加入來擴容這項功能,本章將包括這些內容。

  現在要介紹的高級調度的兩個特性是節點污點,以及pod對於污點的容忍度,這些特性被用於限制哪些pod可以被調度到某一個節點。只有當一個pod容忍某個節點的污點,這個pod才能被調度到該節點。

  這與使用節點選擇器和節點親緣性有些許不同,節點選擇器和節點親緣性規則,是通過明確的在pod中添加的信息,來決定一個pod可以或者不可以被調度到哪些節點上。而污點則是在不修改已有pod信息的前提下,通過在節點上添加污點信息,來拒絕pod在某些節點上的部署。

 

1.介紹污點和容忍度

  學習節點污點的最佳路徑就是看一個己有的污點。默認情況下,這樣一個集群中的主節點需要設置污點,這樣才能保證只有控制面板pod才能部署在主節點上。

  顯示節點的污點信息

  可以通過kubectl describe node查看節點的污點信息,如以下代碼所示。

#代碼16.1顯示通過kubeadm創建的集群中的主節點信息
$ kubectl describe node master.k8s
Name:         master.k8s
Role:
Labels:       beta.kubernetes.io/arch=amd64
              beta.kubernetes.io/os=linux
              kubernetes.io/hostname=master.k8s
              node-role.kubernetes.io/master=
Annotations:  node.alpha.kubernetes.io/ttl=0
              volumes.kubernetes.io/controller-managed-attach-detach=true
Taints:       node-role.kubernetes.io/master:NoSchedule                    #主節點包含一個污點
...

  主節點包含一個污點,污點包含了一個key,value,以及一個effect,表現為<key>=<value>:<effect>。上面顯示的主節點的污點信息,包含一個為node-role.kubernetes.io/master的key,一個空的value,以及值為NoSchedule的effect。

  這個污點將阻止pod調度到這個節點上面,除非有pod能容忍這個污點,而通常容忍這個污點的pod都是系統級別pod(見圖16.1)。

  顯示pod的污點容忍度

  在一個通過kubeadm初始化的集群中,kube-proxy集群組件以pod的形式運行在每個節點上,其中也包括主節點。因為以pod形式運行的主節點組件同時也需要訪問Kubernetes服務。為了確保kube-proxy pod也能夠運行在主節點上,該pod需要添加相應的污點容忍度。該pod整體包含了3個污點容忍度,如以下代碼所示。

#代碼16.2 一個pod的污點容忍度
$ kubectl describe po kube-proxy-80wqm -n kube-system
...
Tolerations:    node-role.kubernetes.io/master=:NoSchedule
                node.alpha.kubernetes.io/notReady=:Exists:NoExecute
                node.alpha.kubernetes.io/unreachable=:Exists:NoExecute
...

  如你所見,第一個污點容忍度匹配了主節點的污點,表示允許這個kube-proxy pod被調度到主節點上。

  注意:盡管在pod的污點容忍度中顯示了等號,但是在節點的污點信息中卻沒有。當污點或者污點容忍度中的value為null時,kubectl故意將污點和污點容忍度進行不同形式的顯示。

  了解污點的效果

  另外兩個在kube-proxy pod上的污點定義了當節點狀態是沒有ready或者是unreachable時,該pod允許運行在該節點多長時間(時間用秒來表示,這里沒有顯示,但是podYAML中可以看到)。這兩個污點容忍度使用的效果是NoExecute而不是NoSchedule。

  每一個污點都可以關聯一個效果,效果包含了以下三種:

    • NoSchedule表示如果pod沒有容忍這些污點,pod則不能被調度到包含這些污點的節點上。
    • PreferNoSchedule是NoSchedule的一個寬松的版本,表示盡量阻止pod被調度到這個節點上,但是如果沒有其他節點可以調度,pod依然會被調度到這個節點上。
    • NoExecute不同於NoSchedule以及PreferNoSchedule,后兩者只在調度期間起作用,而NoExecute也會影響正在節點上運行着的pod。如果在一個節點上添加了NoExecute污點,那些在該節點上運行着的pod,如果沒有容忍這個NoExecute污點,將會從這個節點去除。

 

2.在節點上添加自定義污點

  假設你有一個單獨的Kubernetes集群,上面同時有生產環境和非生產環境的流量。其中最重要的一點是,非生產環境的pod不能運行在生產環境的節點上。可以通過在生產環境的節點上添加污點來滿足這個要求,可以使用kubectl taint命令來添加污點:

$ kubectl taint node node1.k8s node-type=production:NoSchedule
node "node1.k8s" tainted

  這個命令添加了一個taint,其中,key為node-type, value為production,效果為NoSchedule。如果現在部署一個常規pod的多個副本,會發現沒有一個pod被部署到添加了污點信息的節點上面,如以下代碼清單所示。

#代碼16.3 部署沒有污點容忍度的pod
$ kubectl run test --image busybox --replicas 5 -- sleep 99999
deployment "test" created
$ kubectl get po -o wide
NAME                READY  STATUS    RESTARTS   AGE   IP          NODE
test-196686-46ngl   1/1    Running   0          12s   10.47.0.1   node2.k8s
test-196686-73p89   1/1    Running   0          12s   10.47.0.7   node2.k8s
test-196686-77280   1/1    Running   0          12s   10.47.0.6   node2.k8s
test-196686-h9m8f   1/1    Running   0          12s   10.47.0.5   node2.k8s
test-196686-p85ll   1/1    Running   0          12s   10.47.0.4   node2.k8s

  現在,沒人能夠隨意地將pod部署到生產環境節點上了。

 

3.在pod上添加污點容忍度

  為了將生產環境pod部署到生成環境節點上,pod需要能容忍那些添加在節點上的污點。生產環境pod的清單里面需要增加以下的YAML代碼片段。

#代碼16.4 標記污點容忍度的生產環境部署:production-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: prod
spec:
  replicas: 5
  template:
    metadata:
      labels:
        app: prod
    spec:
    ...
      tolerations:
      - key: node-type                #此處的污點容忍度予許pod被調度到生產環境節點上
        operator: Equal
        value: production
        effect: NoSchedule

  如果運行了這個部署,將看到pod就會被調度到生產環境節點,如以下代碼所示。

#代碼16.5 包含污點容忍度的pod被調度到生產環境節點node1$ kubectl get po -o wide
NAME                READY  STATUS    RESTARTS   AGE   IP          NODE
prod-350605-1ph5h   0/1    Running   0          16s   10.44.0.3   node1.k8s
prod-350605-ctqcr   1/1    Running   0          16s   10.47.0.4   node2.k8s
prod-350605-f7pcc   0/1    Running   0          17s   10.44.0.6   node1.k8s
prod-350605-k7c8g   1/1    Running   0          17s   10.47.0.9   node2.k8s
prod-350605-rp1nv   0/1    Running   0          17s   10.44.0.4   node1.k8s

  生產環境pod也被調度到了非生產環境node2。為了防止這種情況發生,也需要在非生產環境的節點設置污點信息,例如node-type=non-production:NoSchedule。那么,也需要在非生產環境pod上添加了對應的污點容忍度。

 

4.了解污點和污點容忍度的使用場景

  節點可以擁有多個污點信息,而pod也可以有多個污點容忍度。正如你所見,污點可以只有一個key和一個效果,而不必設置value。污點容忍度可以通過設置Equal操作符Equal操作符來指定匹配的value(默認情況下的操作符),或者也可以通過設置Exists操作符來匹配污點的key。

  在調度時使用污點和容忍度

  污點可以用來組織新pod的調度(使用NoSchedule效果),或者定義非優先調度的節點(使用PreferNoSchedule效果),甚至是將已有的pod從當前節點剔除。

  可以用任何覺得合適的方式去設置污點和容忍度。例如,可以將一個集群分成多個部分,只允許開發團隊將pod調度到他們特定的節點上。當你的部分節點提供了某種特殊硬件,並且只有部分pod需要使用到這些硬件的時候,也可以通過設置污點和容忍度的方式來實現。

  配置節點失效之后的pod重新調度最長等待時間

  也可以配置一個容忍度,用於當某個pod運行所在的節點變成unready或者unreachable狀態時,Kubernetes可以等待該pod被調度到其他節點的最長等待時間。如果查看其中一個pod的容忍度信息,將看到兩條容忍度信息,如以下代碼所示。

#代碼16.6 帶有默認容忍度的pod
$ kubectl get po prod-350605-1ph5h -o yaml
  tolerations:
  - effect: NoExecute                          #該pod允許所在節點處於notReady狀態為300秒,之后pod將被重新調度
    key: node.alpha.kubernetes.io/notReady 
    operator: Exists 
    tolerationSeconds: 300 
  - effect: NoExecute         #同樣的配置應用於節點處理unreachable狀態
    key: node.alpha.kubernetes.io/unreachable 
    operator: Exists 
    tolerationSeconds: 300

  這兩個容忍度表示,該pod將容忍所在節點處於notReady或者unreachable狀態維持300秒。當Kubernetes控制器檢測到有節點處於notReady或者unreachable狀態時,將會等待300秒,如果狀態持續的話,之后將把該pod重新調度到其他節點上。

  當沒有定義這兩個容忍度時,他們會自動添加到pod上。如果你覺得對於你的pod來說,5分鍾太長的話,可以在pod描述中顯式地將這兩個容忍度設置得更短一些。

  注意:在1.8之前這是一個alpha階段的特性,在未來的Kubernetes版本中可能會有所改變。基於污點信息的pod剔除也不是默認啟用的,如果要啟用這個特性,需要在運行控制器管理器時使用--feature-gates=TaintBasedEvictions=true選項。

 

5.小結

  污點可以讓pod遠離特定的節點。污點就是在不修改已有pod信息的前提下,通過在節點上添加污點信息,來拒絕pod在某些節點上的部署。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM