Kubernetes 的 Pod 調(diào)度的五種策略實(shí)戰(zhàn)講解
今天分享的幾種常用Pod調(diào)度策略,并根據(jù)實(shí)戰(zhàn)操作來加深原理理解,在生產(chǎn)環(huán)境也經(jīng)常使用。
Pod 的調(diào)度策略主要包括下面幾種:
- nodeSelector
- 親和性與反親和性
- nodeName
- Pod 拓?fù)浞植技s束
- 污點(diǎn)與容忍性

一、Pod調(diào)度概述
調(diào)度器通過 Kubernetes 的監(jiān)測(Watch)機(jī)制來發(fā)現(xiàn)集群中新創(chuàng)建且尚未被調(diào)度到節(jié)點(diǎn)上的 Pod。調(diào)度的主要任務(wù)是將Pod分配到集群中的合適的節(jié)點(diǎn)上。調(diào)度器根據(jù)Pod的需求(如CPU、內(nèi)存、存儲等)和節(jié)點(diǎn)的資源狀況(如可用CPU、內(nèi)存、節(jié)點(diǎn)標(biāo)簽等)來決定Pod部署在哪個節(jié)點(diǎn)上。
二、調(diào)度策略詳解
1. nodeSelector
nodeSelector 是 Kubernetes 中最簡單、最直觀的調(diào)度機(jī)制,它基于節(jié)點(diǎn)標(biāo)簽進(jìn)行 Pod 調(diào)度。節(jié)點(diǎn)標(biāo)簽是 Kubernetes 用于標(biāo)識節(jié)點(diǎn)屬性的鍵值對,調(diào)度器會根據(jù)這些標(biāo)簽來決定將 Pod 調(diào)度到哪個節(jié)點(diǎn)。
(1) 工作原理:
- 每個 Kubernetes 節(jié)點(diǎn)可以具有多個標(biāo)簽(labels)。標(biāo)簽是 key: value 的形式,通常表示節(jié)點(diǎn)的特征,如硬件類型、地區(qū)、環(huán)境等。
- Pod 的 nodeSelector 字段指定一組標(biāo)簽,調(diào)度器會篩選出具有這些標(biāo)簽的節(jié)點(diǎn),然后將 Pod 調(diào)度到這些節(jié)點(diǎn)。
(2) 使用場景:
- 環(huán)境隔離:比如,你有一些節(jié)點(diǎn)專門用于生產(chǎn)環(huán)境,其他節(jié)點(diǎn)用于測試環(huán)境,使用 nodeSelector 來確保 Pod 只在生產(chǎn)節(jié)點(diǎn)上運(yùn)行。
- 硬件要求:例如,某些應(yīng)用需要 SSD 磁盤或特定的 CPU 類型,你可以使用 nodeSelector 來確保 Pod 調(diào)度到符合這些硬件要求的節(jié)點(diǎn)。
(3) 實(shí)戰(zhàn)操作:
① 給節(jié)點(diǎn)打上標(biāo)簽
# 給k8s-node2節(jié)點(diǎn)打上ssd標(biāo)簽
kubectl label node k8s-node2 disktype=ssd
# 查看標(biāo)簽
kubectl get node k8s-node1 --show-labels② 編寫yaml文件
【溫馨提示】生產(chǎn)環(huán)境不要直接運(yùn)行pod,這里只是為了演示效果:
vim nodeSelector.yamlapiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeSelector:
disktype: ssd
containers:
- name: nginx
image: docker.m.daocloud.io/nginx:1.25運(yùn)行pod:
kubectl apply -f nodeSelector.yaml③ 查看pod調(diào)度情況
[root@k8s-master data]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 60s 10.224.169.149 k8s-node2 <none> <none>已經(jīng)根據(jù)節(jié)點(diǎn)標(biāo)簽將pod調(diào)度到node2節(jié)點(diǎn)。
(4) nodeSelector的優(yōu)缺點(diǎn):
- 優(yōu)點(diǎn):簡單高效。
- 缺點(diǎn):靈活性差,無法處理復(fù)雜的調(diào)度需求。
2. 親和性與反親和性
親和性(Affinity)和反親和性(Anti-Affinity)是比 nodeSelector 更強(qiáng)大、更靈活的調(diào)度策略。它們允許用戶根據(jù)更多的條件進(jìn)行節(jié)點(diǎn)選擇,比如節(jié)點(diǎn)的標(biāo)簽、Pod 的存在與否等。
- 親和性(Affinity):用于指定 Pod 需要盡量調(diào)度到某些節(jié)點(diǎn)上,基于節(jié)點(diǎn)標(biāo)簽、Pod 與節(jié)點(diǎn)的關(guān)系等。
- 反親和性(Anti-Affinity):用于指定 Pod 不應(yīng)該調(diào)度到某些節(jié)點(diǎn),或者應(yīng)該盡量避免和其他 Pod 調(diào)度到同一個節(jié)點(diǎn)上。
Kubernetes 中有兩種親和性:
- 節(jié)點(diǎn)親和性(Node Affinity)
- Pod 親和性與反親和性(Pod Affinity & Anti-Affinity)。
(1) 節(jié)點(diǎn)親和性
節(jié)點(diǎn)親和性是 nodeSelector 的增強(qiáng)版,允許基于更復(fù)雜的規(guī)則選擇節(jié)點(diǎn)。
實(shí)戰(zhàn)操作:
① 編寫yaml文件
vim nodeAffinity.yamlapiVersion: v1
kind: Pod
metadata:
name: nginx2
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx2
image: docker.m.daocloud.io/nginx:1.25確保 Pod 只會調(diào)度到具有 disktype=ssd標(biāo)簽的節(jié)點(diǎn)。
② 運(yùn)行pod
kubectl apply -f nodeAffinity.yaml③ 查看pod調(diào)度情況
[root@k8s-master data]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 27m 10.224.169.149 k8s-node2 <none> <none>
nginx2 1/1 Running 0 3m16s 10.224.169.154 k8s-node2 <none> <none>已經(jīng)將pod調(diào)度到預(yù)期的node上。
字段解釋:
- nodeAffinity 是定義節(jié)點(diǎn)選擇規(guī)則的字段。通過 requiredDuringSchedulingIgnoredDuringExecution(必須滿足調(diào)度時條件)和 preferredDuringSchedulingIgnoredDuringExecution(調(diào)度時首選,但不強(qiáng)制)來定義硬性和軟性約束。
- matchExpressions 支持使用 In、NotIn、Exists 等操作符,這些操作符使得你可以做更復(fù)雜的條件匹配。
operator 字段操作符說明:
操作符 | 說明 |
In | 指定值必須在給定的列表中 |
NotIn | 指定值不在給定的列表中 |
Exists | 指定鍵存在,不關(guān)心值 |
DoesNotExist | 指定鍵不存在 |
(2) Pod 親和性
Pod 親和性允許你指定 Pod 希望與其他 Pod 一起調(diào)度的偏好,而反親和性則表示 Pod 希望避免與某些 Pod 一起調(diào)度。
① 給前面創(chuàng)建的pod打上app=nginx1的標(biāo)簽
# 給使用nodeSelector創(chuàng)建的nginx打上標(biāo)簽
kubectl label pod nginx app=nginx1② 編寫yaml文件
vim podAffinity.yamlapiVersion: v1
kind: Pod
metadata:
name: nginx3
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 滿足條件才調(diào)度
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx1
topologyKey: "kubernetes.io/hostname"
containers:
- name: nginx3
image: docker.m.daocloud.io/nginx:1.25③ 運(yùn)行pod
kubectl apply -f podAffinity.yaml④ 查看調(diào)度情況
[root@k8s-master data]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 4h32m 10.224.169.149 k8s-node2 <none> <none>
nginx2 1/1 Running 0 4h8m 10.224.169.154 k8s-node2 <none> <none>
nginx3 1/1 Running 0 14s 10.224.169.153 k8s-node2 <none> <none>可見pod已經(jīng)調(diào)度到node2上,現(xiàn)在3個都運(yùn)行在node2上,接下來測試一下反親和性
(3) Pod 反親和性
要求 Pod 不與特定的 Pod 調(diào)度到同一節(jié)點(diǎn)上,通常用于防止某些類型的 Pod 集中到同一節(jié)點(diǎn)上,避免單點(diǎn)故障。
① 編寫yaml文件
vim podAntiAffinity.yamlapiVersion: v1
kind: Pod
metadata:
name: nginx4
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions: # 不要和具有app=nginx1標(biāo)簽的Pod在同一節(jié)點(diǎn)
- key: app
operator: In
values:
- nginx1
topologyKey: "kubernetes.io/hostname"
containers:
- name: app
image: docker.m.daocloud.io/nginx:1.25② 運(yùn)行pod
kubectl apply -f podAntiAffinity.yaml③ 查看調(diào)度情況
[root@k8s-master data]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 4h37m 10.224.169.149 k8s-node2 <none> <none>
nginx2 1/1 Running 0 4h13m 10.224.169.154 k8s-node2 <none> <none>
nginx3 1/1 Running 0 5m26s 10.224.169.153 k8s-node2 <none> <none>
nginx4 1/1 Running 0 10s 10.224.36.69 k8s-node1 <none> <none>可以看到新建的nginx4避免與標(biāo)簽為 app=nginx1的 Pod 調(diào)度到同一節(jié)點(diǎn)上,所以被調(diào)度到node1上,驗(yàn)證了pod的反親和性
親和性和反親和性優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
- 靈活性強(qiáng):支持多條件、復(fù)雜的調(diào)度規(guī)則,可以基于節(jié)點(diǎn)標(biāo)簽、Pod 標(biāo)簽、拓?fù)浣Y(jié)構(gòu)等進(jìn)行細(xì)粒度控制。
- 支持跨節(jié)點(diǎn)調(diào)度:可以控制 Pod 在集群中的分布,增強(qiáng)應(yīng)用的可用性和容錯性。
缺點(diǎn):
- 配置復(fù)雜:調(diào)度規(guī)則更加復(fù)雜,理解和配置起來需要更多的時間。
- 可能影響調(diào)度效率:當(dāng)使用大量的親和性和反親和性規(guī)則時,調(diào)度器需要更多時間來評估每個節(jié)點(diǎn)的匹配情況。
3. nodeName
nodeName 是 Kubernetes 中一種最簡單且強(qiáng)制性的調(diào)度方式,它允許你直接指定一個節(jié)點(diǎn)來運(yùn)行 Pod,而無需依賴調(diào)度器的調(diào)度決策。nodeName 適用于一些特殊場景,比如需要將 Pod 調(diào)度到特定的節(jié)點(diǎn)(例如硬件節(jié)點(diǎn),或特定的節(jié)點(diǎn)上有特定設(shè)備,如 GPU)。
實(shí)戰(zhàn)操作:
① 編寫yaml
vim nodeName.yamlapiVersion: v1
kind: Pod
metadata:
name: nginx5
spec:
nodeName: k8s-node1
containers:
- name: nginx5
image: docker.m.daocloud.io/nginx:1.25② 運(yùn)行pod
kubectl apply -f nodeName.yaml③ 查看調(diào)度情況
[root@k8s-master data]# kubectl get pod nginx5 -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx5 1/1 Running 0 47s 10.224.36.70 k8s-node1 <none> <none>可以看到Pod nginx5 會被直接調(diào)度到 node1節(jié)點(diǎn)上。
nodeName優(yōu)缺點(diǎn):
- 優(yōu)點(diǎn):簡單、直觀,適用于需要特定硬件或設(shè)備的場景。
- 缺點(diǎn):失去調(diào)度器的靈活性,不適用于動態(tài)環(huán)境。
4. Pod 拓?fù)浞植技s束
Pod 拓?fù)浞植技s束用于保證 Pod 在多個節(jié)點(diǎn)、區(qū)域或故障域中的均衡分布。通過設(shè)置 topologySpreadConstraints,可以確保 Pod 在集群中分布更加均衡,避免 Pod 集中到某個節(jié)點(diǎn)或某個區(qū)域,從而增強(qiáng)集群的高可用性和容災(zāi)能力。
apiVersion: v1
kind: Pod
metadata:
name: nginx6
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: nginx
containers:
- name: nginx6
image: docker.m.daocloud.io/nginx:1.25[root@k8s-master data]# kubectl get pod nginx6 -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx6 1/1 Running 0 37s 10.224.36.71 k8s-node1 <none> <none>使用deployment來演示可能效果更明顯.
topologySpreadConstraints 保證 nginx Pod 在不同的主機(jī)上均勻分布。maxSkew 控制 Pod 在各個節(jié)點(diǎn)之間的最大不平衡度,而 topologyKey 是表示分布維度的關(guān)鍵字段,kubernetes.io/hostname 表示按主機(jī)名進(jìn)行分布。
優(yōu)缺點(diǎn):
- 優(yōu)點(diǎn):保證 Pod 在多個節(jié)點(diǎn)、區(qū)域的均衡分布,提高高可用性。
- 缺點(diǎn):配置較復(fù)雜,可能對調(diào)度性能產(chǎn)生影響。
5. 污點(diǎn)與容忍性
污點(diǎn)(Taints)和容忍性(Tolerations)是 Kubernetes 的一對調(diào)度機(jī)制,用于控制 Pod 是否能調(diào)度到帶有某些特定條件的節(jié)點(diǎn)。節(jié)點(diǎn)可以加上污點(diǎn),只有設(shè)置了相應(yīng)容忍性的 Pod 才能調(diào)度到這些節(jié)點(diǎn)。
污點(diǎn)(Taints) 是對節(jié)點(diǎn)的標(biāo)記,表示該節(jié)點(diǎn)不希望接受不符合條件的 Pod。容忍(Tolerations) 是 Pod 上的標(biāo)記,表示 Pod 能夠“容忍”某些污點(diǎn)。
(1) 實(shí)戰(zhàn)操作:
① 給節(jié)點(diǎn)加污點(diǎn):
# 在節(jié)點(diǎn)1上添加污點(diǎn)
kubectl taint nodes k8s-node1 key=value:NoSchedule【溫馨提示】設(shè)置污點(diǎn)后,新建的pod如果沒有設(shè)置容忍,都無法調(diào)度到該節(jié)點(diǎn),已存在的pod不受影響。
② Pod 上設(shè)置容忍性:
vim tolerations.yamlapiVersion: v1
kind: Pod
metadata:
name: nginx7
spec:
tolerations: # 配置容忍規(guī)則,需要完全匹配才可以調(diào)度到有污點(diǎn)的節(jié)點(diǎn)
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
containers:
- name: nginx7
image: docker.m.daocloud.io/nginx:1.25③ 查看調(diào)度情況
[root@k8s-master data]# kubectl get pod nginx7 -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx7 1/1 Running 0 32s 10.224.36.72 k8s-node1 <none> <none>nginx7被調(diào)度到設(shè)置了污點(diǎn)的節(jié)點(diǎn),說明tolerations生效了,容忍了污點(diǎn)。
④ 去除污點(diǎn)(taint)
kubectl taint node k8s-node1 key-(2) 優(yōu)缺點(diǎn):
- 優(yōu)點(diǎn):提供了靈活的節(jié)點(diǎn)隔離和調(diào)度控制,適用于隔離特定類型的工作負(fù)載或維護(hù)節(jié)點(diǎn)。
- 缺點(diǎn):配置復(fù)雜,濫用污點(diǎn)可能導(dǎo)致資源浪費(fèi)或 Pod 調(diào)度錯誤。
三、總結(jié)
Kubernetes 提供了多種調(diào)度策略,可以根據(jù)不同的需求靈活選擇:
- nodeSelector:簡單的節(jié)點(diǎn)標(biāo)簽匹配調(diào)度。
- 親和性與反親和性:更靈活的調(diào)度控制,基于節(jié)點(diǎn)和 Pod 之間的關(guān)系進(jìn)行調(diào)度。
- nodeName:直接指定節(jié)點(diǎn)進(jìn)行調(diào)度。
- Pod 拓?fù)浞植技s束:確保 Pod 在集群中的均衡分布,增強(qiáng)高可用性。
- 污點(diǎn)與容忍性:通過污點(diǎn)和容忍性控制哪些 Pod 可以調(diào)度到哪些節(jié)點(diǎn)。
通過合理組合這些調(diào)度策略,你可以優(yōu)化 Pod 的資源分配、提升集群的可靠性和性能。
































