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在某些節點上的部署。