污點(diǎn)和容忍
在 Kubernetes 中,節(jié)點(diǎn)親和性 NodeAffinity 是 Pod 上定義的一種屬性,能夠使 Pod 按我們的要求調(diào)度到某個(gè)節(jié)點(diǎn)上,而 Taints(污點(diǎn)) 則恰恰相反,它是 Node 上的一個(gè)屬性,可以讓 Pod 不能調(diào)度到帶污點(diǎn)的節(jié)點(diǎn)上,甚至?xí)?duì)帶污點(diǎn)節(jié)點(diǎn)上已有的 Pod 進(jìn)行驅(qū)逐。當(dāng)然,對(duì)應(yīng)的 Kubernetes 可以給 Pod 設(shè)置 Tolerations(容忍) 屬性來讓 Pod 能夠容忍節(jié)點(diǎn)上設(shè)置的污點(diǎn),這樣在調(diào)度時(shí)就會(huì)忽略節(jié)點(diǎn)上設(shè)置的污點(diǎn),將 Pod 調(diào)度到該節(jié)點(diǎn)。一般時(shí)候 Taints 通常與 Tolerations 配合使用。
- 一個(gè) node 可以有多個(gè)污點(diǎn);
- 一個(gè) pod 可以有多個(gè)容忍;
- kubernetes 執(zhí)行多個(gè)污點(diǎn)和容忍方法類似于過濾器
如果一個(gè) node 有多個(gè)污點(diǎn),且 pod 上也有多個(gè)容忍,只要 pod 中容忍能包含 node 上設(shè)置的全部污點(diǎn),就可以將 pod 調(diào)度到該 node 上。如果 pod 上設(shè)置的容忍不能夠包含 node 上設(shè)置的全部污點(diǎn),且 node 上剩下不能被包含的污點(diǎn) effect 為 PreferNoSchedule,那么也可能會(huì)被調(diào)度到該節(jié)點(diǎn)。
注意:
當(dāng) pod 存在容忍,首先 pod 會(huì)選擇沒有污點(diǎn)的節(jié)點(diǎn),然后再次選擇容忍污點(diǎn)的節(jié)點(diǎn)。
- 如果 node 上帶有污點(diǎn) effect 為 NoSchedule,而 pod 上不帶響應(yīng)的容忍,kubernetes 就不會(huì)調(diào)度 pod 到這臺(tái) node 上。
- 如果 Node 上帶有污點(diǎn) effect 為 PreferNoShedule,這時(shí)候 Kubernetes 會(huì)努力不要調(diào)度這個(gè) Pod 到這個(gè) Node 上。
- 如果 Node 上帶有污點(diǎn) effect 為 NoExecute,這個(gè)已經(jīng)在 Node 上運(yùn)行的 Pod 會(huì)從 Node 上驅(qū)逐掉。沒有運(yùn)行在 Node 的 Pod 不能被調(diào)度到這個(gè) Node 上。一般使用與當(dāng)某個(gè)節(jié)點(diǎn)處于 NotReady 狀態(tài)下,pod 迅速在其他正常節(jié)點(diǎn)啟動(dòng)。
污點(diǎn)(Taints)
查看污點(diǎn):
$ kubectl get nodes k8s-master -o go-template={{.spec.taints}}
[map[effect:NoSchedule key:node-role.kubernetes.io/master]]
污點(diǎn)內(nèi)容一般組成為 key、value 及一個(gè) effect 三個(gè)元素,表現(xiàn)為:
```go
<key>=<value>:<effect>
這里的 value 可以為空,表現(xiàn)形式為:
node-role.kubernetes.io/master:NoSchedule
- key: node-role.kubernetes.io/master
- value: 空
- effect: NoSchedule
設(shè)置污點(diǎn)
一般我們需要想要設(shè)置某個(gè)節(jié)點(diǎn)只允許特定的 Pod
進(jìn)行調(diào)度,這時(shí)候就得對(duì)節(jié)點(diǎn)設(shè)置污點(diǎn),可以按 kubectl taint node nodename key=value:effect
格式進(jìn)行設(shè)置,其中 effect
可取值如下:
- PreferNoSchedule: 盡量不要調(diào)度。
- NoSchedule: 一定不能被調(diào)度。
- NoExecute: 不僅不會(huì)調(diào)度, 還會(huì)驅(qū)逐 Node 上已有的 Pod。
一般時(shí)候我們?cè)O(shè)置污點(diǎn),就像下面例子一樣對(duì)其進(jìn)行設(shè)置:
# 設(shè)置污點(diǎn)并不允許 Pod 調(diào)度到該節(jié)點(diǎn)
$ kubectl taint node k8s-master key1=value1:NoSchedule
# 設(shè)置污點(diǎn)盡量阻止污點(diǎn)調(diào)度到該節(jié)點(diǎn)
$ kubectl taint node k8s-master key2=value2:PreferNoSchedule
# 設(shè)置污點(diǎn),不允許普通 Pod 調(diào)度到該節(jié)點(diǎn),且將該節(jié)點(diǎn)上已經(jīng)存在的 Pod 進(jìn)行驅(qū)逐
$ kubectl taint node k8s-master key3=value3:NoExecute
刪除污點(diǎn)
上面說明了如何對(duì) Node
添加污點(diǎn)阻止 Pod
進(jìn)行調(diào)度,下面再說一下如何刪除節(jié)點(diǎn)上的污點(diǎn),可以使用下面命令:
kubectl taint node [node] [key]-
上面語法和創(chuàng)建污點(diǎn)類似,不過需要注意的是刪除污點(diǎn)需要知道 key 和最后面設(shè)置一個(gè) “-” 兩項(xiàng)將污點(diǎn)刪除,示例如下:
為了方便演示,先給節(jié)點(diǎn)設(shè)置污點(diǎn):
# 設(shè)置污點(diǎn)1
$ kubectl taint node k8s-master key1=value1:PreferNoSchedule
node/k8s-master tainted
# 設(shè)置污點(diǎn)2
$ kubectl taint node k8s-master key2=value2:NoSchedule
node/k8s-master tainted
# 設(shè)置污點(diǎn)3,并且不設(shè)置 value
$ kubectl taint node k8s-master key2=:PreferNoSchedule
node/k8s-master tainted
查看污點(diǎn),可以看到上面設(shè)置的三個(gè)值:
$ kubectl describe nodes k8s-master
...
Taints: key2=value2:NoSchedule
node-role.kubernetes.io/master:NoSchedule
key1=value1:PreferNoSchedule
key2:PreferNoSchedule
...
然后刪除污點(diǎn)
刪除污點(diǎn),可以不指定 value,指定 [effect] 值就可刪除該 key[effect] 的污點(diǎn)
$ kubectl taint node k8s-master key1:PreferNoSchedule-
也可以根據(jù) key 直接將該 key2 的所有 [effect] 都刪除:
$ kubectl taint node k8s-master key2-
再次查看污點(diǎn),可以看到以上污點(diǎn)都被刪除:
$ kubectl describe nodes k8s-master
...
Taints: node-role.kubernetes.io/master:NoSchedule
...
容忍 (toleratints)
Pod 設(shè)置容忍
為了使某些 Pod
禁止調(diào)度到某些特定節(jié)點(diǎn)上,就可以對(duì)節(jié)點(diǎn)設(shè)置污點(diǎn) taints
。當(dāng)然,如果希望有些 Pod
能夠忽略節(jié)點(diǎn)的污點(diǎn),繼續(xù)能夠調(diào)度到該節(jié)點(diǎn),就可以對(duì) Pod
設(shè)置容忍,讓 Pod
能夠容忍節(jié)點(diǎn)上設(shè)置的污點(diǎn),例如:
對(duì)一個(gè)節(jié)點(diǎn)設(shè)置污點(diǎn):
kubectl taint node k8s-node01 key=value:NoSchedule
對(duì)于 Pod 設(shè)置容忍, 以下兩種方式都可以:
# 容忍的 key、value 和對(duì)應(yīng) effect 也必須和污點(diǎn) taints 保持一致
......
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
# 容忍 tolerations 的 key 和要污點(diǎn) taints 的 key 一致,且設(shè)置的 effect 也相同,不需要設(shè)置 value
......
tolerations:
- key: "key"
operator: "Exists"
effect: "NoSchedule"
如果不指定 operator,則 operator 默認(rèn)為 equal。
此外,有如下兩個(gè)特例:
- 空的 key 配合 Exist 操作符可以匹配所有的鍵值對(duì)
- 空的 effect 匹配所有的 effect
那么,問題來了:
如果我的集群中有三個(gè) node,我有兩組 pod 要部署,每組 pod 要部署到同一個(gè)節(jié)點(diǎn)上,且兩組 pod 不能部署到同一節(jié)點(diǎn)上,怎么操作最簡(jiǎn)單?
(好吧,nodeSelector 最簡(jiǎn)單…)
apiVersion: apps/vl
kind: Deployment
metadata:
name: example
spec:
replicas: 5
template:
spec:
......
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
設(shè)置容忍時(shí)間
正常情況下, 如果一個(gè)污點(diǎn)帶有 effect=NoExecute
被添加到了這個(gè) Node
。那么不能容忍這個(gè)污點(diǎn)的所有 Pod
就會(huì)立即被踢掉。而帶有容忍標(biāo)簽的 Pod
就不會(huì)踢掉。然而,一個(gè)帶有 effect=Noexecute
的容忍可以指定一個(gè) tolerationSeconds
來指定當(dāng)這個(gè)污點(diǎn)被添加的時(shí)候在多長(zhǎng)時(shí)間內(nèi)不被踢掉(其實(shí)講驅(qū)逐有點(diǎn),不太對(duì)。我明顯感覺這個(gè)容忍時(shí)間就是 pod 用來跑路的嘛)。例如:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "Noexecute"
tolerationSeconds: 3600
如果這個(gè) Pod 已經(jīng)在這個(gè)帶污點(diǎn)且 effect 為 NoExecute 的 node 上。這個(gè) pod 可以一直運(yùn)行到 3600s 后再被踢掉。如果這時(shí)候 Node 的污點(diǎn)被移除了,這個(gè) Pod 就不會(huì)被踢掉。
容忍示例
Operator
默認(rèn)是 Equal
,可設(shè)置為 Equal
與 Exists
兩種,按這兩種進(jìn)行示例:
Operator 是 Exists
容忍任何污點(diǎn)
例如一個(gè)空的 key,將匹配所有的 key、value、effect。即容忍任何污點(diǎn)。
tolerations:
- operator: "Exists"
容忍某 key 值的污點(diǎn)
例如一個(gè)空的 effect,并且 key 不為空,那么將匹配所有與 key 相同的 effect:
tolerations:
- key: "key"
operator: "Exists"
Operator 是 Equal
node 上有一個(gè)污點(diǎn)
Node 和 Pod 的 key 為 key1、value1 與 effect 相同則能調(diào)度:
#污點(diǎn)
key1=value1:NoSchedule
#Pod設(shè)置
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
node 上有多個(gè)污點(diǎn)
Node 的污點(diǎn)的 key、value、effect 和 Pod 容忍都相同則能調(diào)度:
## 設(shè)置污點(diǎn)
key1=value1:NoSchedule
key2=value2:NoExecute
## Pod設(shè)置容忍
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key2"
operator: "Equal"
value: "value2"
effect: "NoExecute"
Node 的污點(diǎn)和 Pod 的大部分都相同,不同的是 Node 污點(diǎn) effect 為 PreferNoSchedule 的,可能會(huì)調(diào)度:
## 污點(diǎn)
key1=value1:NoSchedule
key2=value2:NoExecute
key3=value3:PreferNoSchedule
## Pod設(shè)置容忍
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key2"
operator: "Equal"
value: "value2"
effect: "NoExecute"
Node 的污點(diǎn)和 Pod 的大部分都相同,不同的是 Node 污點(diǎn) effect 為 NoSchedule 和 NoExecute 的,不會(huì)被調(diào)度:
## 污點(diǎn)
key1=value1:NoSchedule
key2=value2:NoExecute
key3=value3:PreferNoSchedule
## Pod設(shè)置容忍
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key3"
operator: "Equal"
value: "value3"
effect: "PreferNoSchedule"
對(duì)比理解 Exists 和 Equal 之間的區(qū)別:
- Exists 是包含,Equal 是等于,Exists 使用范圍更廣,而 Equal 則是精準(zhǔn)匹配。
- 當(dāng)污點(diǎn)中存在 NoExecute 時(shí),而容忍中不存在 NoExecute 時(shí),不會(huì)被調(diào)度到該節(jié)點(diǎn)。
- Exists 可以不寫 value , 而 Equal 則一定要指定對(duì)應(yīng)的 value
節(jié)點(diǎn)自污染,pod 應(yīng)對(duì)節(jié)點(diǎn)故障
此外,當(dāng)某些條件為 true 時(shí),節(jié)點(diǎn)控制器會(huì)自動(dòng)污染節(jié)點(diǎn)。內(nèi)置以下污點(diǎn):
key | 注釋 |
---|---|
node.kubernetes.io/not-ready | 節(jié)點(diǎn)尚未準(zhǔn)備好。這對(duì)應(yīng)于 NodeCondition Ready 為 false。 |
node.kubernetes.io/unreachable | 無法從節(jié)點(diǎn)控制器訪問節(jié)點(diǎn)。這對(duì)應(yīng)于 NodeCondition Ready 為 Unknown。 |
node.kubernetes.io/out-of-disk | 節(jié)點(diǎn)磁盤不足。 |
node.kubernetes.io/memory-pressure | 節(jié)點(diǎn)有內(nèi)存壓力。 |
node.kubernetes.io/disk-pressure | 節(jié)點(diǎn)有磁盤壓力。 |
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 | 當(dāng) kubelet 從 “外部” 云提供程序開始時(shí),此污點(diǎn)在節(jié)點(diǎn)上設(shè)置為將其標(biāo)記為不可用。來自 cloud-controller-manager 的控制器初始化此節(jié)點(diǎn)后,kubelet 刪除此污點(diǎn)。 |
通過上面知識(shí)的鋪墊,當(dāng)一個(gè)節(jié)點(diǎn)宕機(jī)時(shí),kubernetes 集群會(huì)給它打上什么樣的污點(diǎn)呢?
一個(gè) Ready 狀態(tài)的節(jié)點(diǎn)
$ kubectl get node k8s-node02 -o go-template={{.spec.taints}}
<no value>
一個(gè) NotReady 狀態(tài)的節(jié)點(diǎn)
$ kubectl get node k8s-node02 -o go-template={{.spec.taints}}
[map[effect:NoSchedule key:node.kubernetes.io/unreachable timeAdded:2022-07-0423T13:49:58Z]
map[effect:NoExecute key:node.kubernetes.io/unreachable timeAdded:2021-07-04T13:50:03Z]]
處于 NotReady 狀態(tài)的節(jié)點(diǎn)被打上了下面兩個(gè)污點(diǎn):
Taints: node.kubernetes.io/unreachable:NoExecute
node.kubernetes.io/unreachable:NoSchedule
接下來測(cè)試 kubernetes 集群會(huì)給 Pod 分配什么樣的容忍。
注:這兩個(gè)是 kubernetes 自動(dòng)給 pod 添加的容忍。
$ kubectl get po nginx-745b4df97d-mgdmp -o yaml
...
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300 ## 300/60=5min
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300 ## 300/60=5min
...
看到這里,Pod 的失效機(jī)制已經(jīng)很明白了, 當(dāng) node 節(jié)點(diǎn)處于 NotReady 狀態(tài)或者 unreachable 狀態(tài)時(shí),Pod 會(huì)容忍它 5 分鐘,然后被驅(qū)逐。而這 5 分鐘內(nèi)就算 Pod 處于 running 狀態(tài),也是無法正常提供服務(wù)的。因此,可以在 yaml 清單中 手動(dòng)指明 0 容忍,清單文件如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 4
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 0
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 0
containers:
- image: nginx:alpine
name: nginx
生成 Pod
$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-84f6f75c6-c76fm 1/1 Running 0 6s 10.244.3.16 k8s-node02 <none> <none>
nginx-84f6f75c6-hsxq5 1/1 Running 0 6s 10.244.3.15 k8s-node02 <none> <none>
nginx-84f6f75c6-wkt52 1/1 Running 0 6s 10.244.1.63 k8s-node01 <none> <none>
nginx-84f6f75c6-xmkjs 1/1 Running 0 6s 10.244.3.17 k8s-node02 <none> <none>
接下來強(qiáng)制關(guān)閉 k8s-node02 節(jié)點(diǎn),查看 Pod 是否轉(zhuǎn)移。
$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-84f6f75c6-c76fm 1/1 Terminating 0 116s 10.244.3.16 k8s-node02 <none> <none>
nginx-84f6f75c6-csqf4 1/1 Running 0 13s 10.244.1.66 k8s-node01 <none> <none>
nginx-84f6f75c6-hsxq5 1/1 Terminating 0 116s 10.244.3.15 k8s-node02 <none> <none>
nginx-84f6f75c6-r2v4p 1/1 Running 0 13s 10.244.1.64 k8s-node01 <none> <none>
nginx-84f6f75c6-v4knq 1/1 Running 0 13s 10.244.1.65 k8s-node01 <none> <none>
nginx-84f6f75c6-wkt52 1/1 Running 0 116s 10.244.1.63 k8s-node01 <none> <none>
nginx-84f6f75c6-xmkjs 1/1 Terminating 0 116s 10.244.3.17 k8s-node02 <none> <none>
在 node 節(jié)點(diǎn)轉(zhuǎn)為 NotReady 狀態(tài)后,Pod 立刻進(jìn)行了轉(zhuǎn)移。這是通過 在 yaml 清單文件中明確指定 容忍時(shí)間。還可以直接修改 apiserver 配置來修改默認(rèn)容忍時(shí)間。
vim /etc/kubernetes/manifests/kube-apiserver.yaml
...
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.1.11
- --default-not-ready-toleration-seconds=1 ## 新增行
- --default-unreachable-toleration-seconds=1 ## 新增行
...
修改保存后, kube-apiserver-k8s-master
pod 會(huì)自動(dòng)重載最新配置。
$ kubectl get po nginx-84f6f75c6-wkt52 -o yaml
...
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 0
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 0
...
對(duì)于小型集群,可以直接設(shè)置全局變量。文章來源:http://www.zghlxwxcb.cn/news/detail-401034.html
注意:當(dāng) kubernetes 集群只有一個(gè) node 節(jié)點(diǎn)時(shí),無法做到 Pod 轉(zhuǎn)移,因?yàn)?Pod 已經(jīng)無路可退了。文章來源地址http://www.zghlxwxcb.cn/news/detail-401034.html
到了這里,關(guān)于k8s 污點(diǎn)和容忍的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!