Kubernetes taint & toleration
一、概述
前一篇文章講解了Kubernetes 親和性排程
, 所涉及的內容都是描述 pod 的屬性,來宣告此 pod 希望排程到哪類 nodes。而本文介紹的Taint(汙點)
剛好相反,它是node 的一個屬性,允許 node 主動排斥 pod 的排程。
對應的 k8s 又給 pod 新增了配套屬性toleration(容忍)
,用於表示這些 pod 可以(但不強制要求)被排程到具有相應 taints 的 nodes 上。
這兩者經常一起搭配,來確保不將 pod 排程到不合適的 nodes。
看下 taint & toleration 結構體,下面足點介紹時會涉及相關欄位。
type Taint struct { Key string Value string Effect TaintEffect // add taint 的時間點 // 只有 Effect = NoExecute, 該值才會被 nodeController 寫入 TimeAdded *metav1.Time } type Toleration struct { Key string Operator TolerationOperator Value string Effect TaintEffect // 容忍時間 TolerationSeconds *int64 } type TaintEffect string const ( TaintEffectNoSchedule TaintEffect = "NoSchedule" TaintEffectPreferNoSchedule TaintEffect = "PreferNoSchedule" TaintEffectNoExecute TaintEffect = "NoExecute" ) type TolerationOperator string const ( TolerationOpExists TolerationOperator = "Exists" TolerationOpEqualTolerationOperator = "Equal" )
二、Taint
我們可以對 node 設定多個 taints,當然也可以在 pod 配置相同個數的 tolerations。影響排程和執行的具體行為,我們可以分為以下幾類:
-
如果至少有一個
effect == NoSchedule
的 taint 沒有被 pod toleration,那麼 pod 不會被排程到該節點上。 -
如果所有
effect == NoSchedule
的 taints 都被 pod toleration,但是至少有一個effect == PreferNoSchedule
沒有被 pod toleration,那麼 k8s 將努力嘗試不把 pod 排程到該節點上。 -
如果至少有一個
effect== NoExecute
的 taint 沒有被 pod toleration,那麼不僅這個 pod 不會被排程到該節點,甚至這個節點上已經執行但是也沒有設定容忍該汙點的 pods,都將被驅逐。
三、Toleration
再看下 PodSpec 配置 Tolerations,其中的 key、value、effect 與 Node Taint 設定需要保持一致,operator 支援兩類:
- Exists: 這個配置下,不需要指定 value。
- Equal: 需要配置 value 值。(operator 的預設值)
有幾個特殊情況:
- key 為空並且 operator 等於 Exists,表示匹配了所有的 keys,values 和 effects。換句話說就是容忍了所有的 taints。
tolerations: - operator: "Exists"
- effect 為空,則表示匹配所有的 effects(NoSchedule、PreferNoSchedule、NoExecute)
tolerations: - key: "key" operator: "Exists"
還有一個TolerationSeconds
,該值與 effect 為NoExecute
配套使用。用來指定在 node 添加了 effect = NoExecute 的 taint 後,能容忍該 taint 的 pods 可停留在 node 上的時間。
例如:
tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute" tolerationSeconds: 3600
表示如果這個 pod 已經執行在 node 上並且該 node 添加了一個對應的 taint,那麼這個 pod 將會在 node 上停留 3600 秒後才會被驅逐。但是如果 taint 在這個時間前被移除,那麼這個 pod 也就不會被驅逐了。
來個比較形象的圖,描述下:

該圖參考:Taints and tolerations, pod and node affinities demystified · Banzai Cloud
四、內建行為
kubernetes 1.6 版本,node controller 會跟進系統情況自動設定 node taint 屬性。
內建 taint key 如下:
- node.kubernetes.io/not-ready: 節點尚未就緒
- node.kubernetes.io/unreachable: 節點無法被訪問
- node.kubernetes.io/unschedulable: 節點不可排程
- node.kubernetes.io/out-of-disk: 節點磁碟不足
- node.kubernetes.io/memory-pressure: 節點有記憶體壓力
- node.kubernetes.io/disk-pressure: 節點有磁碟壓力
- node.kubernetes.io/network-unavailable: 節點網路不可用
- node.kubernetes.io/pid-pressure: 節點有 pid 壓力
- node.cloudprovider.kubernetes.io/uninitialized: 雲節點未初始化
- node.cloudprovider.kubernetes.io/shutdown: 雲節點已下線
kubernetes 會通過DefaultTolerationSeconds admission controller
為建立的 pod 新增兩個預設的 toleration:node.kubernetes.io/not-ready
和node.kubernetes.io/unreachable
,並且設定tolerationSeconds = 300
。當然這個預設配置,使用者可以自行覆蓋。
這些自動新增的預設配置,確保 node 出現問題後,pod 可以繼續在 node 上停留 5 分鐘。
DefaultTolerationSeconds admission controller 設定的 tolerationSeconds 值,也可以由使用者指定。
具體參考:https://github.com/kubernetes/ ... on.go
還有一個預設行為,就是 DaemonSet。
所有 DaemonSet 建立的 pod 都會新增兩個 toleration:node.alpha.kubernetes.io/unreachable
和node.alpha.kubernetes.io/notReady
。設定effect = NoExecute
,並且不指定tolerationSeconds
。
目的是確保在 node 出現 unreachable 或 notReady 的問題時,DaemonSet Pods 永遠不會被驅逐。
示例
常見的示例如下:
-
專用節點
-
如果你希望將一組節點專用於特定的使用者,那可以將這些節點設定 taints:
kubectl taint nodes nodename dedicated=groupName:NoSchedule
, 然後為 pods 設定對應的 tolerations。
- 如果你希望節點被專用並且確保服務僅使用這批節點,那麼你還應該向這批節點設定 labels (`dedicated=groupName`),並且為對應的 pods 設定 NodeAffinity,以控制 pods 只能跑到這批節點上。
-
如果你希望將一組節點專用於特定的使用者,那可以將這些節點設定 taints:
-
具有特殊硬體的節點
- - 有部分帶有特殊硬體的節點,比如 GPU、FPGA 等,要確保不將不需要專用硬體的 pods排程到這些節點。也可以和 `專有節點` 一樣的方式設定 taints:`kubectl taint nodes nodename special=true:NoSchedule` 或 `kubectl taint nodes nodename special=true:PreferNoSchedule`。建議還可以通過 [Extended Resources](https://v1-12.docs.kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#extended-resources) 和 [ExtendedResourceToleration admission controller](https://v1-12.docs.kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#extendedresourcetoleration) 來更方便的排程依賴特殊硬體的 pods,而不需要手動新增容器的 toleration
-
基於 taint 的驅逐
- - 前面也提到了,可以通過 `NoExecute taint` 來驅逐節點上已經執行的 pods。
五、參考資料
-community/taint-toleration-dedicated.md at master · kubernetes/community · GitHub
-community/taint-node-by-condition.md at master · kubernetes/community · GitHub
-Taints and tolerations, pod and node affinities demystified · Banzai Cloud