iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
Kubernetes

從零到 CKA:30 天掌握 Kubernetes 核心觀念與實作系列 第 15

Day 15|topologySpreadConstraints — 更優雅的 Pod 分散機制

  • 分享至 

  • xImage
  •  

前言

昨天我們學了 Pod Affinity 與 Anti-Affinity,用來控制 Pod 之間的排程關係。

其中 Pod Anti-Affinity 可以讓副本分散到不同 Node,但如果我們想進一步控制「分散得多均勻」,就需要更細緻的機制。

例如:

  • 3 台 Node、4 個 Pod,希望盡量平均分散,而不是單純要求「不要放在一起」
  • required 太嚴格,可能導致 Pod Pending
  • preferred 只是偏好,無法保證分散程度
  • 在大型叢集中,Pod Affinity / Anti-Affinity 的排程計算成本也可能較高

這時候就可以使用 Topology Spread Constraints

topologySpreadConstraints 在 Kubernetes v1.19 正式 GA,可以控制 Pod 在不同 Node、Zone 等拓樸範圍之間的分布差距。

今天我們會學:

  1. 核心概念maxSkewtopologyKeywhenUnsatisfiable
  2. 實作練習 — 讓 Pod 均勻分散到不同 Node
  3. 進階欄位minDomainsnodeAffinityPolicynodeTaintsPolicy
  4. 多條件組合 — 同時跨 Node + 跨 Zone 分散
  5. 與 Pod Anti-Affinity 比較 — 什麼情況該用哪一個?

以下操作皆在 master 節點 執行。


一、核心概念

topologySpreadConstraints 的核心概念是:限制 Pod 在不同拓樸域之間可以相差多少,讓 Scheduler 在排程時盡量維持較平均的分布。

基本欄位

欄位 說明 範例
maxSkew 允許的最大分布差距 1 = 各拓樸域之間盡量不要差超過 1 個 Pod
topologyKey 定義拓樸域的範圍 kubernetes.io/hostname
whenUnsatisfiable 無法滿足分散條件時要怎麼處理 DoNotSchedule(硬性)/ ScheduleAnyway(軟性)
labelSelector 指定哪些 Pod 要一起計算分布 app: web

用比喻理解

想像你在發撲克牌:

  • Pod Anti-Affinity:「盡量不要把特定的牌放在一起」→ 關注 Pod 是否要彼此分開
  • topologySpreadConstraints:「每個人的牌數不要差太多」→ 關注 Pod 分布得均不均勻

skew 怎麼理解?

skew 可以先簡單理解成:

表示 Pod 在不同 Node(或 Zone)之間分布得有多不平均。

例如有 3 台 Node,目前 Pod 分布為:

Node-1:3 個
Node-2:2 個
Node-3:1 個

以最少的 Node-3 為基準,可以理解成:

  • Node-1:差 2 個
  • Node-2:差 1 個
  • Node-3:差 0 個

如果設定:

maxSkew: 1

代表 Scheduler 會限制 Pod 分布不要過度失衡。

因此下一個 Pod 不會繼續排到已經很多 Pod 的 Node-1,而會優先考慮能讓整體分布維持在 maxSkew 限制內的 Node。


二、基本實作:均勻分散 Pod 到各 Node

Step 1:建立 Deployment

vim web-tsc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-tsc
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web-tsc
  template:
    metadata:
      labels:
        app: web-tsc
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: kubernetes.io/hostname
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: web-tsc
      containers:
      - name: nginx
        image: nginx
kubectl apply -f web-tsc.yaml

💡 解讀這段 YAML

「把所有 app=web-tsc 的 Pod 分散到不同 Node 上,並盡量維持平均分布。」

因為設定了 maxSkew: 1,代表各 Node 上符合條件的 Pod 數量差距最多允許相差 1 個。

如果新的 Pod 會讓分布超過這個限制,whenUnsatisfiable: DoNotSchedule 會阻止它被排程。

Step 2:觀察行為

kubectl get pods -l app=web-tsc -o wide

觀察 Pod 的分布結果:

https://ithelp.ithome.com.tw/upload/images/20260817/201819283JIjisvLvG.png

  • 2 台 Node、4 個副本 → 每台 2 個 ✅
  • 2 台 Node、3 個副本 → 一台 2 個、一台 1 個 ✅

因為設定了 maxSkew: 1,所以各 Node 之間符合條件的 Pod 數量差距最多只能相差 1 個。

Step 3:改用 ScheduleAnyway(軟性約束)

如果不希望 Pod 因為無法完全符合分散條件而停留在 Pending,可以把:

vim web-tsc-soft.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-tsc-soft
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web-tsc-soft
  template:
    metadata:
      labels:
        app: web-tsc-soft
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: kubernetes.io/hostname
        whenUnsatisfiable: ScheduleAnyway
        labelSelector:
          matchLabels:
            app: web-tsc-soft
      containers:
      - name: nginx
        image: nginx
kubectl apply -f web-tsc-soft.yaml
kubectl get pods -l app=web-tsc-soft -o wide

這次即使 Pod 的分布暫時不夠平均,也不會因此停留在 Pending

https://ithelp.ithome.com.tw/upload/images/20260817/20181928q8giJOAiXJ.png

ScheduleAnyway 代表 Scheduler 會盡量讓 Pod 分布得更均勻,但不會把它當成硬性限制。


三、進階欄位

除了基本的 maxSkewtopologyKeywhenUnsatisfiable 之外,topologySpreadConstraints 還提供一些更進階的控制欄位:

