如何用三只兔子的故事來輕松理解 Kubernetes 污點和容忍
前言
本文通過自身理解進行述說,如有不準確的地方,請指正。
在講述一系列相關(guān)專業(yè)術(shù)語之前,先嘗試用一個通俗易懂的故事來說明 Kubernetes 中 node 與 pod 之間的愛恨情仇。
雄性(node)| 雌性(pod)
在銀河系以外的一個星球上,有著一群兩性生物,分別是雌性(pod)和雄性(node)。雌性生物居多,而雄性生物由于優(yōu)勝劣汰,只剩下 3 只優(yōu)質(zhì)的雄性生物(node)。雄雌在一起就容易產(chǎn)生吸引,就會有以下的情況產(chǎn)生:
(1)雄(node)少雌(pod)多,而這三只優(yōu)質(zhì)的雄性生物性格、優(yōu)點都是一致的,雌性生物選誰都一樣。于是,雌性生物就分為均等分為三列和三只雄性生物在一起。這種類似于平均分配的原則。
k8s 中的概念:在 k8s 中是最常見最普通的 pod 分布方式,常用與 deployment 和 daemonset 控制器。
(2)時間一長,生物開始了進化。三只雄性(node)生物各自有了不一樣的地方,編號 1 的雄性學(xué)會了種植(node01 label skill='grow');編號 2 的雄性學(xué)會了打獵(node02 label skill='hunt');編號 3 的雄性啥也沒學(xué)會(沒學(xué)會就保持默認)。普通的雌性(pod)仍然保持著平均分配的原則。而一些進化快的雌性(pod)生物發(fā)現(xiàn)了三只優(yōu)質(zhì)雄性(node)生物各自的不同,各自也開始有了一些選擇。一些雌性更加青睞學(xué)會種植的雄性生物(nodeSelector skill='grow') ;一些雌性更加青睞學(xué)打獵的雄性生物(nodeSelector skill='hunt') ;而有些雌性生物喜歡的特點很奇特,它們喜歡會飛的雄性,而僅存的三只雄性生物都無法滿足這一特點。如果有天一只雄性生物進化會飛了,它們就會依附與會飛的雄性生物,如果始終沒有進化出會飛的雄性生物,則它們一直等下去這在 k8s 中,就是 yaml 文件中 nodeSelector 的使用。
k8s 中的概念:當 node 打上特定的標簽后,會出現(xiàn)如下情況:
- pod 中未指定 nodeSelector ,則保持默認 schedule 調(diào)度算法的方式;
- pod 中指定了 nodeSelector ,且指定 nodeSelector 中的 key、value 符合某一個 node 中的某一個 key、value,則這個 pod 直接調(diào)度到該 node;
- pod 中指定了 nodeSelector ,指定 nodeSelector 中的 key、value 不包含在任何一個 node 中,則這個 pod 會一直處于 padding 狀態(tài)。
(3)三只雄性(node)不僅優(yōu)點增長了,缺點也隨之而來。編號 1 的雄性喜歡打臉(node01 taint hobby='face');編號 2 的雄性喜歡打屁股(node01 taint hobby='hunkers');編號 3 的雄性喜歡踩腳(node01 taint hobby='foot');普通的雌性(pod)生物仍然保持平均分配的原則,而一些再次進化的雌性生物也有了自己的性格。能夠容忍打臉的雌性則和編號 1 的雄性在一起(tolerations hobby='face'),但是這個容忍可能是永久,也可能是 1 天(tolerationSeconds=86400)。而這三只雄性生物偶爾會在一起鬼混,編號 1 的雄性生物說不定哪天就嗜好就變?yōu)榱讼矚g睡懶覺。而一些無法容忍它睡懶覺嗜好的雌性生物就會隔一段時間或者馬上就離開它。
k8s 中的概念:這就是 污點 與 容忍。
污點和容忍還有其他的選項參數(shù),后文展開解說。
nodeSelector
將 pod 分配給指定的節(jié)點。
集群如下:
- $ kubectl get nodes
- NAME STATUS ROLES AGE VERSION
- k8s-master Ready master 20h v1.19.7
- k8s-node01 Ready <none> 20h v1.19.7
- k8s-node02 Ready <none> 20h v1.19.7
為 k8s-node01 添加一個標簽
- $ kubectl label nodes k8s-node01 disktype=ssd
- node/k8s-node01 labeled
查看標簽
- $ kubectl get nodes --show-labels
- NAME STATUS ROLES AGE VERSION LABELS
- k8s-master Ready master 20h v1.19.7 ..., kubernetes.io/hostname=k8s-master
- k8s-node01 Ready <none> 20h v1.19.7 ..., disktype=ssd,kubernetes.io/hostname=k8s-node01
- k8s-node02 Ready <none> 20h v1.19.7 ..., kubernetes.io/hostname=k8s-node02
可以看到 k8s-node01 節(jié)點標簽:disktype=ssd
創(chuàng)建一個調(diào)度到 選擇節(jié)點的 Pod
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- labels:
- app: ngx
- name: ngx
- spec:
- replicas: 2
- selector:
- matchLabels:
- app: ngx
- template:
- metadata:
- labels:
- app: ngx
- spec:
- containers:
- - image: nginx:alpine-arm64
- name: nginx
- nodeSelector:
- disktype: ssd #### 選擇服務(wù) key: value 的節(jié)點
創(chuàng)建 pod 查看是否調(diào)度到指定的節(jié)點
- $ kubectl apply -f ngx.yaml
- deployment.apps/ngx created
- $ kubectl get po -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- ngx-5f4df66559-hjmzg 1/1 Running 0 10s 10.244.1.13 k8s-node01 <none> <none>
- ngx-5f4df66559-wqgdb 1/1 Running 0 10s 10.244.1.14 k8s-node01 <none> <none>
k8s 親和性
說道親和性,親和性主要分為兩類:nodeAffinity 和 podAffinity 。
nodeAffinity
nodeAffinity 就是節(jié)點親和性,調(diào)度可以分成軟策略和硬策略兩種方式,軟策略就是如果你沒有滿足調(diào)度要求的節(jié)點的話,POD 就會忽略這條規(guī)則,繼續(xù)完成調(diào)度過程,說白了就是滿足條件最好了,沒有的話也無所謂了的策略;而硬策略就比較強硬了,如果沒有滿足條件的節(jié)點的話,就不斷重試直到滿足條件為止,簡單說就是你必須滿足我的要求,不然我就不干的策略。nodeAffinity就有兩上面兩種策略:
- requiredDuringSchedulingIgnoredDuringExecution :硬策略
- preferredDuringSchedulingIgnoredDuringExecution :軟策略
硬策略
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- labels:
- app: ngx
- name: ngx
- spec:
- replicas: 2
- selector:
- matchLabs:
- app: ngx
- template:
- metadata:
- labels:
- app: ngx
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: disktype ## key 的值
- operator: In ## 包括
- values:
- - ssd ## value
- containers:
- - image: nginx:alpine-arm64
- name: nginx
- nodeSelector:
- disktype: ssd
上面這兩個 pod 只會運行在 滿足 node label disktype=value 的節(jié)點上,如果沒有節(jié)點滿足這個條件,則一直處于 pending 狀態(tài)。
- $ kubectl get po -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- ngx-7b65b44bc-gff9x 1/1 Running 0 3m53s 10.244.1.15 k8s-node01 <none> <none>
- ngx-7b65b44bc-w7bsf 1/1 Running 0 3m53s 10.244.1.16 k8s-node01 <none> <none>
- $ kubectl get nodes k8s-node01 --show-labels
- NAME STATUS ROLES AGE VERSION LABELS
- k8s-node01 Ready <none> 22h v1.19.7 ..., disktype=ssd,kubernetes.io/arch=arm64,kubernetes.io/hostname=k8s-node01
軟策略
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- labels:
- app: ngx
- name: ngx
- spec:
- replicas: 2
- selector:
- matchLabels:
- app: ngx
- template:
- metadata:
- labels:
- app: ngx
- spec:
- affinity:
- nodeAffinity:
- preferredDuringSchedulingIgnoredDuringExecution:
- - weight: 10
- preference:
- matchExpressions:
- - key: disktype
- operator: In
- values:
- - hdd
- containers:
- - image: nginx:alpine-arm64
- name: nginx
軟策略就是,第一選擇是 node label disktype=hdd 的節(jié)點,如果沒有,就采用默認 scheduler 的調(diào)度策略,沒有強制性。
- $ kubectl get po -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- ngx-d4754b6fd-lr96g 1/1 Running 0 2m55s 10.244.2.13 k8s-node02 <none> <none>
- ngx-d4754b6fd-ns7hs 1/1 Running 0 2m55s 10.244.1.28 k8s-node01 <none> <none>
operator 提供如下幾種操作:
- In:label 的值在某個列表中
- NotIn:label 的值不在某個列表中
- Gt:label 的值大于某個值
- Lt:label 的值小于某個值
- Exists:某個 label 存在
- DoesNotExist:某個 label 不存在
如果nodeSelectorTerms下面有多個選項的話,滿足任何一個條件就可以了;如果matchExpressions有多個選項的話,則必須同時滿足這些條件才能正常調(diào)度 POD。
污點和容忍
在 Kubernetes 中,節(jié)點親和性 NodeAffinity 是 Pod 上定義的一種屬性,能夠使 Pod 按我們的要求調(diào)度到某個節(jié)點上,而 Taints(污點) 則恰恰相反,它是 Node 上的一個屬性,可以讓 Pod 不能調(diào)度到帶污點的節(jié)點上,甚至?xí)埸c節(jié)點上已有的 Pod 進行驅(qū)逐。當然,對應(yīng)的 Kubernetes 可以給 Pod 設(shè)置 Tolerations(容忍) 屬性來讓 Pod 能夠容忍節(jié)點上設(shè)置的污點,這樣在調(diào)度時就會忽略節(jié)點上設(shè)置的污點,將 Pod 調(diào)度到該節(jié)點。一般時候 Taints 通常與 Tolerations 配合使用。
污點(Taints)
查看污點
查看 node 的污點
- $ kubectl describe nodes k8s-master
- ...
- Taints: node-role.kubernetes.io/master:NoSchedule
- ...
- # 也可通過下面操作查看:
- $ kubectl get nodes k8s-master -o go-template={{.spec.taints}}
- [map[effect:NoSchedule key:node-role.kubernetes.io/master]]
污點內(nèi)容一般組成為 key、value 及一個 effect 三個元素,表現(xiàn)為:
- <key>=<value>:<effect>
這里的 value 可以為空,表現(xiàn)形式為:
- node-role.kubernetes.io/master:NoSchedule
- - key: node-role.kubernetes.io/master
- - value: 空
- - effect: NoSchedule
設(shè)置污點
一般我們需要想要設(shè)置某個節(jié)點只允許特定的 Pod 進行調(diào)度,這時候就得對節(jié)點設(shè)置污點,可以按 kubectl taint node [node] key=value[effect] 格式進行設(shè)置,其中 effect 可取值如下:
- PreferNoSchedule: 盡量不要調(diào)度。
- NoSchedule: 一定不能被調(diào)度。
- NoExecute: 不僅不會調(diào)度, 還會驅(qū)逐 Node 上已有的 Pod。
一般時候我們設(shè)置污點,就像下面例子一樣對齊進行設(shè)置:
- ### 設(shè)置污點并不允許 Pod 調(diào)度到該節(jié)點
- $ kubectl taint node k8s-master key1=value1:NoSchedule
- ### 設(shè)置污點盡量阻止污點調(diào)度到該節(jié)點
- $ kubectl taint node k8s-master key2=value2:PreferNoSchedule
- ### 設(shè)置污點,不允許普通 Pod 調(diào)度到該節(jié)點,且將該節(jié)點上已經(jīng)存在的 Pod 進行驅(qū)逐
- $ kubectl taint node k8s-master key3=value3:NoExecute
刪除污點
上面說明了如何對 Node 添加污點阻止 Pod 進行調(diào)度,下面再說一下如何刪除節(jié)點上的污點,可以使用下面命令:
- kubectl taint node [node] [key]-
上面語法和創(chuàng)建污點類似,不過需要注意的是刪除污點需要知道 key 和最后面設(shè)置一個 "-" 兩項將污點刪除,示例如下:
為了方便演示,先給節(jié)點設(shè)置污點:
- ### 設(shè)置污點1
- $ kubectl taint node k8s-master key1=value1:PreferNoSchedule
- node/k8s-master tainted
- ### 設(shè)置污點2
- $ kubectl taint node k8s-master key2=value2:NoSchedule
- node/k8s-master tainted
- ### 設(shè)置污點3,并且不設(shè)置 value
- $ kubectl taint node k8s-master key2=:PreferNoSchedule
- node/k8s-master tainted
查看污點,可以看到上面設(shè)置的三個值:
- $ kubectl describe nodes k8s-master
- ...
- Taints: key2=value2:NoSchedule
- node-role.kubernetes.io/master:NoSchedule
- key1=value1:PreferNoSchedule
- key2:PreferNoSchedule
- ...
然后刪除污點
- ### 刪除污點,可以不指定 value,指定 [effect] 值就可刪除該 key[effect] 的污點
- $ kubectl taint node k8s-master key1:PreferNoSchedule-
- ### 也可以根據(jù) key 直接將該 key2 的所有 [effect] 都刪除:
- $ kubectl taint node k8s-master key2-
再次查看污點,可以看到以上污點都被刪除:
- $ kubectl describe nodes k8s-master
- ...
- Taints: node-role.kubernetes.io/master:NoSchedule
- ...
容忍 (toleratints)
Pod 設(shè)置容忍
為了使某些 Pod 禁止調(diào)度到某些特定節(jié)點上,就可以對節(jié)點設(shè)置污點 taints。當然,如果希望有些 Pod 能夠忽略節(jié)點的污點,繼續(xù)能夠調(diào)度到該節(jié)點,就可以對 Pod 設(shè)置容忍,讓 Pod 能夠容忍節(jié)點上設(shè)置的污點,例如:
對一個節(jié)點設(shè)置污點:
- kubectl taint node k8s-node01 key=value:NoSchedule
對于 Pod 設(shè)置容忍, 以下兩種方式都可以:
- ### 容忍的 key、value 和對應(yīng) effect 也必須和污點 taints 保持一致
- ......
- tolerations:
- - key: "key"
- operator: "Equal"
- value: "value"
- effect: "NoSchedule"
- ### 容忍 tolerations 的 key 和要污點 taints 的 key 一致,且設(shè)置的 effect 也相同,不需要設(shè)置 value
- ......
- tolerations:
- - key: "key"
- operator: "Exists"
- effect: "NoSchedule"
Node 和 Pod 對于污點與容忍基本概念
概念
- 一個 node 可以有多個污點;
- 一個 pod 可以有多個容忍;
- kubernetes 執(zhí)行多個污點和容忍方法類似于過濾器
如果一個 node 有多個污點,且 pod 上也有多個容忍,只要 pod 中容忍能包含 node 上設(shè)置的全部污點,就可以將 pod 調(diào)度到該 node 上。如果 pod 上設(shè)置的容忍不能夠包含 node 上設(shè)置的全部污點,且 node 上剩下不能被包含的污點 effect 為 PreferNoSchedule,那么也可能會被調(diào)度到該節(jié)點。
注意
當 pod 總存在 容忍,首先 pod 會選擇沒有污點的節(jié)點,然后再次選擇容忍污點的節(jié)點。
- 如果 node 上帶有污點 effect 為 NoSchedule,而 pod 上不帶響應(yīng)的容忍,kubernetes 就不會調(diào)度 pod 到這臺 node 上。
- 如果 Node 上帶有污點 effect 為 PreferNoShedule,這時候 Kubernetes 會努力不要調(diào)度這個 Pod 到這個 Node 上。
- 如果 Node 上帶有污點 effect 為 NoExecute,這個已經(jīng)在 Node 上運行的 Pod 會從 Node 上驅(qū)逐掉。沒有運行在 Node 的 Pod 不能被調(diào)度到這個 Node 上。一般使用與當某個節(jié)點處于 NotReady 狀態(tài)下,pod 迅速在其他正常節(jié)點啟動。
Deployment 中設(shè)置容忍
在 kubernetes 中 deployment 設(shè)置容忍,示例如下:
- apiVersion: apps/vl
- kind: Deployment
- metadata:
- name: example
- spec:
- replicas: 5
- template:
- spec:
- ......
- tolerations:
- - key: "key"
- operator: "Equal"
- value: "value"
- effect: "NoSchedule"
設(shè)置容忍時間
正常情況下, 如果一個污點帶有 effect=NoExecute 被添加到了這個 Node。那么不能容忍這個污點的所有 Pod 就會立即被踢掉。而帶有容忍標簽的 Pod 就不會踢掉。然而,一個帶有 effect=Noexecute 的容忍可以指定一個 tolerationSeconds 來指定當這個污點被添加的時候在多長時間內(nèi)不被踢掉。例如:
- tolerations:
- - key: "key"
- operator: "Equal"
- value: "value"
- effect: "Noexecute"
- tolerationSeconds: 3600
如果這個 Pod 已經(jīng)在這個帶污點且 effect 為 NoExecute 的 node 上。這個 pod 可以一直運行到 3600s 后再被踢掉。如果這時候 Node 的污點被移除了,這個 Pod 就不會被踢掉。
容忍示例
Operator 默認是 Equal,可設(shè)置為 Equal 與 Exists 兩種,按這兩種進行示例:
Operator 是 Exists
容忍任何污點
例如一個空的 key,將匹配所有的 key、value、effect。即容忍任何污點。
- tolerations:
- - operator: "Exists"
容忍某 key 值的污點
例如一個空的 effect,并且 key 不為空,那么將匹配所有與 key 相同的 effect:
- tolerations:
- - key: "key"
- operator: "Exists"
Operator 是 Equal
node 上有一個污點
Node 和 Pod 的 key 為 key1、value1 與 effect 相同則能調(diào)度:
- #污點
- key1=value1:NoSchedule
- #Pod設(shè)置
- tolerations:
- - key: "key1"
- operator: "Equal"
- value: "value1"
- effect: "NoSchedule"
node 上有多個污點
Node 的污點的 key、value、effect 和 Pod 容忍都相同則能調(diào)度:
- ## 設(shè)置污點
- 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 的污點和 Pod 的大部分都相同,不同的是 Node 污點 effect 為 PreferNoSchedule 的,可能會調(diào)度:
- ## 污點
- 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 的污點和 Pod 的大部分都相同,不同的是 Node 污點 effect 為 NoSchedule 和 NoExecute 的,不會被調(diào)度:
- ## 污點
- 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"
對比理解 Exists 和 Equal 之間的區(qū)別:
- Exists 是包含,Equal 是等于,Exists 使用范圍更廣,而 Equal 則是精準匹配。
- 當污點中存在 NoExecute 時,而容忍中不存在 NoExecute 時,不會被調(diào)度到該節(jié)點。
- Exists 可以不寫 value , 而 Equal 則一定要指定對應(yīng)的 value
污點驅(qū)逐
在使用 kubernetes 時,會遇到 某個 node 節(jié)點明明已經(jīng) 宕機了,查看 node 狀態(tài)從 Ready 狀態(tài)變?yōu)?NotReady 狀態(tài),但是 節(jié)點所在的 pod 卻已經(jīng)處于 running 狀態(tài),過了很長一段時間才會轉(zhuǎn)為 Terminating 狀態(tài),這是為什么呢?
污點是對于 node 節(jié)點來講,如果 node 節(jié)點 effect 設(shè)置為 NoExecute ,它會影響節(jié)點上已經(jīng)運行的 Pod,如下所示:
- 立即將沒有匹配容忍的 pod 驅(qū)逐。
- 設(shè)置容忍但是沒有指定 tolerationSeconds 參數(shù)的,那么該容忍永久生效,不會被驅(qū)逐。
- 設(shè)置容忍但是有指定 tolerationSeconds 參數(shù)的,那么在指定的時間內(nèi)容忍有效,超過指定時間后將被剔除。(pod 默認設(shè)置,tolerationSeconds = 300s)
此外,當某些條件為 true 時,節(jié)點控制器會自動污染節(jié)點。內(nèi)置以下污點:
key | 注釋 |
---|---|
node.kubernetes.io/not-ready | 節(jié)點尚未準備好。這對應(yīng)于 NodeCondition Ready 為 false。 |
node.kubernetes.io/unreachable | 無法從節(jié)點控制器訪問節(jié)點。這對應(yīng)于 NodeCondition Ready 為 Unknown。 |
node.kubernetes.io/out-of-disk | 節(jié)點磁盤不足。 |
node.kubernetes.io/memory-pressure | 節(jié)點有內(nèi)存壓力。 |
node.kubernetes.io/disk-pressure | 節(jié)點有磁盤壓力。 |
node.kubernetes.io/network-unavailable | 節(jié)點的網(wǎng)絡(luò)不可用。 |
node.kubernetes.io/unschedulable | 節(jié)點不可調(diào)度。 |
node.cloudprovider.kubernetes.io/uninitialized | 當 kubelet 從 "外部" 云提供程序開始時,此污點在節(jié)點上設(shè)置為將其標記為不可用。來自 cloud-controller-manager 的控制器初始化此節(jié)點后,kubelet 刪除此污點。 |
通過上面知識的鋪墊,當一個節(jié)點宕機時,kubernetes 集群會給它打上什么樣的污點呢?
一個 Ready 狀態(tài)的節(jié)點
- $ kubectl get node k8s-node02 -o go-template={{.spec.taints}}
- <no value>
一個 NotReady 狀態(tài)的節(jié)點
- $ kubectl get node k8s-node02 -o go-template={{.spec.taints}}
- [map[effect:NoSchedule key:node.kubernetes.io/unreachable timeAdded:2021-12-23T13:49:58Z] map[effect:NoExecute key:node.kubernetes.io/unreachable timeAdded:2021-12-23T13:50:03Z]]
處于 NotReady 狀態(tài)的節(jié)點被打上了下面兩個污點:
- Taints: node.kubernetes.io/unreachable:NoExecute
- node.kubernetes.io/unreachable:NoSchedule
接下來測試 kubernetes 集群會給 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īng)很明白了, 當 node 節(jié)點處于 NotReady 狀態(tài)或者 unreachable 狀態(tài)時,Pod 會容忍它 5 分鐘,然后被驅(qū)逐。而這 5 分鐘內(nèi)就算 Pod 處于 running 狀態(tài),也是無法正常提供服務(wù)的。因此,可以在 yaml 清單中 手動指明 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>
接下來強制關(guān)閉 k8s-node02 節(jié)點,查看 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é)點轉(zhuǎn)為 NotReady 狀態(tài)后,Pod 立刻進行了轉(zhuǎn)移。這是通過 在 yaml 清單文件中明確指定 容忍時間。還可以直接修改 apiserver 配置來修改默認容忍時間。
- 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-masterpod 會自動重載最新配置。
- $ 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
- ...
對于小型集群,可以直接設(shè)置全局變量。
注意:當 kubernetes 集群只有一個 node 節(jié)點時,無法做到 Pod 轉(zhuǎn)移,因為 Pod 已經(jīng)無路可退了。