iT邦幫忙

2026 iThome 鐵人賽

DAY 7
0
Kubernetes

Kubernetes學習心得分享系列 第 7

Day 07:【調度】 進階節點親和性與污點容忍機制

  • 分享至 

  • xImage
  •  

前言

寫這篇想要分享的重點:
在 Kubernetes 叢集中,如何控制 Pod 的調度行為?本篇將深入剖析 Taints/Tolerations(污點與容忍)與 Node Affinity(節點親和性)的運作邏輯,並分享如何結合兩者,將特定的Pod綁定至指定硬體規格的節點。

這篇想要講什麼:

  1. Taints 與 Tolerations 的三個效果 (NoSchedule, PreferNoSchedule, NoExecute) 與運作方式。
  2. Node Affinity 的匹配運算子 (In, NotIn, Exists) 與兩個階段類型 (requiredDuringScheduling..., preferredDuringScheduling...)。
  3. 實戰:為什麼單靠 Taints 或 Node Affinity 無法達到完全的「專屬節點隔離」?如何兩者配合做到雙向排他與綁定?

為何要寫這篇:
在設定調度規則時,常搞混「驅逐」與「吸引」的概念,導致 Pod 被派發到不適合的機器,或是無法成功綁定 GPU/高算力節點。掌握這套排他與吸引機制,是建構高可用與高效能叢集的基礎技能。

名詞對應

  • Pod: 容器組
  • Node: 節點
  • Scheduler: 調度器
  • Taint: 污點
  • Toleration: 容忍度
  • Node Affinity: 節點親和性

Taints 與 Tolerations 運作原理

Taints(污點)是作用在 Node 上的標記,用來「拒絕」不符合條件的 Pod 排入;而 Tolerations(容忍度)則是設定在 Pod 上的屬性,代表該 Pod 可以「容忍」Node 上的特定污點。

簡單比喻:Taint 就像是驅蟲劑,預設會把所有 Pod 驅離;只有身上帶有對應 Toleration 護身符的 Pod,才能順利停靠。

Taint 的三種 Effect 影響效果

  1. NoSchedule:如果 Pod 沒有對應的 Toleration,調度器絕對不會將 Pod 調度到該 Node 上。但已存在於該 Node 上的 Pod 不受影響。
  2. PreferNoSchedule:軟限制。調度器會儘量避免將 Pod 調度到該 Node,但若全叢集無其他可用資源,仍可能勉強調度過去。
  3. NoExecute:強烈限制。不僅新 Pod 無法調度上去,若 Node 上已運行的 Pod 沒有對應 Toleration,會立即被踢出 (Evicted)

設定語法與範例

在 Node 上設定 Taint:

kubectl taint nodes node-gpu hardware=nvidia-a100:NoSchedule

在 Pod 的 spec 中設定 Toleration:

apiVersion: v1
kind: Pod
metadata:
  name: gpu-training-job
spec:
  containers:
  - name: cuda-test
    image: nvidia/cuda:11.0-base
  tolerations:
  - key: "hardware"
    operator: "Equal"
    value: "nvidia-a100"
    effect: "NoSchedule"

Node Affinity 節點親和性機制

與 Taints 這種「排他」邏輯不同,Node Affinity(節點親和性)是以「吸引」的方式,根據 Node 上的 Labels(標籤)來選擇 Pod 要投遞的目标 Node。

Node Affinity 的兩種核心類型

  1. requiredDuringSchedulingIgnoredDuringExecution (硬要求):
    • Scheduling 階段:必須滿足條件才會調度;若無匹配 Node,Pod 會持續處於 Pending 狀態。
    • Execution 階段: Pod 跑起來後,若 Node Label 發生變動導致條件不符,忽略變更,Pod 繼續保持運行
  2. preferredDuringSchedulingIgnoredDuringExecution (軟要求):
    • Scheduling 階段:儘量尋找符合條件的 Node;若找不到,調度器會退而求其次將 Pod 放在其他普通 Node 上。
    • Execution 階段:同樣忽略後續 Label 變動。

💡 區別法,重點在第一個單字:

  • required... $\rightarrow$ 「必須/硬要求」口訣:非他不可。沒找到合適的 Node,就不調度(Pending)。
  • preferred... $\rightarrow$ 「偏好/軟要求」口訣:有他更好。有 match 的 Node 最好,沒有也隨便啦,能跑就行。

語法範例 (使用 In / Exists / NotIn 運算子)

apiVersion: v1
kind: Pod
metadata:
  name: backend-service
spec:
  affinity:
    nodeAffinity: # <-- 1. 啟用 Node 條件篩選 (開關)
      requiredDuringSchedulingIgnoredDuringExecution: # <-- 2. 硬要求:不符就 Pending
        nodeSelectorTerms: # <-- 3. 條件組清單 [組間為 OR 邏輯:滿足任一組即可]
        - matchExpressions: # <-- 4. 表達式清單 [組內為 AND 邏輯:必須同時滿足]
          - key: instance-type
            operator: In # <-- 5. 運算子:In / NotIn / Exists / DoesNotExist / Gt / Lt
            values:
            - high-memory
            - compute-optimized
  containers:
  - name: app
    image: nginx

matchExpressions 運算子(Operators)範例

Kubernetes 的 matchExpressions 支援以下 6 種運算子:

1. In(包含於清單中)

  • 說明:Node 的 Key 數值必須等於 values 清單中的任意一個
  • 範例(即你的 YAML)
key: instance-type
operator: In
values:
- high-memory
- compute-optimized

  • 效果:Node 必須擁有標籤 instance-type=high-memory 或者 instance-type=compute-optimized