欄位 說明
minDomains 指定至少要有多少個「分散範圍」參與計算,例如幾台 Node 或幾個 Zone
nodeAffinityPolicy 決定計算分布時,是否只考慮符合 Pod nodeAffinity / nodeSelector 的 Node
nodeTaintsPolicy 決定計算分布時,是否考慮 Node 的 Taint 與 Pod 的 Toleration
matchLabelKeys 從 Pod 自己的 Label 取得值,進一步決定哪些 Pod 要一起計算分布

這些欄位主要用在更複雜的排程情境,現階段先知道它們的用途即可。

minDomains 的實用場景

假設我們使用:

topologyKey: kubernetes.io/hostname
maxSkew: 1
minDomains: 3

因為 topologyKeykubernetes.io/hostname,所以這裡可以直接把 minDomains: 3 理解成:

希望至少有 3 台符合條件的 Node 參與 Pod 的分散。

如果目前實際只有 1 台符合條件的 Node,Scheduler 在計算分布時會把最低基準視為 0

當這台 Node 上的 Pod 數量繼續增加,就可能超過 maxSkew: 1,使新的 Pod 無法再被排程。

這可以避免 Pod 在可用 Node 太少時,持續全部集中到同一台 Node。


四、多條件組合:同時跨 Node + 跨 Zone 均勻分散

在雲端環境中,叢集可能同時跨越多個 Zone,而且每個 Zone 裡又有多台 Node。

這時候可能同時有兩個需求:

  • 跨 Zone 均勻:讓 Pod 盡量平均分布在不同可用區
  • 跨 Node 均勻:同一個 Zone 內,也盡量不要讓 Pod 集中在同一台 Node
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-multi-tsc
spec:
  replicas: 6
  selector:
    matchLabels:
      app: web-multi-tsc
  template:
    metadata:
      labels:
        app: web-multi-tsc
    spec:
      topologySpreadConstraints:
      # 條件 1:跨 Zone 均勻分散
      - maxSkew: 1
        topologyKey: topology.kubernetes.io/zone
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: web-multi-tsc

      # 條件 2:跨 Node 均勻分散
      - maxSkew: 1
        topologyKey: kubernetes.io/hostname
        whenUnsatisfiable: ScheduleAnyway
        labelSelector:
          matchLabels:
            app: web-multi-tsc

      containers:
      - name: nginx
        image: nginx

💡 解讀這段 YAML

  • 跨 Zone:使用 DoNotSchedule,把 Zone 之間的分散當成硬性限制
  • 跨 Node:使用 ScheduleAnyway,讓 Scheduler 盡量把 Pod 分散到不同 Node,但不強制

這樣可以優先確保 Pod 不會過度集中在同一個 Zone,同時也盡量讓同一個 Zone 內的 Pod 分散到不同 Node。

練習環境注意

在一般的 kubeadm 練習環境中,通常不會特別設定多個 Zone,Node 也可能沒有 topology.kubernetes.io/zone Label。

因此這類跨 Zone 的分散策略,在具有多個 Zone 的叢集環境中會比較容易觀察到效果。


五、跟 Pod Anti-Affinity 的完整比較

比較項目 Pod Anti-Affinity topologySpreadConstraints
主要目標 讓 Pod 避開符合條件的其他 Pod 讓 Pod 在不同 Node、Zone 等範圍中均勻分布
控制方式 控制「要不要跟其他 Pod 在同一個範圍」 透過 maxSkew 控制允許的分布差距
硬性 / 軟性 required / preferred DoNotSchedule / ScheduleAnyway
大型叢集 Pod Anti-Affinity 的排程計算成本較高 更適合表達大量副本的均勻分散需求
多條件組合 可以設定多條規則 可以設定多個 topologySpreadConstraints
適用場景 Pod 之間需要明確避開彼此 需要控制副本在 Node / Zone 之間的分布均勻度

實務上怎麼選?

  • 如果需求是「這兩個 Pod 不要在一起」→ 使用 Pod Anti-Affinity
  • 如果需求是「這些副本要盡量平均分散」→ 使用 topologySpreadConstraints
  • 兩者也可以搭配其他排程機制一起使用,例如用 Pod Affinity 讓 Web 靠近 Cache,再用 topologySpreadConstraints 讓 Web 副本跨 Zone 分散

小結

今天我們學了 Kubernetes 用來控制 Pod 均勻分散的機制 —— topologySpreadConstraints

重點 說明
maxSkew 控制不同 Node 或 Zone 之間,Pod 數量允許相差多少
topologyKey 定義 Pod 的分散範圍,例如 hostname / zone / region
whenUnsatisfiable DoNotSchedule(硬性)vs ScheduleAnyway(軟性)
多條件組合 可以同時控制跨 Zone 與跨 Node 的分布
vs Anti-Affinity Anti-Affinity 著重 Pod 彼此避開;topologySpreadConstraints 著重副本均勻分散

到這裡,我們已經掌握了 Kubernetes 排程的主要控制機制。

但如果叢集資源不足,哪些 Pod 應該優先被排程?哪些 Pod 可以讓出資源?

明天我們來看看 PriorityClass 與 Preemption,了解 Kubernetes 如何透過 Pod 優先級與搶佔機制,在資源不足時決定誰先執行、誰需要讓出位置!


參考資源


上一篇
Day 14|Pod Affinity 與 Anti-Affinity — 控制 Pod 之間的排程關係
下一篇
Day 16|PriorityClass 與 Preemption — Pod 的優先級與搶佔機制
系列文
從零到 CKA:30 天掌握 Kubernetes 核心觀念與實作16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言