k8s 污點和容忍度


污點taints是定義在節點之上的鍵值型屬性數據,用於讓節點拒絕將Pod調度運行於其上, 除非該Pod對象具有接納節點污點的容忍度。而容忍度tolerations是定義在 Pod對象上的鍵值型屬性數據,用於配置其可容忍的節點污點,而且調度器僅能將Pod對象調度至其能夠容忍該節點污點的節點之上,如圖所示

img

節點選擇器nodeSelector和節點親和性nodeAffinity兩種調度方式都是通過在 Pod對象上添加標簽選擇器來完成對特定類型節點標簽的匹配,它們實現的是由Pod選擇節點的機制。而污點和容忍度則是通過向節點添加污點信息來控制Pod對象的調度結果,從而賦予了節點控制何種Pod對象能夠調度於其上的主控權。簡單來說,節點親和性使得Pod對象被吸引到一類特定的節點,而污點則相反,它提供了讓節點排斥特定Pod對象的能力。

Kubernetes使用PodToleratesNodeTaints預選策略和 TaintTolerationPriority優選函數來完成此種類型的高級調度機制。

2、定義污點和容忍度

污點定義在節點的node Spec中,而容忍度則定義在PodpodSpec中,它們都是鍵值型數據,但又都額外支持一個效果effect標記,語法格式為key=value:effect,其中keyvalue的用法及格式與資源注俯-信息相似, 而effect則用於定義對Pod對象的排斥等級,它主要包含以下三種類型

  • NoSchedule
    不能容忍此污點的新Pod對象不可調度至當前節點,屬於強制型約束關系,節點上現存的Pod對象不受影響。
  • PreferNoSchedule
    NoSchedule的柔性約束版本,即不能容忍此污點的新Pod對象盡量不要調度至當前節點,不過無其他節點可供調度時也允許接受相應的Pod對象。節點上現存的Pod對象不受影響。
  • NoExecute
    不能容忍此污點的新Pod對象不可調度至當前節點,屬於強制型約束關系,而且節點上現存的Pod對象因節點污點變動或Pod容忍度變動而不再滿足匹配規則時,Pod對象將被驅逐。

Pod對象上定義容忍度時,它支持兩種操作符:一種是等值比較Equal,表示容忍度與污點必須在keyvalueeffect三者之上完全匹配;另一種是存在性判斷Exists,表示二者的keyeffect必須完全匹配,而容忍度中的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-tppenode-rolenode-projectnode-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>]- 

例如,刪除nodeO1node-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對象的時長

注:
如果operatorExists(此時容忍度不能指定 value)
如果operatorEqual,則它們的value應該相等

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600

使用存在性判斷機制的容忍度示例如下

tolerations:
- key: "key1"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 3600

實踐中,若集群中的一組機器專用於為運行非生產型的容器應用而備置,而且它們可能隨時按需上下線,那么就應該為其添加污點信息,以確保僅那些能容忍此污點的非生產型Pod對象可以調度其上。另外,某些有着特殊硬件的節點需要專用於運行一類有着此類硬件資源需求的Pod對象時,例如,那些有着SSDGPU的設備,也應該為其添加污點信息以排除其他的Pod對象。

5、問題節點標識

Kubernetes1.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-proxykube- flannel等。


免責聲明!

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



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