昨天我們學了 topologySpreadConstraints —— 讓 Pod 在不同 Node 或 Zone 之間更均勻地分散。
到目前為止,排程系列已經涵蓋了:
這些工具主要都在解決「Pod 該去哪裡」的問題。
但還有一個重要的情境:
如果叢集資源不夠,哪些 Pod 應該優先被排程?哪些 Pod 必須讓出資源?
這就是今天要介紹的 PriorityClass 與 Preemption。
今天我們會學:
value、globalDefault、preemptionPolicy
system-cluster-critical / system-node-critical
以下操作皆在 master 節點 執行。
PriorityClass 是一個叢集層級的資源,不屬於任何 Namespace,用來定義 Pod 的優先級。
每個 PriorityClass 都有一個整數 value:
數字越大,代表優先級越高。
Pod 可以透過:
spec:
priorityClassName: high-priority
引用指定的 PriorityClass,Scheduler 就能知道這個 Pod 的優先級。
當一個高優先級 Pod 因為資源不足而無法被排程時,Scheduler 可能會嘗試移除部分較低優先級的 Pod,騰出足夠的資源。
如果成功騰出空間,高優先級 Pod 就有機會被排程到該 Node。
這個機制就叫做 Preemption(搶佔)。
Scheduler 的決策流程可以簡化成:
💡注意
Preemption 並不代表高優先級 Pod 一出現,就一定會立刻把低優先級 Pod 移除。
Scheduler 會先判斷:「如果把這些低優先級 Pod 移走,空出來的資源夠不夠讓高優先級 Pod 跑起來?」
如果夠,才會進行 Preemption;如果移除後還是不夠,就不會白白把這些 Pod 移除。
想像一間急診室:
對應到 Kubernetes:
| 急診室 | Kubernetes |
|---|---|
| 病患分級(Level 1–5) | PriorityClass(value 越大,優先級越高) |
| 診間 | Node 的可用資源(CPU / Memory) |
| 讓低優先級病患離開診間 | Preemption —— 移除低優先級 Pod |
| 醫生 | Scheduler |
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。
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,讓它們在資源不足時能優先被排程,也比較不容易被較低優先級的工作負載影響。
我們來模擬「資源不足時,高優先級 Pod 搶佔低優先級 Pod」的過程。
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

先確認 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

💡 重點
可以調整
replicas和resources.requests,讓低優先級 Pod 幾乎把 Node 可分配的資源用滿。這樣下一步建立高優先級 Pod 時,Scheduler 才比較容易因為資源不足而觸發 Preemption。
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
# 看 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

你可能會觀察到:
low-priority-app 的 Pod 被終止,釋放 Node 資源high-priority-app 的 Pod 成功排程到騰出的空間💡被搶佔的低優先級 Pod 會怎樣?
如果這些 Pod 是由 Deployment 管理,Deployment Controller 會嘗試重新建立新的 Pod。
但此時資源可能已經被高優先級 Pod 使用,因此新建立的低優先級 Pod 可能會停留在
Pending,直到叢集再次有足夠資源。
有些場景下,你希望某些 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 | 主題 | 解決的問題 |
|---|---|---|
| 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 如何在應用程式正式啟動之前,先把必要的準備工作做好!