寫在開篇
Node Affinity(節(jié)點親和性)允許在節(jié)點級別上指定一些條件來控制Pod被調(diào)度到哪些節(jié)點上霉晕。它還有兩種策略笼痛,本篇通過實戰(zhàn)演示如何使用兩種策略來控制Pod的調(diào)度士八。
測試環(huán)境
還是老樣子容燕,本次實戰(zhàn)繼續(xù)使用以下K8S集群環(huán)境進行:
節(jié)點 | 主機名 | IP |
---|---|---|
Master節(jié)點 | k8s-b-master | 192.168.11.100 |
工作節(jié)點1 | k8s-b-node01 | 192.168.11.101 |
工作節(jié)點2 | k8s-b-node02 | 192.168.11.102 |
工作節(jié)點3 | k8s-b-node03 | 192.168.11.103 |
工作節(jié)點4 | k8s-b-node04 | 192.168.11.104 |
工作節(jié)點5 | k8s-b-node05 | 192.168.11.105 |
工作節(jié)點6 | k8s-b-node06 | 192.168.11.106 |
開始實戰(zhàn)
在本次實戰(zhàn)中,使用一個名為goweb的測試應用程序來演示Node Affinity的使用婚度。goweb是我用Golang開發(fā)的簡單Web應用程序蘸秘,用于測試和驗證K8S的調(diào)度策略。當然了蝗茁,你也可以自己開發(fā)一個類似的應用醋虏,然后使用自己的應用來進行本篇的實戰(zhàn)內(nèi)容。
策略1
在這個實戰(zhàn)案例中哮翘,我將使用requiredDuringSchedulingIgnoredDuringExecution策略颈嚼,該策略要求Pod只能調(diào)度到特定的節(jié)點上。 我將創(chuàng)建一個Node Affinity規(guī)則饭寺,要求goweb應用只能調(diào)度到主機名為k8s-b-node03的節(jié)點上阻课。
首先,需要創(chuàng)建一個名為goweb-node-affinity.yaml的文件艰匙,并將以下內(nèi)容復制到文件中:
apiVersion: apps/v1
kind: Deployment
metadata:
name: goweb
namespace: goweb-namespace
spec:
replicas: 3
selector:
matchLabels:
app: goweb
template:
metadata:
labels:
app: goweb
spec:
containers:
- name: goweb
image: 192.168.11.253/library/goweb:latest
ports:
- containerPort: 80
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-b-node03
保存文件后限煞,使用以下命令應用goweb應用的Node Affinity規(guī)則:
kubectl apply -f goweb-node-affinity.yaml
現(xiàn)在,K8S調(diào)度器將只會將goweb應用調(diào)度到主機名為k8s-b-node03的節(jié)點上员凝。
[root@k8s-b-master ~]# kubectl get pod -n goweb-namespace -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
goweb-5559b4bbf5-5mpd8 1/1 Running 0 64s 10.244.199.138 k8s-b-node03 <none> <none>
goweb-5559b4bbf5-lbq4j 1/1 Running 0 63s 10.244.199.139 k8s-b-node03 <none> <none>
goweb-5559b4bbf5-lqkzh 1/1 Running 0 70s 10.244.199.137 k8s-b-node03 <none> <none>
策略2
在這個實戰(zhàn)案例中署驻,我將使用preferredDuringSchedulingIgnoredDuringExecution策略,該策略盡量將Pod調(diào)度到滿足條件的節(jié)點上,但不是強制要求旺上。 我將創(chuàng)建一個Node Affinity規(guī)則瓶蚂,優(yōu)先將goweb應用調(diào)度到擁有標簽app=goweb-node的節(jié)點上。
首先抚官,我創(chuàng)建一個名為goweb-preferred-node-affinity.yaml的文件扬跋,并將以下內(nèi)容復制到文件中:
apiVersion: apps/v1
kind: Deployment
metadata:
name: goweb
namespace: goweb-namespace
spec:
replicas: 3
selector:
matchLabels:
app: goweb
template:
metadata:
labels:
app: goweb
spec:
containers:
- name: goweb
image: 192.168.11.253/library/goweb:latest
ports:
- containerPort: 80
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: app
operator: In
values:
- goweb-node
保存文件后,使用以下命令應用goweb應用的Node Affinity規(guī)則:
kubectl apply -f goweb-preferred-node-affinity.yaml
現(xiàn)在凌节,K8S調(diào)度器將優(yōu)先將goweb應用調(diào)度到擁有標簽app=goweb-node的節(jié)點上钦听,但如果沒有滿足條件的節(jié)點,它仍然可以調(diào)度到其他節(jié)點上倍奢。
查看node標簽和調(diào)度結(jié)果:
# 查看label:
[root@k8s-b-master ~]# kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8s-b-master Ready control-plane 49d v1.25.4 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-b-master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
k8s-b-node01 Ready <none> 49d v1.25.4 app=goweb-node,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-b-node01,kubernetes.io/os=linux
k8s-b-node02 Ready <none> 49d v1.25.4 app=goweb-node,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-b-node02,kubernetes.io/os=linux
...
# 調(diào)度結(jié)果:
[root@k8s-b-master ~]# kubectl get pod -n goweb-namespace -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
goweb-58799f9b4c-cd5j4 1/1 Running 0 16s 10.244.51.204 k8s-b-node01 <none> <none>
goweb-58799f9b4c-hpwlt 1/1 Running 0 16s 10.244.232.147 k8s-b-node02 <none> <none>
goweb-58799f9b4c-ksps5 1/1 Running 0 16s 10.244.232.146 k8s-b-node02 <none> <none>
刪除app標簽后再次查看調(diào)度結(jié)果:
# 刪除
kubectl label nodes k8s-b-node01 app-
kubectl label nodes k8s-b-node02 app-
# 調(diào)度結(jié)果:
[root@k8s-b-master ~]# kubectl get pod -n goweb-namespace -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
goweb-58799f9b4c-5hr8h 1/1 Running 0 2s 10.244.25.77 k8s-b-node05 <none> <none>
goweb-58799f9b4c-5vnr9 1/1 Running 0 2s 10.244.232.148 k8s-b-node02 <none> <none>
goweb-58799f9b4c-hwxjc 1/1 Running 0 2s 10.244.151.4 k8s-b-node06 <none> <none>
注意到了吧朴上?刪除app標簽后,就沒有滿足條件的節(jié)點了卒煞,但它仍然可以調(diào)度到其他節(jié)點上痪宰。通過實戰(zhàn),已經(jīng)證實了這一點畔裕。
使用場景
下面聊聊兩種策略在實際工作中可能的使用場景衣撬。
1. requiredDuringSchedulingIgnoredDuringExecution
它的特點是:強制要求Pod只能調(diào)度到特定節(jié)點的策略“缛模可能適用的場景:
- 硬件特性要求:比如對底層硬件有特殊要求的應用具练,就可以將Pod調(diào)度到擁有特定標簽貨其它屬性的節(jié)點上。
- 數(shù)據(jù)本地性要求:比如需要訪問特定數(shù)據(jù)源的應用甜无,將Pod調(diào)度到與數(shù)據(jù)源最近的節(jié)點上扛点,這樣可以減少網(wǎng)絡延遲和提高性能。
- 資源隔離:將特定類型的任務或工作負載隔離到專用的節(jié)點上岂丘。
舉個貼近實際的例子陵究,假設有一組節(jié)點,其中幾個節(jié)點擁有牛逼的CPU和內(nèi)存資源奥帘。希望將一些需要較高計算能力的任務調(diào)度到這些節(jié)點上铜邮。這時候就可以使用此策略來指定這些節(jié)點的標簽或其他屬性,就可以將Pod限制在這些節(jié)點上了寨蹋。
2. preferredDuringSchedulingIgnoredDuringExecution
它的特點是:優(yōu)先選擇滿足條件的節(jié)點進行調(diào)度的策略牲距。可能適用的場景:
- 資源利用率優(yōu)化:比如希望將Pod調(diào)度到擁有特定資源的節(jié)點上钥庇,但如果沒有滿足條件的節(jié)點牍鞠,仍然可以將Pod調(diào)度到其他節(jié)點上。
- 可用性和容錯性:為了提高應用程序的可用性和容錯性评姨,我們可以將Pod調(diào)度到多個節(jié)點上难述,但仍然優(yōu)先將其調(diào)度到特定節(jié)點上萤晴。如果該節(jié)點不可用,調(diào)度器將選擇次優(yōu)節(jié)點進行調(diào)度胁后。
舉個例子店读,假設有一組節(jié)點,其中一些節(jié)點的網(wǎng)卡連接的是光交換機攀芯,網(wǎng)絡更快屯断。希望將網(wǎng)絡密集型的應用優(yōu)先調(diào)度到這些節(jié)點上,這時候就可以指定這些節(jié)點的網(wǎng)絡特性標簽或其他屬性侣诺。
再舉個例子殖演,假設在具有不同地理位置的多個數(shù)據(jù)中心中部署應用。就可以優(yōu)先將Pod調(diào)度到與應用所服務的區(qū)域最近的節(jié)點上年鸳,以此來達到減少延遲趴久、提高用戶體驗的效果。
我為什么要用“可能適用的場景”來說明搔确?因為我覺得彼棍,看這篇文章的你應該可以想到更好的應用場景,歡迎留言討論膳算。
最后總結(jié)
接下來做個關鍵性的總結(jié):
- Node Affinity有兩種策略:
- requiredDuringSchedulingIgnoredDuringExecution:調(diào)度器只有在規(guī)則被滿足的時候才能執(zhí)行調(diào)度(硬策略)
- preferredDuringSchedulingIgnoredDuringExecution:調(diào)度器會嘗試尋找滿足對應規(guī)則的節(jié)點座硕。如果找不到匹配的節(jié)點,調(diào)度器仍然會調(diào)度該Pod(軟策略)
- 匹配方式有兩種:
- matchExpressions:基于標簽的匹配涕蜂,可以包含一個或多個條件华匾,每個條件由鍵、運算符和值組成宇葱,適用于更復雜的標簽匹配邏輯的場景瘦真。
- matchFields:允許基于節(jié)點的字段選擇節(jié)點刊头,而不是基于標簽黍瞧。比如指定節(jié)點上的字段名稱和值進行匹配。這對于選擇節(jié)點的特定屬性非常有用原杂,例如節(jié)點的操作系統(tǒng)印颤、內(nèi)存大小等。
- operator屬性可能的枚舉值:
- "DoesNotExist": 用于檢查標簽或注解不存在的情況穿肄。
- "Exists": 用于檢查標簽或注解存在的情況年局。
- "Gt": 用于數(shù)字類型的匹配,表示大于指定值咸产。
- "In": 用于匹配給定值列表中的任何一個值矢否。
- "Lt": 用于數(shù)字類型的匹配,表示小于指定值脑溢。
- "NotIn": 用于匹配不在給定值列表中的任何一個值僵朗。
希望本篇的實戰(zhàn)能對你理解和使用K8S中的Node Affinity特性有所幫助。你可以根據(jù)實際需求和集群環(huán)境,靈活應用Node Affinity來優(yōu)化應用的調(diào)度行為验庙。好了顶吮,本篇就到此結(jié)束,有問題可以評論區(qū)留言討論或者私信討論粪薛。
注重運維實戰(zhàn)悴了,我們比誰都拼!日常分享實用干貨违寿,助你成為運維大神湃交!探索技術的魅力,從這里開始陨界!
點擊鏈接巡揍,暢讀精彩文章,從中獲取洞見菌瘪,為自己的技術之旅注入新的動力腮敌!關注我的微信公眾號,不錯過更多精彩內(nèi)容俏扩。
【K8S(專注于深入研究K8S相關的各種技術和知識分享糜工。)】:https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzUzMTkyODc4NQ==&scene=1&album_id=2474851867500544003&count=3#wechat_redirect
【Go&Py(涵蓋了Go和Python兩種流行的編程語言。)】:https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzUzMTkyODc4NQ==&scene=1&album_id=2869340550028771330&count=3#wechat_redirect
【Ops(運維領域的討論和交流录淡。)】:https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzUzMTkyODc4NQ==&scene=1&album_id=2869345486221262853&count=3#wechat_redirect