iT邦幫忙

2026 iThome 鐵人賽

DAY 16
0
Kubernetes

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

Day 16|PriorityClass 與 Preemption — Pod 的優先級與搶佔機制

  • 分享至 

  • xImage
  •  

前言

昨天我們學了 topologySpreadConstraints —— 讓 Pod 在不同 Node 或 Zone 之間更均勻地分散。

到目前為止,排程系列已經涵蓋了:

  • Day 12:Scheduler 與資源管理 —— Pod 怎麼被分配到 Node
  • Day 13:Node Affinity 與 Taints & Tolerations —— 控制 Pod 與 Node 的關係
  • Day 14:Pod Affinity 與 Anti-Affinity —— 控制 Pod 與 Pod 的關係
  • Day 15:topologySpreadConstraints —— 讓 Pod 更均勻地分散

這些工具主要都在解決「Pod 該去哪裡」的問題。

但還有一個重要的情境:

如果叢集資源不夠,哪些 Pod 應該優先被排程?哪些 Pod 必須讓出資源?

這就是今天要介紹的 PriorityClass 與 Preemption

今天我們會學:

  1. 核心概念 — PriorityClass 與 Preemption 是什麼?
  2. 用比喻理解 — 急診分級制度
  3. PriorityClass 重要欄位valueglobalDefaultpreemptionPolicy
  4. Kubernetes 內建的 PriorityClasssystem-cluster-critical / system-node-critical
  5. 實作練習 — 建立自訂 PriorityClass,觀察 Preemption 行為
  6. preemptionPolicy: Never — 優先級高,但不主動搶佔其他 Pod

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


一、核心概念

PriorityClass

PriorityClass 是一個叢集層級的資源,不屬於任何 Namespace,用來定義 Pod 的優先級。

每個 PriorityClass 都有一個整數 value

數字越大,代表優先級越高。

Pod 可以透過:

spec:
  priorityClassName: high-priority

引用指定的 PriorityClass,Scheduler 就能知道這個 Pod 的優先級。

Preemption(搶佔)

當一個高優先級 Pod 因為資源不足而無法被排程時,Scheduler 可能會嘗試移除部分較低優先級的 Pod,騰出足夠的資源。

如果成功騰出空間,高優先級 Pod 就有機會被排程到該 Node。

這個機制就叫做 Preemption(搶佔)

排程流程

Scheduler 的決策流程可以簡化成:

  1. Pod 進入排程佇列,通常會優先處理 priority 較高的 Pod
  2. Scheduler 嘗試找到一台符合條件,而且有足夠資源的 Node
  3. 如果找不到合適的 Node,Scheduler 可能會評估是否能透過 Preemption 騰出空間
  4. 如果找到適合被搶佔的低優先級 Pod,這些 Pod 會進入終止流程
  5. 等資源釋放後,高優先級 Pod 才有機會被排程到該 Node

💡注意

Preemption 並不代表高優先級 Pod 一出現,就一定會立刻把低優先級 Pod 移除。

Scheduler 會先判斷:「如果把這些低優先級 Pod 移走,空出來的資源夠不夠讓高優先級 Pod 跑起來?」

如果夠,才會進行 Preemption;如果移除後還是不夠,就不會白白把這些 Pod 移除。


二、用比喻理解

想像一間急診室

  • 每位病患進來時都會被分級(Level 1 最嚴重 → Level 5 最輕微)
  • 醫生會優先處理高優先級的病患
  • 如果所有診間都滿了,這時來了一位 Level 1 病患,醫院可能會先讓較低優先級的病患離開診間,把資源讓給更緊急的病患
  • 這就像 Kubernetes 的 Preemption —— 高優先級 Pod 可以搶佔低優先級 Pod 的資源

對應到 Kubernetes:

急診室 Kubernetes
病患分級(Level 1–5) PriorityClass(value 越大,優先級越高)
診間 Node 的可用資源(CPU / Memory)
讓低優先級病患離開診間 Preemption —— 移除低優先級 Pod
醫生 Scheduler

三、PriorityClass 欄位詳解

基本結構

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000000
globalDefault: false
preemptionPolicy: PreemptLowerPriority
description: "高優先級,用於關鍵業務 Pod"

欄位說明

欄位 說明 預設值
value Pod 的優先級數值,數字越大,優先級越高。自訂 PriorityClass 的最大值為 1,000,000,000 (必填)
globalDefault 是否作為叢集的預設 PriorityClass。設為 true 後,沒有指定 priorityClassName 的新 Pod 會使用這個優先級;整個叢集只能有一個 false
preemptionPolicy PreemptLowerPriority:允許搶佔較低優先級的 Pod;Never:不主動搶佔,只保留較高的排程優先級 PreemptLowerPriority
description PriorityClass 的用途說明,方便維運人員理解 (選填)

💡 value 的範圍限制

自訂 PriorityClass 的 value 最大可以設定到1,000,000,000
超過 10 億 的優先級數值保留給 Kubernetes 內建的系統 PriorityClass 使用,因此自訂 PriorityClass 不應超過這個值。

如果沒有設定任何 globalDefault: true 的 PriorityClass,也沒有在 Pod 中指定 priorityClassName,該 Pod 的優先級預設為 0


四、內建 PriorityClass

Kubernetes 預設提供兩個內建的 PriorityClass,給系統關鍵元件使用:

kubectl get priorityclasses
名稱 value 用途
system-cluster-critical 2,000,000,000 叢集層級的重要系統元件
system-node-critical 2,000,001,000 Node 層級的重要系統元件,也是 Kubernetes 最高的 Pod 優先級

其中:

system-node-critical > system-cluster-critical

這兩個 PriorityClass 的數值都高於一般使用者可自訂的上限 1,000,000,000

💡為什麼系統元件需要這麼高的優先級?

像 DNS、網路等系統元件一旦無法正常運作,可能會影響整個叢集。

因此 Kubernetes 會給這些關鍵 Pod 很高的 Priority,讓它們在資源不足時能優先被排程,也比較不容易被較低優先級的工作負載影響。


五、實作練習:觀察 Preemption 行為

我們來模擬「資源不足時,高優先級 Pod 搶佔低優先級 Pod」的過程。

Step 1:建立兩個 PriorityClass

vim priority-classes.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: low-priority
value: 100
description: "低優先級 — 可被搶佔"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 10000
description: "高優先級 — 關鍵業務"
kubectl apply -f priority-classes.yaml
kubectl get priorityclasses

https://ithelp.ithome.com.tw/upload/images/20260818/2018192807ZZzuOpoZ.png

Step 2:用低優先級 Pod 把資源吃滿

先確認 Node 的可用資源:

kubectl describe nodes | grep -A 5 "Allocatable"

然後部署低優先級的 Pod,讓它們佔滿資源:

vim low-priority-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: low-priority-app
spec:
  replicas: 12
  selector:
    matchLabels:
      app: low-priority-app
  template:
    metadata:
      labels:
        app: low-priority-app
    spec:
      priorityClassName: low-priority
      containers:
      - name: busybox
        image: busybox
        command: ["sleep", "3600"]
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
kubectl apply -f low-priority-deploy.yaml
kubectl get pods -l app=low-priority-app -o wide

https://ithelp.ithome.com.tw/upload/images/20260818/20181928oYUxCvfMX4.png

💡 重點

可以調整 replicasresources.requests,讓低優先級 Pod 幾乎把 Node 可分配的資源用滿。

這樣下一步建立高優先級 Pod 時,Scheduler 才比較容易因為資源不足而觸發 Preemption

Step 3:部署高優先級 Pod,觀察搶佔

vim high-priority-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: high-priority-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: high-priority-app
  template:
    metadata:
      labels:
        app: high-priority-app
    spec:
      priorityClassName: high-priority
      containers:
      - name: nginx
        image: nginx
        resources:
          requests:
            cpu: "200m"
            memory: "128Mi"
kubectl apply -f high-priority-deploy.yaml

Step 4:觀察結果

# 看 Pod 狀態 — 只顯示本次實驗的 Pod,低優先級的某些 Pod 應該被驅逐了
kubectl get pods -l 'app in (low-priority-app, high-priority-app)' -o wide

# 看事件 — 會看到 Preemption 相關的事件
kubectl get events --sort-by='.lastTimestamp' | grep -i preempt

# 看高優先級 Pod 的詳細資訊
kubectl describe pod -l app=high-priority-app

https://ithelp.ithome.com.tw/upload/images/20260818/20181928pL0lbqG0Ry.png

你可能會觀察到:

  • 部分 low-priority-app 的 Pod 被終止,釋放 Node 資源
  • high-priority-app 的 Pod 成功排程到騰出的空間
  • Pod 的 Events 中可能看到與 Preemption 相關的排程訊息

💡被搶佔的低優先級 Pod 會怎樣?

如果這些 Pod 是由 Deployment 管理,Deployment Controller 會嘗試重新建立新的 Pod。

但此時資源可能已經被高優先級 Pod 使用,因此新建立的低優先級 Pod 可能會停留在 Pending,直到叢集再次有足夠資源。


六、preemptionPolicy: Never — 高優先級但不搶佔

有些場景下,你希望某些 Pod 的排隊順序靠前,但不要去驅逐別人。這時候可以用 preemptionPolicy: Never

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority-no-preempt
value: 10000
preemptionPolicy: Never
description: "高優先級但不搶佔 — 排隊優先,但不踢人"

💡 什麼時候用 Never

回到急診室的比喻:想像一位 VIP 病患,醫院會讓 VIP 優先排隊,但不會因此中斷正在進行中的看診,把其他病患趕走。

適合用在:

  • Batch Job:希望比一般工作更早被排程,但不希望因此搶佔正在執行的服務
  • 開發 / 測試環境的 Pod:希望有較高的排程優先級,但不要影響其他已經執行中的 Pod

行為差異對照

preemptionPolicy 排程優先級 資源不足時
PreemptLowerPriority(預設) Priority 較高的 Pod 會優先被 Scheduler 處理 可能透過 Preemption 移除較低優先級 Pod,騰出資源
Never 一樣享有較高的 Priority 不會主動搶佔其他 Pod,只能等待資源釋放

小結

今天我們學了 Kubernetes 排程系列的最後一塊拼圖 —— PriorityClass 與 Preemption

重點 說明
PriorityClass 叢集層級資源,透過 value 定義 Pod 優先級,數字越大代表優先級越高
Preemption 資源不足時,Scheduler 可能搶佔較低優先級的 Pod,為高優先級 Pod 騰出資源
內建 PriorityClass system-cluster-critical / system-node-critical,用於重要的系統元件
preemptionPolicy: Never Priority 仍然較高,但不主動搶佔其他 Pod,只等待資源釋放
value 範圍 自訂 PriorityClass 的最大值為 1,000,000,000,更高的數值保留給 Kubernetes 系統使用

排程系列完整回顧(Day 12–16)

Day 主題 解決的問題
Day 12 Scheduler 與資源管理 Pod 怎麼被分配到 Node、資源怎麼控管
Day 13 Node Affinity 與 Taints & Tolerations 控制 Pod 與 Node 的關係
Day 14 Pod Affinity 與 Anti-Affinity 控制 Pod 與 Pod 的關係
Day 15 topologySpreadConstraints 讓 Pod 在不同 Node / Zone 之間更均勻地分散
Day 16 PriorityClass 與 Preemption 資源不足時,決定 誰先被排程、誰需要讓出資源

到這裡,Kubernetes 排程系列就告一段落了!

我們從「Pod 該去哪裡」一路學到「資源不足時誰應該優先」,涵蓋了 Kubernetes 中常見的排程控制機制。

但回頭想想,我們目前討論的 Pod 大多都只有一個主要 Container。

在真實環境中,一個 Pod 啟動前經常需要先完成一些準備工作,例如:

  • 等待資料庫就緒
  • 下載設定檔
  • 初始化資料目錄

這些工作要怎麼在主要 Container 啟動前先完成?

明天我們來學 Init Container — Pod 啟動前的初始化機制,看看 Kubernetes 如何在應用程式正式啟動之前,先把必要的準備工作做好!


參考資源


上一篇
Day 15|topologySpreadConstraints — 更優雅的 Pod 分散機制
下一篇
Day 17|Init Container — Pod 啟動前的初始化機制
系列文
從零到 CKA:30 天掌握 Kubernetes 核心觀念與實作17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言