Kubernetes PodDisruptionBudget 可用性保障

Kubernetes PodDisruptionBudget for High Availability

前言

在 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

注意minAvailablemaxUnavailable 不能同時設定,只能擇一使用。

標籤選擇器

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 因健康檢查失敗而被重啟的行為。

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy