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

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


咨詢
建站咨詢
