前言
前面介紹了節(jié)點(diǎn)親和性調(diào)度,它可以使得我們的Pod調(diào)度到指定的Node節(jié)點(diǎn)上轨蛤,而污點(diǎn)(Taints)與之相反蜜宪,它可以讓Node拒絕Pod的運(yùn)行,甚至驅(qū)逐已經(jīng)在該Node上運(yùn)行的Pod
污點(diǎn)是Node上設(shè)置的一個(gè)屬性祥山,通常設(shè)置污點(diǎn)表示該節(jié)點(diǎn)有問題圃验,比如磁盤要滿了,資源不足缝呕,或者該Node正在升級(jí)暫時(shí)不能提供使用等情況澳窑,這時(shí)不希望再有新的Pod進(jìn)來,這個(gè)時(shí)候就可以給該節(jié)點(diǎn)設(shè)置一個(gè)污點(diǎn)供常。
但是有的時(shí)候其實(shí)Node節(jié)點(diǎn)并沒有故障摊聋,只是不想讓一些Pod調(diào)度進(jìn)來,比如這臺(tái)節(jié)點(diǎn)磁盤空間比較大栈暇,希望是像Elasticsearch麻裁、Minio這樣需要較大磁盤空間的Pod才調(diào)度進(jìn)來,那么就可以給節(jié)點(diǎn)設(shè)置一個(gè)污點(diǎn)源祈,給Pod設(shè)置容忍(Tolerations)對(duì)應(yīng)污點(diǎn)煎源,如果再配合節(jié)點(diǎn)親和性功能還可以達(dá)到獨(dú)占節(jié)點(diǎn)的效果
一般時(shí)候 Taints 總是與 Tolerations配合使用
污點(diǎn)(Taints)
我們已經(jīng)知道了設(shè)置污點(diǎn)后,一般Pod將不會(huì)調(diào)度到該節(jié)點(diǎn)上來香缺,大家看過我先前的文章會(huì)發(fā)現(xiàn)手销,我的K8s集群有三個(gè)節(jié)點(diǎn),分別是master图张、node01锋拖、node02,但是每次Pod都不會(huì)調(diào)度到master節(jié)點(diǎn)祸轮,那是因?yàn)榇罱↘8s集群的時(shí)候姑隅,K8s給master自帶了一個(gè)污點(diǎn)。
查看污點(diǎn)
查看master上是否有污點(diǎn)倔撞,通過describe命令可以看到節(jié)點(diǎn)上的所有污點(diǎn)
[root@master ~]# kubectl describe node master
...
Taints: node-role.kubernetes.io/master:NoSchedule
...
還可以通過如下命令查看
[root@master ~]# kubectl get nodes master -o go-template={{.spec.taints}}
[map[effect:NoSchedule key:node-role.kubernetes.io/master]]
發(fā)現(xiàn)master上自帶了一個(gè)沒有value的污點(diǎn) node-role.kubernetes.io/master 讲仰,effect 為 NoSchedule,由于我們的Pod都沒有容忍這個(gè)污點(diǎn)痪蝇,所以一直都不會(huì)調(diào)度到master
污點(diǎn)類別
上面我們看到了污點(diǎn)有一個(gè)effect 屬性為NoSchedule鄙陡,其實(shí)還有其它兩種類別分別是 PreferNoSchedule與 NoExecute
- NoSchedule: 如果沒有容忍該污點(diǎn)就不能調(diào)度進(jìn)來。
- PreferNoSchedule: 相當(dāng)于NoExecute的一個(gè)軟限制躏啰,如果沒有容忍該污點(diǎn)趁矾,盡量不要把Pod調(diào)度進(jìn)來,但也不是強(qiáng)制的给僵。
- NoExecute: 如果沒有設(shè)置容忍該污點(diǎn)毫捣,新的Pod肯定不會(huì)調(diào)度進(jìn)來, 并且已經(jīng)在運(yùn)行的Pod沒有容忍該污點(diǎn)也會(huì)被驅(qū)逐
設(shè)置污點(diǎn)
污點(diǎn)分別由key详拙、value(可以為空)、effect 組成蔓同,設(shè)置命令如下
# 設(shè)置污點(diǎn)并不允許Pod調(diào)度到該節(jié)點(diǎn)
$ kubectl taint node node01 key=value:NoSchedule
# 設(shè)置污點(diǎn)盡量不要讓Pod調(diào)度到該節(jié)點(diǎn)
$ kubectl taint node node01 key=value:PreferNoSchedule
# 設(shè)置污點(diǎn)饶辙,不允許Pod調(diào)度到該節(jié)點(diǎn),并且且將該節(jié)點(diǎn)上沒有容忍該污點(diǎn)的Pod將進(jìn)行驅(qū)逐
$ kubectl taint node node01 key=value:NoExecute
刪除污點(diǎn)
# 刪除該key的所有污點(diǎn)
$ kubectl taint node node01 key-
# 刪除該key的某一個(gè)污點(diǎn)
$ kubectl taint node node01 key=value:NoSchedule-
# 刪除該key的某一個(gè)污點(diǎn)可以不寫value
$ kubectl taint node node01 key:NoSchedule-
污點(diǎn)測(cè)試
給node01節(jié)點(diǎn)設(shè)置一個(gè)污點(diǎn)斑粱,表示只有前臺(tái)web應(yīng)用才能調(diào)度弃揽,后端app應(yīng)用不能調(diào)度
[root@master ~]# kubectl taint node node01 web=true:NoSchedule
node/node01 tainted
編寫 web-taint.yaml 內(nèi)容如下,有三個(gè)Pod均沒有容忍該污點(diǎn)
apiVersion: v1
kind: Pod
metadata:
name: web-taint1
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent # 本地有不拉取鏡像
---
apiVersion: v1
kind: Pod
metadata:
name: web-taint2
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent # 本地有不拉取鏡像
---
apiVersion: v1
kind: Pod
metadata:
name: web-taint3
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent # 本地有不拉取鏡像
啟動(dòng)Pod则北,觀察Pod是否都被調(diào)度到node02節(jié)點(diǎn)
# 啟動(dòng)三個(gè)Pod
[root@master taint]# kubectl create -f web-taint.yaml
pod/web-taint1 created
pod/web-taint2 created
pod/web-taint3 created
# 查看pod詳情發(fā)現(xiàn)均被調(diào)度到node02節(jié)點(diǎn)
[root@master taint]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-taint1 1/1 Running 0 13s 10.244.2.35 node02 <none> <none>
web-taint2 1/1 Running 0 13s 10.244.2.34 node02 <none> <none>
web-taint3 1/1 Running 0 13s 10.244.2.36 node02 <none> <none>
給node02節(jié)點(diǎn)天津污點(diǎn) app=true:NoExecute矿微,表示只有后端服務(wù)才能調(diào)度進(jìn)來,并且已經(jīng)在node02節(jié)點(diǎn)上運(yùn)行的不是后端服務(wù)的節(jié)點(diǎn)將被驅(qū)逐
# 設(shè)置污點(diǎn)
[root@master taint]# kubectl taint node node02 app=true:NoExecute
node/node02 tainted
# 查看Pod詳情尚揣,發(fā)現(xiàn)三個(gè)Pod已經(jīng)被驅(qū)逐
[root@master taint]# kubectl get pod -o wide
No resources found in default namespace.
從上面可以知道我們雖然設(shè)置了污點(diǎn)涌矢,但是我們的節(jié)點(diǎn)其實(shí)很正常,既然是正常節(jié)點(diǎn)快骗,那么就可以有服務(wù)運(yùn)行蒿辙,這就需要用到容忍機(jī)制來運(yùn)行這些Pod
容忍(Toletations)
如果需要Pod忽略Node上的污點(diǎn),就需要給Pod設(shè)置容忍滨巴,并且是需要容忍該P(yáng)od上的所有污點(diǎn)。
通過 kubectl explain pod.spec.tolerations 可以查看容忍的配置項(xiàng)
配置項(xiàng)
tolerations: # 數(shù)組類型俺叭,可以設(shè)置多個(gè)容忍
- key: # 污點(diǎn)key
operator: # 操作符恭取,有兩個(gè)選項(xiàng) Exists and Equal 默認(rèn)是Equal
value: # 污點(diǎn)value,如果使用Equal需要設(shè)置熄守,如果是Exists就不需要設(shè)置
effect: # 可以設(shè)置為NoSchedule蜈垮、PreferNoSchedule、NoExecute裕照,如果為空表示匹配該key下所有污點(diǎn)攒发,
tolerationSeconds: # 如果污點(diǎn)類型為NoExecute,還可以設(shè)置一個(gè)時(shí)間晋南,表示這一個(gè)時(shí)間段內(nèi)Pod不會(huì)被驅(qū)逐惠猿,過了這個(gè)時(shí)間段會(huì)立刻驅(qū)逐,0或者負(fù)數(shù)會(huì)被立刻驅(qū)逐
設(shè)置容忍
給Pod設(shè)置容忍node01節(jié)點(diǎn)的污點(diǎn)web=true:NoSchedule
編寫 web-tolerations.yaml 內(nèi)容如下负间,容忍污點(diǎn)web=true:NoSchedule
apiVersion: v1
kind: Pod
metadata:
name: web-tolerations
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent # 本地有不拉取鏡像
tolerations:
- key: web
operator: Equal
value: "true"
effect: NoSchedule
啟動(dòng)web-tolerations偶妖,觀察Pod是否正常運(yùn)行
# 啟動(dòng)web-tolerations
[root@master taint]# kubectl create -f web-tolerations.yaml
pod/web-tolerations created
# Pod正常運(yùn)行,且運(yùn)行在node01節(jié)點(diǎn)
[root@master taint]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-tolerations 1/1 Running 0 8s 10.244.1.92 node01 <none> <none>
查看該P(yáng)od上的容忍
[root@master taint]# kubectl describe pod web-tolerations
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
web=true:NoSchedule
可以看到我們?cè)O(shè)置的Tolerations在里邊政溃,除了我們自己的趾访,K8s還會(huì)給每個(gè)Pod設(shè)置兩個(gè)默認(rèn)Tolerations,并且Tolerations時(shí)間為五分鐘董虱,表示某些節(jié)點(diǎn)發(fā)生一些臨時(shí)性問題扼鞋,Pod能夠繼續(xù)在該節(jié)點(diǎn)上運(yùn)行五分鐘等待節(jié)點(diǎn)恢復(fù),并不是立刻被驅(qū)逐,從而避免系統(tǒng)的異常波動(dòng)
編寫 app-tolerations.yaml 內(nèi)容如下云头,容忍污點(diǎn)app=true:NoExecute捐友,并且只容忍60s
apiVersion: v1
kind: Pod
metadata:
name: app-tolerations
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: app
operator: Exists
effect: NoExecute
tolerationSeconds: 60
啟動(dòng)app-tolerations,查看Pod是否能夠正常運(yùn)行盘寡,且運(yùn)行在node02節(jié)點(diǎn)楚殿,等待60秒,查看Pod是否已被驅(qū)逐
# 啟動(dòng)app-tolerations
[root@master taint]# kubectl create -f app-tolerations.yaml
pod/app-tolerations created
# 查看詳情竿痰,已經(jīng)運(yùn)行成功并且調(diào)度到了node02節(jié)點(diǎn)脆粥,此時(shí)運(yùn)行59秒
[root@master taint]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
app-tolerations 1/1 Running 0 59s 10.244.2.37 node02 <none> <none>
# 運(yùn)行60秒查看,狀態(tài)已經(jīng)變?yōu)門erminating
[root@master taint]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
app-tolerations 1/1 Terminating 0 60s 10.244.2.37 node02 <none> <none>
# 立刻再次查看影涉,已經(jīng)被驅(qū)逐
[root@master taint]# kubectl get pod -o wide
No resources found in default namespace.
如果一個(gè)節(jié)點(diǎn)沒有任何污點(diǎn)变隔,另一個(gè)節(jié)點(diǎn)有污點(diǎn),并且Pod容忍了該污點(diǎn)蟹倾,那么最終會(huì)調(diào)度到哪個(gè)節(jié)點(diǎn)呢匣缘?
刪除node02節(jié)點(diǎn)的污點(diǎn)app=true:NoExecute,保留node01節(jié)點(diǎn)的web=true:NoSchedule鲜棠,再次啟動(dòng)之前的web-tolerations.yaml 觀察Pod所在節(jié)點(diǎn)
# 刪除node02上的污點(diǎn)
[root@master taint]# kubectl taint node node02 app:NoExecute-
node/node02 untainted
# 啟動(dòng)Pod web-tolerations
[root@master taint]# kubectl create -f web-tolerations.yaml
pod/web-tolerations created
# Pod正常運(yùn)行肌厨,并且運(yùn)行在node02節(jié)點(diǎn)
[root@master taint]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-tolerations 1/1 Running 0 2s 10.244.2.38 node02 <none> <none>
上面表明,即使是容忍了該污點(diǎn)豁陆,如果有其它節(jié)點(diǎn)不需要容忍就可以調(diào)度的話柑爸,那還是會(huì)優(yōu)先選擇沒有污點(diǎn)的機(jī)器,但是生產(chǎn)上往往設(shè)置污點(diǎn)就是為了給你這個(gè)Pod使用的盒音,不能調(diào)度到其它節(jié)點(diǎn)表鳍,這個(gè)時(shí)候需要配合節(jié)點(diǎn)親和性調(diào)度一起使用。
Equal 與 Exists
Exists 表示key是否存在所以無需設(shè)置value祥诽,Equal 則必須設(shè)置value需要完全匹配譬圣,默認(rèn)為Equal
空的key配合Exists 可以匹配所有的key-value,也就是容忍所有的污點(diǎn)雄坪,生產(chǎn)上非常不建議使用
節(jié)點(diǎn)故障后Pod的驅(qū)逐行為
上面也提到了厘熟,K8s為每個(gè)Pod設(shè)置了兩個(gè)容忍,如果是一些臨時(shí)性故障维哈,可以容忍五分鐘不被驅(qū)逐
在K8s 1.6之后還引入了Taint的兩個(gè)新特性盯漂,TaintNodesByCondition與TaintBasedEvictions用來改善出現(xiàn)異常時(shí)對(duì)Pod的調(diào)度與驅(qū)逐問題
TaintNodesByCondition的特性如下(為節(jié)點(diǎn)添加NoSchedule的污點(diǎn))
- Node節(jié)點(diǎn)會(huì)不斷的檢查Node的狀態(tài),并且設(shè)置對(duì)應(yīng)的Condition
- 不斷地根據(jù)Condition的變更設(shè)置對(duì)應(yīng)的Taint
- 不斷地根據(jù)Taint驅(qū)逐Node上的Pod
主要污點(diǎn)如下
node.kubernetes.io/not-ready 節(jié)點(diǎn)未就緒笨农,節(jié)點(diǎn)Ready為False
node.kubernetes.io/unreachable 節(jié)點(diǎn)不可觸達(dá)
node.kubernetes.io/out-of-disk 磁盤空間已滿
node.kubernetes.io/network-unavailable 網(wǎng)絡(luò)不可用
node.kubernetes.io/unschedulable 節(jié)點(diǎn)不可調(diào)度
node.cloudprovider.kubernetes.io/uninitialized 如果 kubelet 從 外部
云服務(wù)商啟動(dòng)的就缆,該污點(diǎn)用來標(biāo)識(shí)某個(gè)節(jié)點(diǎn)當(dāng)前為不可用狀態(tài),當(dāng)云控制器 cloud-controller-manager 初始化這個(gè)節(jié)點(diǎn)后,kubelet 會(huì)將此污點(diǎn)移除
**TaintBasedEvictions **特性添加的是NoExecute的污點(diǎn),例如內(nèi)存與磁盤有壓力時(shí)哨啃,如果Pod沒有設(shè)置容忍這些污點(diǎn)洋访,則會(huì)被驅(qū)逐琅催,以保證Node不會(huì)崩潰
主要污點(diǎn)如下
node.kubernetes.io/memory-pressure 內(nèi)存不足
node.kubernetes.io/disk-pressure 磁盤不足
1.13版本之后TaintNodesByCondition 與 TaintBasedEvictions 都是默認(rèn)開啟
污點(diǎn)與容忍就介紹到這里妈倔,后面將會(huì)介紹Pod的控制器等曼。
歡迎關(guān)注巡验,學(xué)習(xí)不迷路廓旬!