污點和容忍度
節(jié)點親和性 是 Pod 的一種屬性,它使 Pod 被吸引到一類特定的節(jié)點 (這可能出于一種偏好,也可能是硬性要求)。
污點(Taint) 則相反——它使節(jié)點能夠排斥一類特定的 Pod。
容忍度(Toleration) 是應(yīng)用于 Pod 上的。容忍度允許調(diào)度器調(diào)度帶有對應(yīng)污點的 Pod。 容忍度允許調(diào)度但并不保證調(diào)度:作為其功能的一部分, 調(diào)度器也會評估其他參數(shù)。
污點和容忍度(Toleration)相互配合,可以用來避免 Pod 被分配到不合適的節(jié)點上。 每個節(jié)點上都可以應(yīng)用一個或多個污點,這表示對于那些不能容忍這些污點的 Pod, 是不會被該節(jié)點接受的。
例子
你可以使用命令 kubectl taint 給節(jié)點增加一個污點。比如
[root@kubernetes-master ~]# kubectl taint nodes node1 key1=value1:NoSchedule
給節(jié)點 node1 增加一個污點,它的鍵名是 key1,鍵值是 value1,效果是 NoSchedule。 這表示只有擁有和這個污點相匹配的容忍度的 Pod 才能夠被分配到 node1 這個節(jié)點。
若要移除上述命令所添加的污點,你可以執(zhí)行:
[root@kubernetes-master ~]# kubectl taint nodes node1 key1=value1:NoSchedule-
你可以在 Pod 規(guī)約中為 Pod 設(shè)置容忍度。 下面兩個容忍度均與上面例子中使用 kubectl taint 命令創(chuàng)建的污點相匹配, 因此如果一個 Pod 擁有其中的任何一個容忍度,都能夠被調(diào)度到 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 的默認(rèn)值是 Equal。
一個容忍度和一個污點相“匹配”是指它們有一樣的鍵名和效果,并且:
- 如果 operator 是 Exists(此時容忍度不能指定 value),或者
- 如果 operator 是 Equal,則它們的 value 應(yīng)該相等。
注意存在兩種特殊情況:
如果一個容忍度的 key 為空且 operator 為 Exists, 表示這個容忍度與任意的 key、value 和 effect 都匹配,即這個容忍度能容忍任何污點。
如果 effect 為空,則可以與所有鍵名 key1 的效果相匹配。
上述例子中 effect 使用的值為 NoSchedule,你也可以使用另外一個值 PreferNoSchedule。 這是“優(yōu)化”或“軟”版本的 NoSchedule —— 系統(tǒng)會 盡量 避免將 Pod 調(diào)度到存在其不能容忍污點的節(jié)點上, 但這不是強(qiáng)制的。effect 的值還可以設(shè)置為 NoExecute,下文會詳細(xì)描述這個值。
你可以給一個節(jié)點添加多個污點,也可以給一個 Pod 添加多個容忍度設(shè)置。 Kubernetes 處理多個污點和容忍度的過程就像一個過濾器:從一個節(jié)點的所有污點開始遍歷, 過濾掉那些 Pod 中存在與之相匹配的容忍度的污點。余下未被過濾的污點的 effect 值決定了 Pod 是否會被分配到該節(jié)點。需要注意以下情況:
- 如果未被忽略的污點中存在至少一個 effect 值為 NoSchedule 的污點, 則 Kubernetes 不會將 Pod 調(diào)度到該節(jié)點。
- 如果未被忽略的污點中不存在 effect 值為 NoSchedule 的污點, 但是存在至少一個 effect 值為 PreferNoSchedule 的污點, 則 Kubernetes 會 嘗試 不將 Pod 調(diào)度到該節(jié)點。
- 如果未被忽略的污點中存在至少一個 effect 值為 NoExecute 的污點, 則 Kubernetes 不會將 Pod 調(diào)度到該節(jié)點(如果 Pod 還未在節(jié)點上運行), 或者將 Pod 從該節(jié)點驅(qū)逐(如果 Pod 已經(jīng)在節(jié)點上運行)。
例如,假設(shè)你給一個節(jié)點添加了如下污點:
[root@kubernetes-master ~]# kubectl taint nodes node1 key1=value1:NoSchedule
[root@kubernetes-master ~]# kubectl taint nodes node1 key1=value1:NoExecute
[root@kubernetes-master ~]# 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 不會被調(diào)度到上述節(jié)點,因為其沒有容忍度和第三個污點相匹配。 但是如果在給節(jié)點添加上述污點之前,該 Pod 已經(jīng)在上述節(jié)點運行, 那么它還可以繼續(xù)運行在該節(jié)點上,因為第三個污點是三個污點中唯一不能被這個 Pod 容忍的。
通常情況下,如果給一個節(jié)點添加了一個 effect 值為 NoExecute 的污點, 則任何不能忍受這個污點的 Pod 都會馬上被驅(qū)逐,任何可以忍受這個污點的 Pod 都不會被驅(qū)逐。 但是,如果 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 秒,然后被驅(qū)逐。 如果在此之前上述污點被刪除了,則 Pod 不會被驅(qū)逐。
例如:
通過污點和容忍度,可以靈活地讓 Pod 避開某些節(jié)點或者將 Pod 從某些節(jié)點驅(qū)逐。 下面是幾個使用例子:
- 專用節(jié)點:如果想將某些節(jié)點專門分配給特定的一組用戶使用,你可以給這些節(jié)點添加一個污點(即, kubectl taint nodes nodename dedicated=groupName:NoSchedule), 然后給這組用戶的 Pod 添加一個相對應(yīng)的容忍度 (通過編寫一個自定義的準(zhǔn)入控制器, 很容易就能做到)。 擁有上述容忍度的 Pod 就能夠被調(diào)度到上述專用節(jié)點,同時也能夠被調(diào)度到集群中的其它節(jié)點。 如果你希望這些 Pod 只能被調(diào)度到上述專用節(jié)點, 那么你還需要給這些專用節(jié)點另外添加一個和上述污點類似的 label(例如:dedicated=groupName), 同時還要在上述準(zhǔn)入控制器中給 Pod 增加節(jié)點親和性要求,要求上述 Pod 只能被調(diào)度到添加了 dedicated=groupName 標(biāo)簽的節(jié)點上。
- 配備了特殊硬件的節(jié)點:在部分節(jié)點配備了特殊硬件(比如 GPU)的集群中, 我們希望不需要這類硬件的 Pod 不要被調(diào)度到這些特殊節(jié)點,以便為后繼需要這類硬件的 Pod 保留資源。 要達(dá)到這個目的,可以先給配備了特殊硬件的節(jié)點添加污點 (例如 kubectl taint nodes nodename special=true:NoSchedule 或 kubectl taint nodes nodename special=true:PreferNoSchedule), 然后給使用了這類特殊硬件的 Pod 添加一個相匹配的容忍度。 和專用節(jié)點的例子類似,添加這個容忍度的最簡單的方法是使用自定義 準(zhǔn)入控制器。 比如,我們推薦使用擴(kuò)展資源 來表示特殊硬件,給配置了特殊硬件的節(jié)點添加污點時包含擴(kuò)展資源名稱, 然后運行一個 ExtendedResourceToleration 準(zhǔn)入控制器。此時,因為節(jié)點已經(jīng)被設(shè)置污點了,沒有對應(yīng)容忍度的 Pod 不會被調(diào)度到這些節(jié)點。 但當(dāng)你創(chuàng)建一個使用了擴(kuò)展資源的 Pod 時,ExtendedResourceToleration 準(zhǔn)入控制器會自動給 Pod 加上正確的容忍度,這樣 Pod 就會被自動調(diào)度到這些配置了特殊硬件的節(jié)點上。 這種方式能夠確保配置了特殊硬件的節(jié)點專門用于運行需要這些硬件的 Pod, 并且你無需手動給這些 Pod 添加容忍度。
- 基于污點的驅(qū)逐: 這是在每個 Pod 中配置的在節(jié)點出現(xiàn)問題時的驅(qū)逐行為, 接下來的章節(jié)會描述這個特性。
基于污點的驅(qū)逐
特性狀態(tài): Kubernetes v1.18 [stable]
前文提到過污點的效果值 NoExecute 會影響已經(jīng)在節(jié)點上運行的如下 Pod:
- 如果 Pod 不能忍受這類污點,Pod 會馬上被驅(qū)逐。
- 如果 Pod 能夠忍受這類污點,但是在容忍度定義中沒有指定 tolerationSeconds, 則 Pod 還會一直在這個節(jié)點上運行。
- 如果 Pod 能夠忍受這類污點,而且指定了 tolerationSeconds, 則 Pod 還能在這個節(jié)點上繼續(xù)運行這個指定的時間長度。
當(dāng)某種條件為真時,節(jié)點控制器會自動給節(jié)點添加一個污點。當(dāng)前內(nèi)置的污點包括
- node.kubernetes.io/not-ready:節(jié)點未準(zhǔn)備好。這相當(dāng)于節(jié)點狀況 Ready 的值為 “False”。
- node.kubernetes.io/unreachable:節(jié)點控制器訪問不到節(jié)點. 這相當(dāng)于節(jié)點狀況 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)絡(luò)不可用。
- node.kubernetes.io/unschedulable: 節(jié)點不可調(diào)度。
- node.cloudprovider.kubernetes.io/uninitialized:如果 kubelet 啟動時指定了一個“外部”云平臺驅(qū)動, 它將給當(dāng)前節(jié)點添加一個污點將其標(biāo)志為不可用。在 cloud-controller-manager 的一個控制器初始化這個節(jié)點后,kubelet 將刪除這個污點。
在節(jié)點被排空時,節(jié)點控制器或者 kubelet 會添加帶有 NoExecute 效果的相關(guān)污點。 如果異常狀態(tài)恢復(fù)正常,kubelet 或節(jié)點控制器能夠移除相關(guān)的污點。
在某些情況下,當(dāng)節(jié)點不可達(dá)時,API 服務(wù)器無法與節(jié)點上的 kubelet 進(jìn)行通信。 在與 API 服務(wù)器的通信被重新建立之前,刪除 Pod 的決定無法傳遞到 kubelet。 同時,被調(diào)度進(jìn)行刪除的那些 Pod 可能會繼續(xù)運行在分區(qū)后的節(jié)點上。
說明:
控制面會限制向節(jié)點添加新污點的速率。這一速率限制可以管理多個節(jié)點同時不可達(dá)時 (例如出現(xiàn)網(wǎng)絡(luò)中斷的情況),可能觸發(fā)的驅(qū)逐的數(shù)量。
你可以為 Pod 設(shè)置 tolerationSeconds,以指定當(dāng)節(jié)點失效或者不響應(yīng)時, Pod 維系與該節(jié)點間綁定關(guān)系的時長。
比如,你可能希望在出現(xiàn)網(wǎng)絡(luò)分裂事件時,對于一個與節(jié)點本地狀態(tài)有著深度綁定的應(yīng)用而言, 仍然停留在當(dāng)前節(jié)點上運行一段較長的時間,以等待網(wǎng)絡(luò)恢復(fù)以避免被驅(qū)逐。 你為這種 Pod 所設(shè)置的容忍度看起來可能是這樣:
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 6000
說明:
Kubernetes 會自動給 Pod 添加針對 node.kubernetes.io/not-ready 和 node.kubernetes.io/unreachable 的容忍度,且配置 tolerationSeconds=300, 除非用戶自身或者某控制器顯式設(shè)置此容忍度。
這些自動添加的容忍度意味著 Pod 可以在檢測到對應(yīng)的問題之一時,在 5 分鐘內(nèi)保持綁定在該節(jié)點上。
DaemonSet 中的 Pod 被創(chuàng)建時, 針對以下污點自動添加的 NoExecute 的容忍度將不會指定 tolerationSeconds:
- node.kubernetes.io/unreachable
- node.kubernetes.io/not-ready
這保證了出現(xiàn)上述問題時 DaemonSet 中的 Pod 永遠(yuǎn)不會被驅(qū)逐。
基于節(jié)點狀態(tài)添加污點
控制平面使用節(jié)點控制器自動創(chuàng)建 與節(jié)點狀況 對應(yīng)的、效果為 NoSchedule 的污點。
調(diào)度器在進(jìn)行調(diào)度時檢查污點,而不是檢查節(jié)點狀況。這確保節(jié)點狀況不會直接影響調(diào)度。 例如,如果 DiskPressure 節(jié)點狀況處于活躍狀態(tài),則控制平面添加 node.kubernetes.io/disk-pressure 污點并且不會調(diào)度新的 Pod 到受影響的節(jié)點。 如果 MemoryPressure 節(jié)點狀況處于活躍狀態(tài),則控制平面添加 node.kubernetes.io/memory-pressure 污點。
對于新創(chuàng)建的 Pod,可以通過添加相應(yīng)的 Pod 容忍度來忽略節(jié)點狀況。 控制平面還在具有除 BestEffort 之外的 QoS 類的 Pod 上添加 node.kubernetes.io/memory-pressure 容忍度。 這是因為 Kubernetes 將 Guaranteed 或 Burstable QoS 類中的 Pod(甚至沒有設(shè)置內(nèi)存請求的 Pod) 視為能夠應(yīng)對內(nèi)存壓力,而新創(chuàng)建的 BestEffort Pod 不會被調(diào)度到受影響的節(jié)點上。文章來源:http://www.zghlxwxcb.cn/news/detail-571446.html
DaemonSet 控制器自動為所有守護(hù)進(jìn)程添加如下 NoSchedule 容忍度,以防 DaemonSet 崩潰:文章來源地址http://www.zghlxwxcb.cn/news/detail-571446.html
- 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 添加容忍度
到了這里,關(guān)于【云原生】POD污點和容忍度的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!