2. NotIn(不包含於清單中)

  • 說明:Node 的 Key 數值不能values 清單中的任何一個。常用於避開特定節點(例如老舊機器或測試機)。
  • 範例
key: environment
operator: NotIn
values:
- testing
- staging

  • 效果:絕對不排程到 environment=testingenvironment=staging 的 Node 上。

3. Exists(鍵存在即可)

  • 說明:只要 Node 擁有這個 key 標籤即可,不在乎 Value 是什麼
  • 注意:使用 ExistsDoesNotExist 時,不能values 欄位(否則 YAML 會報錯)。
  • 範例
key: gpu-attached
operator: Exists

  • 效果:只要 Node 身上帶有 gpu-attached 這個 Key(例如 gpu-attached=truegpu-attached=nvidia-t4),都符合條件。

4. DoesNotExist(鍵不存在)

  • 說明:Node 絕對不能擁有這個 key 標籤。
  • 範例
key: maintenance-mode
operator: DoesNotExist

  • 效果:避開所有被標記為維護中(帶有 maintenance-mode 標籤)的 Node。

5. Gt (Greater Than) 與 Lt (Less Than)

  • 說明:進行數字大小比較values 欄位只能包含一個字串格式的數字。
  • 範例
key: cpu-cores
operator: Gt
values:
- "8"

  • 效果:只排程到 CPU 核心數大於 8 的 Node 上。

常見運算子對照與場景整理

運算子 values 欄位 邏輯意義 常見場景
In 必須提供(可多個) $\text{Key} \in {\text{Val}_1, \text{Val}_2}$ 限定特定機型(high-memory)、地區(us-east-1a)。
NotIn 必須提供(可多個) $\text{Key} \notin {\text{Val}_1, \text{Val}_2}$ 排除故障節點、避開搶佔式實例(Spot Instance)。
Exists 不可提供 標籤 Key 存在即可 尋找有特殊硬體(如 GPU/SSD)的機器。
DoesNotExist 不可提供 標籤 Key 不可存在 避開被打上特定標籤(如維護中、隔離中)的機器。
Gt / Lt 必須提供(限 1 個數字) 數值比大小 依據節點自訂的性能分數或規格進行門檻篩選。

實戰組合:精準綁定硬體規格節點

常見問題:「如果我有一批帶有 GPU 的超強節點,只希望 AI 訓練 Pod 部署上去,且一般服務絕對不能佔用他,要怎麼設定?」

  • 只用 Taints/Tolerations:一般 Pod 進不去 GPU Node,但 AI Pod 可能會被調度到一般普通 Node 上(因為 Toleration 只代表「可以去」,不代表「一定要去」)。➡️ 失敗
  • 只用 Node Affinity:AI Pod 一定會去 GPU Node,但一般的 Pod 沒有設定 Affinity,依然可能被調度到 GPU Node 佔用資源。➡️ 失敗

最佳解:雙向綁定 (Taints + Node Affinity)

  1. 對專用節點上記號 (Taint + Label):

    # 上 Taint 阻擋一般 Pod
    kubectl taint nodes node-gpu dedicated=ai-workload:NoSchedule
    # 上 Label 提供 Affinity 識別
    kubectl label nodes node-gpu dedicated=ai-workload
    
  2. 在專用 Pod 上設定雙向配置 (Toleration + NodeAffinity):

    apiVersion: v1
    kind: Pod
    metadata:
      name: deep-learning-pod
    spec:
      # 1. 允許進入帶有污點的專用 Node
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "ai-workload"
        effect: "NoSchedule"
      # 2. 強制指定一定要進入帶有此 Label 的 Node
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: dedicated
                operator: In
                values:
                - ai-workload
      containers:
      - name: trainer
        image: tensorflow/tensorflow:latest-gpu
    

透過雙向設定:

  • 一般 Pod 無法侵入 GPU 節點(被 Taint 擋下)。
  • AI Pod 一定只會落在 GPU 節點上(被 Node Affinity 強制鎖定)。

總結

  • 本篇總結:
    Taints/Tolerations 負責「設定門檻阻擋不合適的 Pod」,而 Node Affinity 則負責「主動吸引特定 Pod 到合適的節點」;唯有將兩者組合使用,才能實現真正的節點專屬隔離與精準調度。
  • 下一篇預告:
    解決了 Pod 要放在哪台機器的調度問題後,下回 Day 08 我們將探討 容器資源限制與配額管理 (Limits & Quotas)——深入分析 CPU/Memory Requests 與 Limits 的差異,並透過 LimitRange 與 ResourceQuota 避免某些容器將 Namespace 資源吃光!敬請期待!

Takeaway

  • 驅離與吸引的差別:Taints(污點)是 Node 用來拒絕 Pod 的「門檻機制」;Node Affinity(節點親和性)則是 Pod 主動選擇特定 Node 的「吸引機制」。
  • Taint 三效果NoSchedule 阻擋新 Pod 進駐;PreferNoSchedule 盡量避免但不強制;NoExecute 則會強制驅逐(Evict)現有未設定容忍度的 Pod。
  • Affinity 兩大階段requiredDuringScheduling... 是硬要求,配對失敗會導致 PendingpreferredDuringScheduling... 是軟要求,找不到目標會退而求其次調度。
  • 專屬節點雙向綁定:若要劃分專屬節點(如 GPU 機器),必須同時給 Node 上 Taint 與 Label,並在 Pod 設定對應 Toleration 與 Node Affinity,避免一般 Pod 侵入或專用 Pod 被調度到普通節點。

上一篇
Day 06:【排程】 節點分配與手動調度控制
下一篇
Day 08:【資源】 容器資源限制與配額管理 (Limits & Quotas)
系列文
Kubernetes學習心得分享8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言