節點親和性(詳見這裏),是 pod 的一種屬性(偏好或硬性要求),它使 pod 被吸引到一類特定的節點。Taint 則相反,它使 節點 可以 排斥 一類特定的 pod。node
Taint 和 toleration 相互配合,能夠用來避免 pod 被分配到不合適的節點上。每一個節點上均可以應用一個或多個 taint ,這表示對於那些不能容忍這些 taint 的 pod,是不會被該節點接受的。若是將 toleration 應用於 pod 上,則表示這些 pod 能夠(但不要求)被調度到具備匹配 taint 的節點上。git
您可使用命令 kubectl taint 給節點增長一個 taint。好比,shell
kubectl taint nodes node1 key=value:NoSchedule
給節點 node1
增長一個 taint,它的 key 是 key
,value 是 value
,effect 是 NoSchedule
。這表示只有擁有和這個 taint 相匹配的 toleration 的 pod 纔可以被分配到 node1
這個節點。您能夠在 PodSpec 中定義 pod 的 toleration。下面兩個 toleration 均與上面例子中使用 kubectl taint
命令建立的 taint 相匹配,所以若是一個 pod 擁有其中的任何一個 toleration 都可以被分配到 node1
:markdown
想刪除上述命令添加的 taint ,您能夠運行:網絡
kubectl taint nodes kube11 key:NoSchedule-
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
tolerations:
- key: "key"
operator: "Exists"
effect: "NoSchedule"
一個 toleration 和一個 taint 相「匹配」是指它們有同樣的 key 和 effect ,而且:ide
operator
是 Exists
(此時 toleration 不能指定 value
),或者operator
是 Equal
,則它們的 value
應該相等Note:注意: 存在兩種特殊狀況:優化
- 若是一個 toleration 的
key
爲空且 operator 爲Exists
,表示這個 toleration 與任意的 key 、 value 和 effect 都匹配,即這個 toleration 能容忍任意 taint。tolerations: - operator: "Exists"
- 若是一個 toleration 的
effect
爲空,則key
值與之相同的相匹配 taint 的effect
能夠是任意值。tolerations: - key: "key" operator: "Exists"
上述例子使用到的 effect
的一個值 NoSchedule
,您也可使用另一個值 PreferNoSchedule
。這是「優化」或「軟」版本的 NoSchedule
——系統會*儘可能*避免將 pod 調度到存在其不能容忍 taint 的節點上,但這不是強制的。effect
的值還能夠設置爲 NoExecute
,下文會詳細描述這個值。spa
您能夠給一個節點添加多個 taint ,也能夠給一個 pod 添加多個 toleration。Kubernetes 處理多個 taint 和 toleration 的過程就像一個過濾器:從一個節點的全部 taint 開始遍歷,過濾掉那些 pod 中存在與之相匹配的 toleration 的 taint。餘下未被過濾的 taint 的 effect 值決定了 pod 是否會被分配到該節點,特別是如下狀況:code
NoSchedule
的 taint,則 Kubernetes 不會將 pod 分配到該節點。NoSchedule
的 taint,可是存在 effect 值爲 PreferNoSchedule
的 taint,則 Kubernetes 會*嘗試*將 pod 分配到該節點。NoExecute
的 taint,則 Kubernetes 不會將 pod 分配到該節點(若是 pod 還未在節點上運行),或者將 pod 從該節點驅逐(若是 pod 已經在節點上運行)。例如,假設您給一個節點添加了以下的 taint內存
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule
而後存在一個 pod,它有兩個 toleration
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
在這個例子中,上述 pod 不會被分配到上述節點,由於其沒有 toleration 和第三個 taint 相匹配。可是若是在給節點添加 上述 taint 以前,該 pod 已經在上述節點運行,那麼它還能夠繼續運行在該節點上,由於第三個 taint 是三個 taint 中惟一不能被這個 pod 容忍的。
一般狀況下,若是給一個節點添加了一個 effect 值爲 NoExecute
的 taint,則任何不能忍受這個 taint 的 pod 都會立刻被驅逐,任何能夠忍受這個 taint 的 pod 都不會被驅逐。可是,若是 pod 存在一個 effect 值爲 NoExecute
的 toleration 指定了可選屬性 tolerationSeconds
的值,則表示在給節點添加了上述 taint 以後,pod 還能繼續在節點上運行的時間。例如,
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600
這表示若是這個 pod 正在運行,而後一個匹配的 taint 被添加到其所在的節點,那麼 pod 還將繼續在節點上運行 3600 秒,而後被驅逐。若是在此以前上述 taint 被刪除了,則 pod 不會被驅逐。
經過 taint 和 toleration ,能夠靈活地讓 pod *避開*某些節點或者將 pod 從某些節點驅逐。下面是幾個使用例子:
kubectl taint nodes nodename dedicated=groupName:NoSchedule
),而後給這組用戶的 pod 添加一個相對應的 toleration(經過編寫一個自定義的admission controller,很容易就能作到)。擁有上述 toleration 的 pod 就可以被分配到上述專用節點,同時也可以被分配到集羣中的其它節點。若是您但願這些 pod 只能被分配到上述專用節點,那麼您還須要給這些專用節點另外添加一個和上述 taint 相似的 label (例如:dedicated=groupName
),同時 還要在上述 admission controller 中給 pod 增長節點親和性要求上述 pod 只能被分配到添加了 dedicated=groupName
標籤的節點上。kubectl taint nodes nodename special=true:NoSchedule
or kubectl taint nodes nodename special=true:PreferNoSchedule
),而後給使用了這類特殊硬件的 pod 添加一個相匹配的 toleration。和專用節點的例子相似,添加這個 toleration 的最簡單的方法是使用自定義 admission controller。好比,咱們推薦使用 Extended Resources 來表示特殊硬件,給配置了特殊硬件的節點添加 taint 時包含 extended resource 名稱,而後運行一個 ExtendedResourceToleration admission controller。此時,由於節點已經被 taint 了,沒有對應 toleration 的 Pod 會被調度到這些節點。但當你建立一個使用了 extended resource 的 Pod 時,ExtendedResourceToleration
admission controller 會自動給 Pod 加上正確的 toleration ,這樣 Pod 就會被自動調度到這些配置了特殊硬件件的節點上。這樣就可以確保這些配置了特殊硬件的節點專門用於運行 須要使用這些硬件的 Pod,而且您無需手動給這些 Pod 添加 toleration。前文咱們提到過 taint 的 effect 值 NoExecute
,它會影響已經在節點上運行的 pod * 若是 pod 不能忍受effect 值爲 NoExecute
的 taint,那麼 pod 將立刻被驅逐 * 若是 pod 可以忍受effect 值爲 NoExecute
的 taint,可是在 toleration 定義中沒有指定 tolerationSeconds
,則 pod 還會一直在這個節點上運行。 * 若是 pod 可以忍受effect 值爲 NoExecute
的 taint,並且指定了 tolerationSeconds
,則 pod 還能在這個節點上繼續運行這個指定的時間長度。
此外,Kubernetes 1.6 已經支持(alpha階段)節點問題的表示。換句話說,當某種條件爲真時,node controller會自動給節點添加一個 taint。當前內置的 taint 包括: * node.kubernetes.io/not-ready
:節點未準備好。這至關於節點狀態 Ready
的值爲 「False
「。 * node.kubernetes.io/unreachable
:node controller 訪問不到節點. 這至關於節點狀態 Ready
的值爲 「Unknown
「。 * node.kubernetes.io/out-of-disk
:節點磁盤耗盡。 * node.kubernetes.io/memory-pressure
:節點存在內存壓力。 * node.kubernetes.io/disk-pressure
:節點存在磁盤壓力。 * node.kubernetes.io/network-unavailable
:節點網絡不可用。 * node.kubernetes.io/unschedulable
: 節點不可調度。 * node.cloudprovider.kubernetes.io/uninitialized
:若是 kubelet 啓動時指定了一個 「外部」 cloud provider,它將給當前節點添加一個 taint 將其標誌爲不可用。在 cloud-controller-manager 的一個 controller 初始化這個節點後,kubelet 將刪除這個 taint。
在啓用了 TaintBasedEvictions
這個 alpha 功能特性後(在 Kubernetes controller manager 的 --feature-gates
參數中包含TaintBasedEvictions=true
開啓這個功能特性,例如:--feature-gates=FooBar=true,TaintBasedEvictions=true
),NodeController (或 kubelet)會自動給節點添加這類 taint,上述基於節點狀態 Ready 對 pod 進行驅逐的邏輯會被禁用。
Note:注意:爲了保證因爲節點問題引發的 pod 驅逐rate limiting行爲正常,系統實際上會以 rate-limited 的方式添加 taint。在像 master 和 node 通信中斷等場景下,這避免了 pod 被大量驅逐。
使用這個 alpha 功能特性,結合 tolerationSeconds
,pod 就能夠指定當節點出現一個或所有上述問題時還將在這個節點上運行多長的時間。
好比,一個使用了不少本地狀態的應用程序在網絡斷開時,仍然但願停留在當前節點上運行一段較長的時間,願意等待網絡恢復以免被驅逐。在這種狀況下,pod 的 toleration 多是下面這樣的:
tolerations:
- key: "node.alpha.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 6000
注意,Kubernetes 會自動給 pod 添加一個 key 爲 node.kubernetes.io/not-ready
的 toleration 並配置 tolerationSeconds=300
,除非用戶提供的 pod 配置中已經已存在了 key 爲 node.kubernetes.io/not-ready
的 toleration。一樣,Kubernetes 會給 pod 添加一個 key 爲 node.kubernetes.io/unreachable
的 toleration 並配置 tolerationSeconds=300
,除非用戶提供的 pod 配置中已經已存在了 key 爲 node.kubernetes.io/unreachable
的 toleration。
這種自動添加 toleration 機制保證了在其中一種問題被檢測到時 pod 默認可以繼續停留在當前節點運行 5 分鐘。這兩個默認 toleration 是由 DefaultTolerationSeconds admission controller添加的。
DaemonSet 中的 pod 被建立時,針對如下 taint 自動添加的 NoExecute
的 toleration 將不會指定 tolerationSeconds
:
node.alpha.kubernetes.io/unreachable
node.kubernetes.io/not-ready
這保證了出現上述問題時 DaemonSet 中的 pod 永遠不會被驅逐,這和 TaintBasedEvictions
這個特性被禁用後的行爲是同樣的。
1.8 版本引入了一個 alpha 特性,讓 node controller 根據節點的狀態建立 taint。當開啓了這個特性時(經過給 scheduler 的 --feature-gates
添加 TaintNodesByCondition=true
參數,例如:--feature-gates=FooBar=true,TaintNodesByCondition=true
),scheduler不會去檢查節點的狀態,而是檢查節點的 taint。這確保了節點的狀態不影響應該調度哪些 Pod 到節點上。用戶能夠經過給 Pod 添加 toleration 來選擇忽略節點的一些問題(節點狀態的形式表示)。 從 Kubernetes 1.8 開始,DaemonSet controller 會自動添加以下 NoSchedule
toleration,以防止 DaemonSet 中斷。 * node.kubernetes.io/memory-pressure
* node.kubernetes.io/disk-pressure
* node.kubernetes.io/out-of-disk
(只適合 critical pod) * node.kubernetes.io/unschedulable
(1.10 或更高版本) * node.kubernetes.io/network-unavailable
(只適合 host network)
添加上述 toleration 確保了向後兼容,您也能夠選擇自由的向 DaemonSet 添加 toleration。