k8s 汙點和容忍度
汙點taints
是定義在節點之上的鍵值型屬性資料,用於讓節點拒絕將Pod
排程運行於其上, 除非該Pod
物件具有接納節點汙點的容忍度。而容忍度tolerations
是定義在 Pod
物件上的鍵值型屬性資料,用於配置其可容忍的節點汙點,而且排程器僅能將Pod
物件排程至其能夠容忍該節點汙點的節點之上,如圖所示
節點選擇器nodeSelector
和節點親和性nodeAffinity
兩種排程方式都是通過在 Pod
物件上新增標籤選擇器來完成對特定型別節點標籤的匹配,它們實現的是由Pod
選擇節點的機制。而汙點和容忍度則是通過向節點新增汙點資訊來控制Pod
物件的排程結果,從而賦予了節點控制何種Pod
物件能夠排程於其上的主控權。簡單來說,節點親和性使得Pod
Pod
物件的能力。
Kubernetes
使用PodToleratesNodeTaints
預選策略和 TaintTolerationPriority
優選函式來完成此種類型的高階排程機制。
2、定義汙點和容忍度
汙點定義在節點的node Spec
中,而容忍度則定義在Pod
的podSpec
中,它們都是鍵值型資料,但又都額外支援一個效果effect
標記,語法格式為key=value:effect
,其中key
和value
的用法及格式與資源注俯-資訊相似, 而effect
則用於定義對Pod
物件的排斥等級,它主要包含以下三種類型
- NoSchedule
不能容忍此汙點的新Pod
Pod
物件不受影響。 - PreferNoSchedule
NoSchedule
的柔性約束版本,即不能容忍此汙點的新Pod
物件儘量不要排程至當前節點,不過無其他節點可供排程時也允許接受相應的Pod
物件。節點上現存的Pod
物件不受影響。 - NoExecute
不能容忍此汙點的新Pod
物件不可排程至當前節點,屬於強制型約束關係,而且節點上現存的Pod
物件因節點汙點變動或Pod
容忍度變動而不再滿足匹配規則時,Pod
物件將被驅逐。
在Pod
物件上定義容忍度時,它支援兩種操作符:一種是等值比較Equal
,表示容忍度與汙點必須在key
、value
和effect
Exists
,表示二者的key
和effect
必須完全匹配,而容忍度中的value
欄位要使用空值。
一個節點可以配置使用多個汙點,一個Pod
物件也可以有多個容忍度,不過二者在進行匹配檢查時應遵循如下邏輯。
- 首先處理每個有著與之匹配的容忍度的汙點
- 不能匹配到的汙點上,如果存在一個汙點使用了
NoSchedule
效用標識,則拒絕排程Pod
物件至此節點 - 不能匹配到的汙點上,若沒有任何一個使用了
NoSchedule
效用標識,但至少有一個使用了PreferNoScheduler
,則應儘量避免將Pod
物件排程至此節點 - 如果至少有一個不匹配的汙點使用了
NoExecute
效用標識,則節點將立即驅逐Pod
物件,或者不予排程至給定節點;另外,即便容忍度可以匹配到使用了NoExecute
效用標識的汙點,若在定義容忍度時還同時使用tolerationSeconds
屬性定義了容忍時限,則超出時限後其也將被節點驅逐。
使用kubeadm
部署的Kubernetes
叢集,其Master
節點將自動新增汙點資訊以阻止不能容忍此汙點的Pod
物件排程至此節點,因此,使用者手動建立的未特意新增容忍此汙點容忍度的Pod
物件將不會被排程至此節點
kubectl describe nodes k8s-master-01
Name: k8s-master-01
Roles: master
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=k8s-master-01
kubernetes.io/os=linux
node-role.kubernetes.io/master=
......
Taints: node-role.kubernetes.io/master:NoSchedule
Unschedulable: false
有些系統級應用,如kube-proxy
或者kube-flannel
等,都在資源建立時就新增上了相應的容忍度以確保它們被DaemonSet
控制器建立時能夠排程至Master
節點執行一個例項:
# kubectl -n kube-system describe pods calico-node-pw5n9
......
Node-Selectors: beta.kubernetes.io/os=linux
Tolerations: :NoSchedule
:NoExecute
CriticalAddonsOnly
node.kubernetes.io/disk-pressure:NoSchedule
node.kubernetes.io/memory-pressure:NoSchedule
node.kubernetes.io/network-unavailable:NoSchedule
node.kubernetes.io/not-ready:NoExecute
node.kubernetes.io/pid-pressure:NoSchedule
node.kubernetes.io/unreachable:NoExecute
node.kubernetes.io/unschedulable:NoSchedule
這類Pod
是構成Kubernetes
系統的基礎且關鍵性的元件,它們甚至還定義了更大的容忍度。從上面某calico-node
例項的容忍度定義來看,它還能容忍那些報告了磁碟壓力或記憶體壓力的節點,以及未就緒的節點和不可達的節點,以確保它們能在任何狀態下正常排程至叢集節點上執行。
3、管理節點的汙點
任何符合其鍵值規範要求的字串均可用於定義汙點資訊:僅可使用字母、數字、連線符、點號和下劃線,且僅能以字母或數字開頭,其中鍵名的長度上限為253
個字元,值最長為63
個字元。實踐中,汙點通常用於描述具體的部署規劃,它們的鍵名形如node-tppe
、node-role
、node-project
或node-geo
等,因此還可在必要時帶上域名以描述其額外的資訊,如node-type.linux.io
等。使用kubectl taint
命令即可向節點新增汙點,命令的語法格式如下:
kubectl taint nodes <node-name> <key>=<value>:<effect>
例如,使用node-type=production:NoSchedule
定義節點node01.linux.io
:
# kubectl taint nodes node01.linux.io node-type=production:NoSchedule
node "node01.linux.io" tainted
此時,nodeO1
上已有的Pod
物件不受影響,但新建的Pod
若不能容忍此汙點將不能再被排程至此節點。可以檢視節點上的汙點資訊:
# kubectl get nodes node01.linux.io -o go-template={{.spec.taints}}
[map[value:production effect:NoSchedule key:node-type]]
需要注意的是,即便是同一個鍵值資料,若其效用標識不同,則其也分屬於不同的汙點資訊,例如,將上面命令中的效用標識定義為PreferNoSchedule
再新增一次
# kubectl taint nodes node01.linux.io node-type=production:PreferNoSchedule
node "node01.linux.io" tainted
刪除某汙點,仍然通過kubectl taint
命令進行,但要使用如下的命令格式,省略效用標識則表示刪除使用指定鍵名的所有汙點,否則就只刪除指定鍵名上對應效用標識的汙點:
kubectl taint nodes <node-name> <key>:[<effect>]-
例如,刪除nodeO1
上node-type
鍵的效用標識為NoSchedule
的汙點資訊:
# kubectl taint nodes node01.linux.io node-type:NoSchedule-
node "node01.linux.io" untainted
若要刪除使用指定鍵名的所有汙點,則在刪除命令中省略效用標識即能實現,例如:
# kubectl taint nodes node01.linux.io node-type-
node "node01.linux.io" untainted
刪除節點上的全部汙點資訊,通過kubectl patch
命令將節點屬性spec.taints
的值直接置空即可,例如:
# kubectl patch nodes node01.linux.io -p '{"spec":{"taints":[]}}'
node "node01.linux.io" patched
節點汙點的變動會影響到新建Pod
物件的排程結果,而且使用NoExecute
進行標識時,還會影響到節點上現有的Pod
物件。
4、Pod物件的容忍度
Pod
物件的容忍度可通過其spec.tolerations
欄位進行新增,根據使用的操作符不同,主要有兩種可用的形式:一種是與汙點資訊完全匹配的等值關係;另一種是判斷汙點資訊存在性的匹配方式。使用Equal
操作符的示例如下所示,其中 tolerationSeconds
用於定義延遲驅逐當前Pod
物件的時長
注:
如果operator
是Exists
(此時容忍度不能指定 value)
如果operator
是Equal
,則它們的value
應該相等
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600
使用存在性判斷機制的容忍度示例如下
tolerations:
- key: "key1"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 3600
實踐中,若叢集中的一組機器專用於為執行非生產型的容器應用而備置,而且它們可能隨時按需上下線,那麼就應該為其新增汙點資訊,以確保僅那些能容忍此汙點的非生產型Pod
物件可以排程其上。另外,某些有著特殊硬體的節點需要專用於執行一類有著此類硬體資源需求的Pod
物件時,例如,那些有著SSD
或GPU
的裝置,也應該為其新增汙點資訊以排除其他的Pod
物件。
5、問題節點標識
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
等。