前言
在 Kubernetes 叢集的日常營運中,節點維護、叢集升級、自動擴縮容等操作都可能導致 Pod 被終止或重新調度。為了確保應用程式在這些操作期間仍能維持一定的可用性,Kubernetes 提供了 PodDisruptionBudget (PDB) 這個重要的資源物件。本文將詳細介紹 PDB 的概念、設定方式與最佳實踐。
PodDisruptionBudget 概述
PodDisruptionBudget 是 Kubernetes 中用於保護應用程式可用性的機制。它允許叢集管理員定義在進行自願性中斷(Voluntary Disruption)時,必須維持的最小可用 Pod 數量或最大不可用 Pod 數量。
PDB 的主要用途包括:
- 確保在節點維護期間,應用程式仍有足夠的副本數量來處理請求
- 防止叢集自動擴縮容過程中同時終止過多 Pod
- 保障滾動更新時的服務可用性
自願與非自願中斷
在 Kubernetes 中,Pod 的中斷可分為兩種類型:
非自願中斷(Involuntary Disruption)
非自願中斷是指無法預期或控制的事件,PDB 無法防止這類中斷:
- 硬體故障導致節點失效
- 雲端供應商的虛擬機器被意外刪除
- 核心層級的錯誤(Kernel Panic)
- 網路分區導致節點與叢集失聯
- 節點資源不足導致 Pod 被驅逐
自願中斷(Voluntary Disruption)
自願中斷是由叢集管理員或自動化系統主動發起的操作,PDB 可以限制這類中斷的影響:
- 節點排空(Node Drain)進行維護
- 叢集升級
- Deployment 的滾動更新
- 叢集自動擴縮容(Cluster Autoscaler)縮減節點
- 手動刪除 Pod
PDB 設定參數
PDB 透過以下主要參數來定義可用性保障:
minAvailable 設定
minAvailable 指定在任何時候必須維持可用的最小 Pod 數量。可以設定為整數或百分比。
1
2
3
4
5
6
7
8
9
10
| apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-app-pdb
namespace: production
spec:
minAvailable: 2
selector:
matchLabels:
app: web-app
|
使用百分比的範例:
1
2
3
4
5
6
7
8
9
10
| apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-server-pdb
namespace: production
spec:
minAvailable: "50%"
selector:
matchLabels:
app: api-server
|
maxUnavailable 設定
maxUnavailable 指定在任何時候允許不可用的最大 Pod 數量。同樣可以設定為整數或百分比。
1
2
3
4
5
6
7
8
9
10
| apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: worker-pdb
namespace: production
spec:
maxUnavailable: 1
selector:
matchLabels:
app: worker
|
使用百分比的範例:
1
2
3
4
5
6
7
8
9
10
| apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: cache-pdb
namespace: production
spec:
maxUnavailable: "25%"
selector:
matchLabels:
app: cache
|
注意:minAvailable 與 maxUnavailable 不能同時設定,只能擇一使用。
標籤選擇器
PDB 透過標籤選擇器(Label Selector)來指定要保護的 Pod。選擇器必須與目標 Deployment、StatefulSet 或其他工作負載的 Pod 標籤相符。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: database-pdb
namespace: production
spec:
minAvailable: 2
selector:
matchLabels:
app: database
tier: backend
matchExpressions:
- key: environment
operator: In
values:
- production
- staging
|
檢查 PDB 狀態
建立 PDB 後,可以使用以下指令檢查其狀態:
1
2
3
4
5
6
7
8
| # 列出所有 PDB
kubectl get pdb -A
# 查看特定 PDB 的詳細資訊
kubectl describe pdb web-app-pdb -n production
# 以 YAML 格式輸出 PDB 狀態
kubectl get pdb web-app-pdb -n production -o yaml
|
PDB 狀態中的重要欄位:
currentHealthy:目前健康的 Pod 數量desiredHealthy:期望健康的 Pod 數量disruptionsAllowed:允許中斷的 Pod 數量expectedPods:預期的 Pod 總數
與叢集維護整合
節點排空(Node Drain)
當執行節點排空時,Kubernetes 會尊重 PDB 的設定:
1
2
3
4
5
6
7
8
| # 排空節點前先設定為不可調度
kubectl cordon node-1
# 執行排空,會遵守 PDB 設定
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data
# 如需強制排空(不建議),可使用 --force
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data --force
|
與 Deployment 搭配使用
完整的 Deployment 與 PDB 設定範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| apiVersion: apps/v1
kind: Deployment
metadata:
name: web-application
namespace: production
spec:
replicas: 4
selector:
matchLabels:
app: web-application
template:
metadata:
labels:
app: web-application
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-application-pdb
namespace: production
spec:
minAvailable: 3
selector:
matchLabels:
app: web-application
|
最佳實踐
1. 為關鍵服務設定 PDB
所有生產環境中的關鍵服務都應該設定 PDB,以確保在叢集維護期間維持服務可用性。
2. 避免過於嚴格的設定
如果 minAvailable 設定過高或 maxUnavailable 設定過低,可能會導致節點無法正常排空。建議至少允許一個 Pod 不可用。
1
2
3
4
5
6
7
| # 不建議:可能導致維護困難
spec:
minAvailable: "100%"
# 建議:允許適度的中斷
spec:
maxUnavailable: 1
|
3. 確保足夠的副本數量
PDB 的保護效果取決於應用程式的副本數量。如果只有一個副本,PDB 無法提供有效的保護。
4. 使用百分比進行彈性設定
對於副本數量可能變動的應用程式,使用百分比可以提供更靈活的保護:
1
2
| spec:
maxUnavailable: "25%"
|
5. 監控 PDB 狀態
定期監控 PDB 的 disruptionsAllowed 欄位,確保叢集維護操作不會被阻塞。
6. 搭配 Pod Anti-Affinity
結合 Pod 反親和性規則,確保 Pod 分散在不同節點上,進一步提高可用性:
1
2
3
4
5
6
7
8
9
10
11
12
| spec:
template:
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: web-application
topologyKey: kubernetes.io/hostname
|
常見問題
Q: PDB 設定後節點無法排空怎麼辦?
A: 檢查 PDB 的 disruptionsAllowed 是否為 0。如果是,可能需要先增加副本數量,或暫時調整 PDB 設定。
Q: minAvailable 與 maxUnavailable 如何選擇?
A: 如果關注的是「至少要有幾個 Pod 可用」,使用 minAvailable;如果關注的是「最多允許幾個 Pod 不可用」,使用 maxUnavailable。
Q: PDB 會影響 Pod 的自動重啟嗎?
A: 不會。PDB 只影響自願性中斷,不影響 Pod 因健康檢查失敗而被重啟的行為。
參考資料