前言
前面介紹了定向調(diào)度轨奄,雖然很方便孟害,但是也存在一些問題,不夠靈活并且是硬限制挪拟,如果Node節(jié)點(diǎn)不存在挨务,那么該P(yáng)od就運(yùn)行不了,所以使用場景還是有所限制玉组。
針對于上面問題谎柄,k8s就給我們提供了親和性調(diào)度,它在NodeSelector上做了一些擴(kuò)展惯雳,可以通過配置優(yōu)先選擇符合條件的Node節(jié)點(diǎn)朝巫,如果沒有也可以調(diào)度到其它Node節(jié)點(diǎn)上,取代了定向調(diào)度的硬限制吨凑。隨著親和性調(diào)度越來越能夠體現(xiàn)NodeSelector的功能捍歪,最終NodeSelector應(yīng)該會(huì)被廢棄
親和性調(diào)度有兩種分別是 節(jié)點(diǎn)親和性 與 Pod親和性户辱。本文主要介紹節(jié)點(diǎn)親和性,Pod親和性后面更新
NodeAffinity
NodeAffinity表示Node親和性調(diào)度糙臼,用于替換NodeSelector的全新調(diào)度策略
目前nodeAffinity有兩種配置項(xiàng)
requiredDuringSchedulingIgnoredDuringExecution
必須滿足指定的規(guī)則才能將Pod調(diào)度到節(jié)點(diǎn)庐镐,屬于硬限制,調(diào)度完成之后就不再檢查條件是否滿足变逃,與NodeSelector非常像只是語法不同必逆,所以說NodeAffinity可以替代NodeSelector
通過 kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution 可以查看配置項(xiàng),具體如下
requiredDuringSchedulingIgnoredDuringExecution
nodeSelectorTerms #<[]Object> -required- 節(jié)點(diǎn)選擇列表
- matchFields # <[]Object> 按節(jié)點(diǎn)字段列出的節(jié)點(diǎn)選擇器要求列表
- matchExpressions #<[]Object> 按節(jié)點(diǎn)標(biāo)簽列出的節(jié)點(diǎn)選擇器要求列表(推薦)
- key # 標(biāo)簽名
operator # 操作符 包括 In揽乱、NotIn名眉、Exists、DoesNotExist凰棉、Gt损拢、Lt
values # 標(biāo)簽值
操作符代表的含義如下
In # label的值必須在某個(gè)節(jié)點(diǎn)列表中
NotIn # 與In相反
Exists # 某個(gè)label存在
DoesNotExist # 某個(gè)label不存在
Gt # label的值大于某個(gè)值
Lt # label的值小于某個(gè)值
后面講的Pod親和性具有互斥功能,Node親和性雖然語法上沒有互斥功能撒犀,但是通過 NotIn和DoesNotExist可以實(shí)現(xiàn)節(jié)點(diǎn)互斥的功能
通過kubectl label命令給node01打上北京機(jī)房的標(biāo)簽福压,給node02打上上海機(jī)房的標(biāo)簽
kubectl label nodes node01 area=bj
kubectl label nodes node02 area=shanghai
# 查看標(biāo)簽是否設(shè)置成功
kubectl get nodes --show-labels
編寫 nginx-nodeAffinity-required.yaml 內(nèi)容如下
apiVersion: v1
kind: Pod
metadata:
name: nginx-node-affinity-required
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: area
operator: In
values: ['bj','changsha']
啟動(dòng)Pod,由于設(shè)置values: ['bj','changsha']或舞,所以只有node01滿足要求荆姆,觀察Pod所在節(jié)點(diǎn)
# 啟動(dòng)
[root@master affinity]# kubectl create -f nginx-nodeAffinity-required.yaml
pod/nginx-node-affinity-required created
# 查看Pod詳情,落在node01節(jié)點(diǎn)
[root@master affinity]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-node-affinity-required 1/1 Running 0 23s 10.244.1.71 node01 <none> <none>
修改yaml為values: ['shanghai','changsha']映凳,此時(shí)只有node02滿足要求胆筒,啟動(dòng)Pod觀察Pod所在節(jié)點(diǎn)
# 刪除之前Pod
[root@master affinity]# kubectl delete -f nginx-nodeAffinity-required.yaml
pod "nginx-node-affinity-required" deleted
# 啟動(dòng)
[root@master affinity]# kubectl create -f nginx-nodeAffinity-required.yaml
pod/nginx-node-affinity-required created
# 查看Pod詳情,落在node02節(jié)點(diǎn)
[root@master affinity]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-node-affinity-required 1/1 Running 0 8s 10.244.2.24 node02 <none> <none>
修改yaml為values: ['hangzhou','changsha']诈豌,此時(shí)沒有節(jié)點(diǎn)滿足要求仆救,前面提到requiredDuringSchedulingIgnoredDuringExecution屬于硬限制,所以Pod應(yīng)該運(yùn)行不起來队询,啟動(dòng)Pod,觀察Pod狀態(tài)
# 刪除之前Pod
[root@master affinity]# kubectl delete -f nginx-nodeAffinity-required.yaml
pod "nginx-node-affinity-required" deleted
# 啟動(dòng)
[root@master affinity]# kubectl create -f nginx-nodeAffinity-required.yaml
pod/nginx-node-affinity-required created
# 查看Pod詳情派桩,狀態(tài)為Pending并沒有運(yùn)行成功
[root@master affinity]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-node-affinity-required 0/1 Pending 0 14s <none> <none> <none> <none>
# 查看啟動(dòng)過程事件,拋出異常
[root@master affinity]# kubectl describe pod nginx-node-affinity-required|grep -A 100 Event
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 44s default-scheduler 0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
preferredDuringSchedulingIgnoredDuringExecution
優(yōu)先滿足指定規(guī)則蚌斩,調(diào)度器會(huì)嘗試調(diào)度Pod到指定Node铆惑,如果沒有此節(jié)點(diǎn),也不會(huì)強(qiáng)制要求送膳,是一個(gè)軟限制员魏。如果有多個(gè)匹配規(guī)則,可以設(shè)置權(quán)重(weight)來定義執(zhí)行的先后順序叠聋。
通過 kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution 可以查看配置項(xiàng)撕阎,具體如下
preferredDuringSchedulingIgnoredDuringExecution
- weight # 權(quán)重,范圍1-100碌补。
preference # 一個(gè)節(jié)點(diǎn)選擇器項(xiàng)虏束,與相應(yīng)的權(quán)重相關(guān)聯(lián)
matchFields # <[]Object> 按節(jié)點(diǎn)字段列出的節(jié)點(diǎn)選擇器要求列表
matchExpressions # <[]Object> 按節(jié)點(diǎn)標(biāo)簽列出的節(jié)點(diǎn)選擇器要求列表(推薦)
key # 標(biāo)簽
operator # 操作符
values # <[]string> 標(biāo)簽值
編寫 nginx-nodeAffinity-preferred.yaml 內(nèi)容如下,設(shè)置兩個(gè)匹配規(guī)則棉饶,以權(quán)重定義執(zhí)行順序
apiVersion: v1
kind: Pod
metadata:
name: nginx-node-affinity-preferred
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: area
operator: In
values: ['bj']
- weight: 2
preference:
matchExpressions:
- key: area
operator: In
values: ['shanghai']
啟動(dòng)Pod,由于設(shè)置有兩個(gè)匹配規(guī)則镇匀,并且shanghai的優(yōu)先級高于bj照藻,所以應(yīng)該要落在node02節(jié)點(diǎn),觀察Pod所在節(jié)點(diǎn)
# 啟動(dòng)
[root@master affinity]# kubectl create -f nginx-nodeAffinity-preferred.yaml
pod/nginx-node-affinity-preferred created
# 查看Pod詳情汗侵,落在node02節(jié)點(diǎn)
[root@master affinity]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-node-affinity-preferred 1/1 Running 0 12s 10.244.2.25 node02 <none> <none>
修改yaml將bj的權(quán)重設(shè)為3幸缕,再次啟動(dòng)Pod,觀察Pod所在節(jié)點(diǎn)
# 刪除之前Pod
[root@master affinity]# kubectl delete -f nginx-nodeAffinity-preferred.yaml
pod "nginx-node-affinity-preferred" deleted
# 啟動(dòng)
[root@master affinity]# kubectl create -f nginx-nodeAffinity-preferred.yaml
pod/nginx-node-affinity-preferred created
# 查看Pod詳情晰韵,落在node01節(jié)點(diǎn)
[root@master affinity]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-node-affinity-preferred 1/1 Running 0 8s 10.244.1.72 node01 <none> <none>
修改yaml如下发乔,條件均不滿足
apiVersion: v1
kind: Pod
metadata:
name: nginx-node-affinity-preferred
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: area
operator: In
values: ['changsha']
- weight: 2
preference:
matchExpressions:
- key: area
operator: In
values: ['hangzhou']
啟動(dòng)Pod,上面提到雪猪,這種調(diào)度為軟限制栏尚,如果沒有找到符合條件的Node會(huì)退而求其次,選擇一個(gè)資源充足的Pod進(jìn)行調(diào)度
# 刪除之前Pod
[root@master affinity]# kubectl delete -f nginx-nodeAffinity-preferred.yaml
pod "nginx-node-affinity-preferred" deleted
# 啟動(dòng)
[root@master affinity]# kubectl create -f nginx-nodeAffinity-preferred.yaml
pod/nginx-node-affinity-preferred created
# 調(diào)度到了node01幾點(diǎn)
[root@master affinity]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-node-affinity-preferred 1/1 Running 0 4s 10.244.1.74 node01 <none> <none>
問題
由于nodeSelector還未被廢棄浪蹂,那么同時(shí)設(shè)置nodeSelector與nodeAffinity抵栈,該如何調(diào)度
從上面給出的親和性配置項(xiàng)可以知道nodeSelectorTerms為一個(gè)數(shù)組類型,可以設(shè)置多個(gè)matchExpressions坤次,那么有多個(gè)matchExpressions該如何匹配
matchExpressions也是一個(gè)數(shù)組,可以設(shè)置多組key-value操作斥赋,這又該如何匹配
同時(shí)定義nodeSelector與nodeAffinity
編寫 affinity-nodeselector.yaml 內(nèi)容如下
apiVersion: v1
kind: Pod
metadata:
name: affinity-nodeselector
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: area
operator: In
values: ['bj']
nodeSelector:
area: shanghai
啟動(dòng)Pod缰猴,由于兩者都是硬限制,限制的條件不同應(yīng)該無法調(diào)度疤剑。
# 啟動(dòng)Pod
[root@master affinity]# kubectl create -f affinity-nodeselector.yaml
pod/affinity-nodeselector created
# 查看Pod狀態(tài)滑绒,未啟動(dòng)成功
[root@master affinity]# kubectl get pods
NAME READY STATUS RESTARTS AGE
affinity-nodeselector 0/1 Pending 0 9s
# 查看啟動(dòng)事件,看到了似曾相識的報(bào)錯(cuò)
[root@master affinity]# kubectl describe pod affinity-nodeselector | grep -A 100 Events
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 34s default-scheduler 0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
修改nodeSelector隘膘,將條件也設(shè)置為bj,啟動(dòng)成功
[root@master affinity]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
affinity-nodeselector 1/1 Running 0 7s 10.244.1.75 node01 <none> <none>
nodeAffinity指定多個(gè)matchExpressions如何執(zhí)行
編寫 multiple-nodeselectorterms.yaml 內(nèi)容如下
apiVersion: v1
kind: Pod
metadata:
name: multiple-nodeselectorterms
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: area
operator: In
values: ['changsha']
- matchExpressions:
- key: area
operator: In
values: ['shanghai']
啟動(dòng)Pod疑故,如果可以啟動(dòng)成功并且在node02節(jié)點(diǎn),表示只要滿足一個(gè)條件即可弯菊,如果啟動(dòng)不成功表示都要滿足
# 啟動(dòng)
[root@master affinity]# kubectl create -f multiple-nodeselectorterms.yaml
pod/multiple-nodeselectorterms created
# 觀察Pod詳情纵势,啟動(dòng)成功,并且Pod落在node02節(jié)點(diǎn)
[root@master affinity]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
multiple-nodeselectorterms 1/1 Running 0 19s 10.244.2.26 node02 <none> <none>
matchExpressions有多個(gè)匹配項(xiàng)
編寫 multiple-matchexpressions.yaml 內(nèi)容如下
apiVersion: v1
kind: Pod
metadata:
name: multiple-matchexpressions
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: area
operator: In
values: ['changsha']
- key: area
operator: In
values: ['shanghai']
啟動(dòng)Pod管钳,如果可以啟動(dòng)成功并且在node02節(jié)點(diǎn)钦铁,表示只要滿足一個(gè)條件即可,如果啟動(dòng)不成功表示都要滿足
# 啟動(dòng)
[root@master affinity]# kubectl create -f multiple-matchexpressions.yaml
pod/multiple-matchexpressions created
# 觀察Pod才漆,啟動(dòng)失敗
[root@master affinity]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
multiple-matchexpressions 0/1 Pending 0 11s <none> <none> <none> <none>
# 查看啟動(dòng)事件牛曹,還是熟悉的報(bào)錯(cuò)
[root@master affinity]# kubectl describe pod multiple-matchexpressions | grep -A 100 Events
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 48s default-scheduler 0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
總結(jié)
如果同時(shí)定義了nodeSelector與nodeAffinity,兩個(gè)條件必須滿足醇滥,才能調(diào)度到指定Pod上
如果有多個(gè) matchExpressions 黎比,那么只要滿足一個(gè)即可
如果一個(gè)matchExpressions 下有多個(gè)匹配項(xiàng)超营,那么需要全部滿足
節(jié)點(diǎn)親和性就介紹到這里,后面介紹Pod親和性調(diào)度與互斥調(diào)度阅虫。
歡迎關(guān)注演闭,學(xué)習(xí)不迷路!