新聞中心
污點和容忍度
節(jié)點親和性 是 Pod 的一種屬性,它使 Pod 被吸引到一類特定的節(jié)點 (這可能出于一種偏好,也可能是硬性要求)。 污點(Taint)則相反——它使節(jié)點能夠排斥一類特定的 Pod。

容忍度(Toleration)是應用于 Pod 上的,允許(但并不要求)Pod 調度到帶有與之匹配的污點的節(jié)點上。
污點和容忍度(Toleration)相互配合,可以用來避免 Pod 被分配到不合適的節(jié)點上。 每個節(jié)點上都可以應用一個或多個污點,這表示對于那些不能容忍這些污點的 Pod,是不會被該節(jié)點接受的。
概念
你可以使用命令 kubectl taint 給節(jié)點增加一個污點。比如,
kubectl taint nodes node1 key1=value1:NoSchedule
給節(jié)點 ?node1 ?增加一個污點,它的鍵名是 ?key1?,鍵值是 ?value1?,效果是 ?NoSchedule?。 這表示只有擁有和這個污點相匹配的容忍度的 Pod 才能夠被分配到 ?node1 ?這個節(jié)點。
若要移除上述命令所添加的污點,你可以執(zhí)行:
kubectl taint nodes node1 key1=value1:NoSchedule-
你可以在 PodSpec 中定義 Pod 的容忍度。 下面兩個容忍度均與上面例子中使用 ?kubectl taint? 命令創(chuàng)建的污點相匹配, 因此如果一個 Pod 擁有其中的任何一個容忍度都能夠被分配到 ?node1? :
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
tolerations:
- key: "key1"
operator: "Exists"
effect: "NoSchedule"
這里是一個使用了容忍度的 Pod:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: "example-key"
operator: "Exists"
effect: "NoSchedule"
?operator ?的默認值是 ?Equal?。
一個容忍度和一個污點相“匹配”是指它們有一樣的鍵名和效果,并且:
- 如果 ?
operator?是 ?Exists?(此時容忍度不能指定 ?value?),或者 - 如果 ?
operator?是 ?Equal?,則它們的 ?value?應該相等
Note:
存在兩種特殊情況:
如果一個容忍度的 ?
key?為空且 operator 為 ?
Exists?, 表示這個容忍度與任意的 key 、value 和 effect 都匹配,即這個容忍度能容忍任意 taint。
如果 ?
effect?為空,則可以與所有鍵名 ?
key1?的效果相匹配。
上述例子中 ?effect ?使用的值為 ?NoSchedule?,你也可以使用另外一個值 ?PreferNoSchedule?。 這是“優(yōu)化”或“軟”版本的 ?NoSchedule ?—— 系統(tǒng)會 盡量 避免將 Pod 調度到存在其不能容忍污點的節(jié)點上, 但這不是強制的。?effect ?的值還可以設置為 ?NoExecute?,下文會詳細描述這個值。
你可以給一個節(jié)點添加多個污點,也可以給一個 Pod 添加多個容忍度設置。 Kubernetes 處理多個污點和容忍度的過程就像一個過濾器:從一個節(jié)點的所有污點開始遍歷, 過濾掉那些 Pod 中存在與之相匹配的容忍度的污點。余下未被過濾的污點的 effect 值決定了 Pod 是否會被分配到該節(jié)點,特別是以下情況:
- 如果未被過濾的污點中存在至少一個 effect 值為 ?
NoSchedule?的污點, 則 Kubernetes 不會將 Pod 分配到該節(jié)點。 - 如果未被過濾的污點中不存在 effect 值為 ?
NoSchedule?的污點, 但是存在 effect 值為 ?PreferNoSchedule?的污點, 則 Kubernetes 會 嘗試 不將 Pod 分配到該節(jié)點。 - 如果未被過濾的污點中存在至少一個 effect 值為 ?
NoExecute?的污點, 則 Kubernetes 不會將 Pod 分配到該節(jié)點(如果 Pod 還未在節(jié)點上運行), 或者將 Pod 從該節(jié)點驅逐(如果 Pod 已經(jīng)在節(jié)點上運行)。
例如,假設你給一個節(jié)點添加了如下污點
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule
假定有一個 Pod,它有兩個容忍度:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
在這種情況下,上述 Pod 不會被分配到上述節(jié)點,因為其沒有容忍度和第三個污點相匹配。 但是如果在給節(jié)點添加上述污點之前,該 Pod 已經(jīng)在上述節(jié)點運行, 那么它還可以繼續(xù)運行在該節(jié)點上,因為第三個污點是三個污點中唯一不能被這個 Pod 容忍的。
通常情況下,如果給一個節(jié)點添加了一個 effect 值為 ?NoExecute ?的污點, 則任何不能忍受這個污點的 Pod 都會馬上被驅逐, 任何可以忍受這個污點的 Pod 都不會被驅逐。 但是,如果 Pod 存在一個 effect 值為 ?NoExecute ?的容忍度指定了可選屬性 ?tolerationSeconds ?的值,則表示在給節(jié)點添加了上述污點之后, Pod 還能繼續(xù)在節(jié)點上運行的時間。例如,
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600
這表示如果這個 Pod 正在運行,同時一個匹配的污點被添加到其所在的節(jié)點, 那么 Pod 還將繼續(xù)在節(jié)點上運行 3600 秒,然后被驅逐。 如果在此之前上述污點被刪除了,則 Pod 不會被驅逐。
使用例子
通過污點和容忍度,可以靈活地讓 Pod 避開 某些節(jié)點或者將 Pod 從某些節(jié)點驅逐。下面是幾個使用例子:
- 專用節(jié)點:如果你想將某些節(jié)點專門分配給特定的一組用戶使用,你可以給這些節(jié)點添加一個污點(即, ?
kubectl taint nodes nodename dedicated=groupName:NoSchedule?), 然后給這組用戶的 Pod 添加一個相對應的 toleration(通過編寫一個自定義的 準入控制器,很容易就能做到)。 擁有上述容忍度的 Pod 就能夠被分配到上述專用節(jié)點,同時也能夠被分配到集群中的其它節(jié)點。 如果你希望這些 Pod 只能被分配到上述專用節(jié)點,那么你還需要給這些專用節(jié)點另外添加一個和上述 污點類似的 label (例如:?dedicated=groupName?),同時 還要在上述準入控制器中給 Pod 增加節(jié)點親和性要求上述 Pod 只能被分配到添加了 ?dedicated=groupName? 標簽的節(jié)點上。 - 配備了特殊硬件的節(jié)點:在部分節(jié)點配備了特殊硬件(比如 GPU)的集群中, 我們希望不需要這類硬件的 Pod 不要被分配到這些特殊節(jié)點,以便為后繼需要這類硬件的 Pod 保留資源。 要達到這個目的,可以先給配備了特殊硬件的節(jié)點添加 taint (例如 ?
kubectl taint nodes nodename special=true:NoSchedule? 或 ?kubectl taint nodes nodename special=true:PreferNoSchedule?), 然后給使用了這類特殊硬件的 Pod 添加一個相匹配的 toleration。 和專用節(jié)點的例子類似,添加這個容忍度的最簡單的方法是使用自定義 準入控制器。 比如,我們推薦使用擴展資源 來表示特殊硬件,給配置了特殊硬件的節(jié)點添加污點時包含擴展資源名稱, 然后運行一個 ?ExtendedResourceToleration?準入控制器。此時,因為節(jié)點已經(jīng)被設置污點了,沒有對應容忍度的 Pod 不會被調度到這些節(jié)點。但當你創(chuàng)建一個使用了擴展資源的 Pod 時, ExtendedResourceToleration 準入控制器會自動給 Pod 加上正確的容忍度, 這樣 Pod 就會被自動調度到這些配置了特殊硬件件的節(jié)點上。 這樣就能夠確保這些配置了特殊硬件的節(jié)點專門用于運行需要使用這些硬件的 Pod, 并且你無需手動給這些 Pod 添加容忍度。 - 基于污點的驅逐: 這是在每個 Pod 中配置的在節(jié)點出現(xiàn)問題時的驅逐行為,接下來的章節(jié)會描述這個特性。
基于污點的驅逐
FEATURE STATE: Kubernetes v1.18 [stable]
前文提到過污點的 effect 值 ?NoExecute ?會影響已經(jīng)在節(jié)點上運行的 Pod
- 如果 Pod 不能忍受 effect 值為 ?
NoExecute?的污點,那么 Pod 將馬上被驅逐 - 如果 Pod 能夠忍受 effect 值為 ?
NoExecute?的污點,但是在容忍度定義中沒有指定 ?tolerationSeconds?,則 Pod 還會一直在這個節(jié)點上運行。 - 如果 Pod 能夠忍受 effect 值為 ?
NoExecute?的污點,而且指定了 ?tolerationSeconds?, 則 Pod 還能在這個節(jié)點上繼續(xù)運行這個指定的時間長度。
當某種條件為真時,節(jié)點控制器會自動給節(jié)點添加一個污點。當前內(nèi)置的污點包括:
- ?
node.kubernetes.io/not-ready?:節(jié)點未準備好。這相當于節(jié)點狀態(tài) ?Ready?的值為 "?False?"。 - ?
node.kubernetes.io/unreachable?:節(jié)點控制器訪問不到節(jié)點. 這相當于節(jié)點狀態(tài) ?Ready?的值為 "?Unknown?"。 - ?
node.kubernetes.io/memory-pressure?:節(jié)點存在內(nèi)存壓力。 - ?
node.kubernetes.io/disk-pressure?:節(jié)點存在磁盤壓力。 - ?
node.kubernetes.io/pid-pressure?: 節(jié)點的 PID 壓力。 - ?
node.kubernetes.io/network-unavailable?:節(jié)點網(wǎng)絡不可用。 - ?
node.kubernetes.io/unschedulable?: 節(jié)點不可調度。 - ?
node.cloudprovider.kubernetes.io/uninitialized?:如果 kubelet 啟動時指定了一個 "外部" 云平臺驅動, 它將給當前節(jié)點添加一個污點將其標志為不可用。在 cloud-controller-manager 的一個控制器初始化這個節(jié)點后,kubelet 將刪除這個污點。
在節(jié)點被驅逐時,節(jié)點控制器或者 kubelet 會添加帶有 ?NoExecute ?效應的相關污點。 如果異常狀態(tài)恢復正常,kubelet 或節(jié)點控制器能夠移除相關的污點。
Note: 為了保證由于節(jié)點問題引起的 Pod 驅逐 速率限制行為正常, 系統(tǒng)實際上會以限定速率的方式添加污點。在像主控節(jié)點與工作節(jié)點間通信中斷等場景下, 這樣做可以避免 Pod 被大量驅逐。
使用這個功能特性,結合 ?tolerationSeconds?,Pod 就可以指定當節(jié)點出現(xiàn)一個 或全部上述問題時還將在這個節(jié)點上運行多長的時間。
比如,一個使用了很多本地狀態(tài)的應用程序在網(wǎng)絡斷開時,仍然希望停留在當前節(jié)點上運行一段較長的時間, 愿意等待網(wǎng)絡恢復以避免被驅逐。在這種情況下,Pod 的容忍度可能是下面這樣的:
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 6000
Note:
Kubernetes 會自動給 Pod 添加一個 key 為 ?
node.kubernetes.io/not-ready? 的容忍度 并配置 ?
tolerationSeconds=300?,除非用戶提供的 Pod 配置中已經(jīng)已存在了 key 為 ?
node.kubernetes.io/not-ready? 的容忍度。
同樣,Kubernetes 會給 Pod 添加一個 key 為 ?
node.kubernetes.io/unreachable? 的容忍度 并配置 ?
tolerationSeconds=300?,除非用戶提供的 Pod 配置中已經(jīng)已存在了 key 為 ?
node.kubernetes.io/unreachable? 的容忍度。
這種自動添加的容忍度意味著在其中一種問題被檢測到時 Pod 默認能夠繼續(xù)停留在當前節(jié)點運行 5 分鐘。
DaemonSet 中的 Pod 被創(chuàng)建時, 針對以下污點自動添加的 ?NoExecute ?的容忍度將不會指定 ?tolerationSeconds?:
- ?
node.kubernetes.io/unreachable? - ?
node.kubernetes.io/not-ready?
這保證了出現(xiàn)上述問題時 DaemonSet 中的 Pod 永遠不會被驅逐。
基于節(jié)點狀態(tài)添加污點
控制平面使用節(jié)點控制器自動創(chuàng)建 與節(jié)點狀況對應的帶有 ?NoSchedule ?效應的污點。
調度器在進行調度時檢查污點,而不是檢查節(jié)點狀況。這確保節(jié)點狀況不會直接影響調度。 例如,如果 ?DiskPressure ?節(jié)點狀況處于活躍狀態(tài),則控制平面 添加 ?node.kubernetes.io/disk-pressure? 污點并且不會調度新的 pod 到受影響的節(jié)點。如果 ?MemoryPressure ?節(jié)點狀況處于活躍狀態(tài),則 控制平面添加 ?node.kubernetes.io/memory-pressure? 污點。
對于新創(chuàng)建的 Pod,可以通過添加相應的 Pod 容忍度來忽略節(jié)點狀況。 控制平面還在具有除 ?BestEffort ?之外的 QoS 類的 Pod 上 添加 ?node.kubernetes.io/memory-pressure? 容忍度。 這是因為 Kubernetes 將 ?Guaranteed ?或 ?Burstable ?QoS 類中的 Pod(甚至沒有設置內(nèi)存請求的 Pod) 視為能夠應對內(nèi)存壓力,而新創(chuàng)建的 ?BestEffort ?Pod 不會被調度到受影響的節(jié)點上。
DaemonSet 控制器自動為所有守護進程添加如下 ?NoSchedule? 容忍度以防 DaemonSet 崩潰:
- ?
node.kubernetes.io/memory-pressure? - ?
node.kubernetes.io/disk-pressure? - ?
node.kubernetes.io/pid-pressure? (1.14 或更高版本) - ?
node.kubernetes.io/unschedulable? (1.10 或更高版本) - ?
node.kubernetes.io/network-unavailable? (只適合主機網(wǎng)絡配置)
添加上述容忍度確保了向后兼容,你也可以選擇自由向 DaemonSet 添加容忍度。
新聞名稱:創(chuàng)新互聯(lián)kubernetes教程:Kubernetes污點和容忍度
本文路徑:http://fisionsoft.com.cn/article/cceposo.html


咨詢
建站咨詢
