iT邦幫忙

2024 iThome 鐵人賽

0
Kubernetes

一起來看 Kubernetes 官方文件吧!系列 第 16

Day16 - 一起來看 Kubernetes 官方文件吧!- PodDisruptionBudget

  • 分享至 

  • xImage
  •  

前言

前幾天看了形形色色的干擾類型,今天來實做看看 pdb 並且理解用法吧

今日目標

  • 配置 PodDisruptionBudget (PDB)
  • 確認 PDB 與 drain node 的互動關係

Specifying a Disruption Budget for your Application

https://kubernetes.io/docs/tasks/run-application/configure-pdb/

PodDisruptionBudget (PDB) 是用來確保 pods 同時存在一定數量,以確保 app 可以持續提供服務不停機

Identify an Application to Protect

PDB 可以配置於以下 k8s 內建的 controller:

  • Deployment
  • ReplicationController (在 Deployment 出來前的替代品)
  • ReplicaSet
  • StatefulSet

在配置 pdb 時,確保上述 controller 的 .spec.selector 是與 pdb 的 .spec.selector 一致

Think about how your application reacts to disruptions

在配置 PDB 之前,需要依據 app 的型態考慮情況:

  • Stateless frontends:
    • 希望:服務減少量不要超過 10%
    • 解法:配置 PDB: minAvailable=90%
  • Single-instance Stateful Application
    • 希望:服務要在管理者知道的情況下才能中斷
    • 解法1:容忍暫時的停機 (不配置 pdb)
    • 解法2:設定 PDB: maxUnavailable=0。此配置會使得 cluster admin 在處理 drain node 時被阻攔,並且必須向相關人士確認後刪除 PDB,工作才能繼續
  • Multiple-instance Stateful application such as Consul, ZooKeeper, or etcd
    • 希望:確保服務總數不要少於最低可運作狀態 (e.g. etcd 的 Raft 演算法會限制 cluster size 與最小容忍度)
    • 解法1:PDB 設置為 maxUnavailable=1,也就是最多只有一個 pods 可以被中斷
    • 解法2:PDB 設定 minAvailable 為最低選舉數量 (e.g. 當 scale 為 5 時,配置 3 代表至少有 3 個 member 提供服務) (比起解法1 可以允許更多的停機)

Rounding logic when specifying percentages

minAvailable or maxUnavailable 這兩個參數可以被配置為整數或是百分比

  • 當 minAvailable 被配置為 10 時,代表會有最少 10 個 pods 保持可用
  • 當指定為 50% 時,則會根據 replicas 數量,去找到最接近的整數
    • 如 replicas: 7 時,50% 為 3.5,取整數為 4. (向上取整數)

Specifying a PodDisruptionBudget

根據以上內容,PDB 主要的三個參數為:

  • .spec.selector:指定對應的 controller / pods
  • .spec.minAvailable:確保最少可用的數量。若設定為百分比,則會向上取整
  • .spec.maxUnavailable:最多不可用的數量。若設定為百分比,則會向上取整
    • maxUnavailableminAvailable 只能配置其中一種

配置上的幾種例子:

  1. minAvailable=30%:當 app 有至少 30% 為 health 時,驅逐 pods 的行為是被允許的
  2. maxUnavailable=30%:確保未健康的 pods 不會超過 30% (換句話說,健康的 pods 要至少有 70%)。
    但有個特殊情況:當 repilcas: 1 時,30% 會取得 0.3,而向上取整會是 1,在這樣的情況下 PDB 並不會阻止 pods 的驅逐行為,進而導致無法使用率為 100%

通常一個 PDB 就對應到一個 pods controller,不太會混用(混用管理也蠻困難的)。

另外一個特殊情況是 minAvailable=100%maxUnavailable=0% 時,表示此 pods 永遠無法被驅逐,kubectl drain node 指令也會卡死,這在 PDB 的語法上是合法的

補充:cluster admin 在執行 drain node 的動作時,最好先檢查過所有 PDB 的配置,並且在 kubectl drain 指令加上 —timeout 的參數,以避免指令永遠卡死 (尤其在配置自動化腳本時 e.g. ansible-playbook,可能會直接導致 play 卡住然後又看不到輸出訊息無法 debug)

minAvailable 範例如下:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: zookeeper

maxUnavailable 範例如下:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: zookeeper

當 app=zookeeper 的 controller replicas 配置為 3 時,此兩個配置是等價的。

Check the status of the PDB

可以透過 kubectl get 指令確認 PDB 的狀態:

kubectl get poddisruptionbudgets
# 當 replicas <3
NAME     MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
zk-pdb   2               N/A               0                     7s
# 當 replicas = 3
NAME     MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
zk-pdb   2               N/A               1                     7s

主要就看 ALLOWED DISRUPTIONS 欄位,就可以知道目前還能夠允許幾個 pods 被驅逐了。

測試建立 PDB

快速建立一個 nginx app, 並且配置 PDB 之後,drain node 看看行為

建立一個 replicas 為 7 的 deployment:

# 建立的 deployment 會有 app: pdb-deployment 的 labels
❯ kubectl create deployment --replicas=7 pdb-deployment --image=nginx

根據上述 maxUnavailable 的範例,建立一個 PDB:

# pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: pdb-deployment
spec:
  maxUnavailable: 70%
  selector:
    matchLabels:
      app: pdb-deployment

❯ k apply -f pdb.yaml
❯ k get -f pdb.yaml
NAME             MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
pdb-deployment   N/A             70%               5                     44s

可以發現在 replicas:7 且設定為 max=70% 時,算法為 7*70%=4.9,並向上取整為 5 了

測試看看 min 的配置,改為 80%:

...
spec:
  minAvailable: 80%
...
#
❯ k apply -f pdb.yaml 
❯ k get -f pdb.yaml
NAME             MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
pdb-deployment   80%             N/A               1                     7m22s

7 * 80% = 5.6,向上取整為 6,7-6 = 1 ,因此最多可以 1 個 pods 不健康

接下來我們測試看看,若是直接使用 kubectl delete 刪除所有的 pods 是否會觸發 PDB?

❯ k delete pods -l app=pdb-deployment
pod "pdb-deployment-845f8bdc8f-2xsq7" deleted
pod "pdb-deployment-845f8bdc8f-8xllz" deleted
pod "pdb-deployment-845f8bdc8f-d9wrk" deleted
pod "pdb-deployment-845f8bdc8f-ldwzt" deleted
pod "pdb-deployment-845f8bdc8f-ndsdx" deleted
pod "pdb-deployment-845f8bdc8f-q57ws" deleted
pod "pdb-deployment-845f8bdc8f-wh9ll" deleted

可以看到 PDB 並不會阻擋 user 下的 delete 命令,這在前幾天有討論到,delete 並不是自願干擾的一種,透過 eviction API 的才是自願干擾!

接著讓我們試試看 drain node 的行爲:

# 找到有兩個 pods 以上的 node
❯ k get pods -o wide 
NAME                              READY   STATUS    RESTARTS   AGE    IP           NODE          NOMINATED NODE   READINESS GATES
pdb-deployment-845f8bdc8f-c72jq   1/1     Running   0          2m7s   10.0.0.226   k8s-master1   <none>           <none>
pdb-deployment-845f8bdc8f-gpmjw   1/1     Running   0          2m7s   10.0.1.6     k8s-master2   <none>           <none>
pdb-deployment-845f8bdc8f-j25dx   1/1     Running   0          2m7s   10.0.2.66    k8s-master3   <none>           <none>
pdb-deployment-845f8bdc8f-j9z9s   1/1     Running   0          2m8s   10.0.1.5     k8s-master2   <none>           <none>
pdb-deployment-845f8bdc8f-k4k2b   1/1     Running   0          2m8s   10.0.1.168   k8s-master2   <none>           <none>
pdb-deployment-845f8bdc8f-xjrl4   1/1     Running   0          2m8s   10.0.0.107   k8s-master1   <none>           <none>
pdb-deployment-845f8bdc8f-xzfvc   1/1     Running   0          2m8s   10.0.2.63    k8s-master3   <none>           <none>
# 嘗試 drain k8s-msater3
❯ k drain k8s-master3 --ignore-daemonsets --timeout=60s

執行後會發現有兩個 pods 觸發了 eviction API,但因為最多同時只能一個關閉,因此一個成功一個失敗,接著等到新的 pods 健康後,另一個驅逐才會成功:

Warning: ignoring DaemonSet-managed Pods: kube-system/cilium-envoy-vvq2g, kube-system/cilium-g9mvk, kube-system/kube-proxy-xjk4h
evicting pod default/pdb-deployment-845f8bdc8f-xzfvc
evicting pod default/pdb-deployment-845f8bdc8f-j25dx
error when evicting pods/"pdb-deployment-845f8bdc8f-j25dx" -n "default" (will retry after 5s): Cannot evict pod as it would violate the pod's disruption budget.
pod/pdb-deployment-845f8bdc8f-xzfvc evicted
evicting pod default/pdb-deployment-845f8bdc8f-j25dx
pod/pdb-deployment-845f8bdc8f-j25dx evicted
node/k8s-master3 drained

https://ithelp.ithome.com.tw/upload/images/20241225/20168801LljA33GhLX.png
在 PDB 的 status 欄位,可以看到 currentHealthy 等等資訊:

❯ k get pdb pdb-deployment -o yaml
...
status:
  conditions:
  - lastTransitionTime: "2024-09-11T10:25:55Z"
    message: ""
    observedGeneration: 5
    reason: SufficientPods
    status: "True"
    type: DisruptionAllowed
  currentHealthy: 7
  desiredHealthy: 6
  disruptionsAllowed: 1
  expectedPods: 7
  observedGeneration: 5
...

kubectl describe pdb 顯示的資訊也差不多:

❯ k describe pdb pdb-deployment 
Name:           pdb-deployment
Namespace:      default
Min available:  80%
Selector:       app=pdb-deployment
Status:
    Allowed disruptions:  1
    Current:              7
    Desired:              6
    Total:                7
Events:                   <none>

而 PDB 在認定 pods 是否為健康則是透過 pods 的 type="Ready" 且 status="True" 的欄位來判定。

Arbitrary workloads and arbitrary selectors

當要設定 PDB 於非 k8s 內建的 controller 時,有以下限制:

  • 只能配置 .spec.minAvailable,不能用 .spec.maxUnavailable
  • 只能配置整數,不能配置百分比 (因為沒有 replicas 可以計算)

筆者目前還不太確定這樣的使用情境,不過基本上可以想像透過這樣配置,可以避免受 PDB 管理的 posd 少於一定數量,且若 kubectl drain node 觸發該 PDB 時,將會永遠卡住 (因爲沒有 pods controller 會建立新的副本出來)

結論

透過配置 PDB,可以確保部署在 k8s cluster 內的 APP 持續提供服務,但若是配置不當 (e.g. 在 replicas:1 的 controller 上配置 PDB),可能會導致 kubectl drain node 指令永遠無法正常被執行,Cluster admin 在撰寫一些自動化腳本用來管理 cluster 時,也要多多注意 PDB 的配置唷 ~

參考

https://kubernetes.io/docs/tasks/run-application/configure-pdb/


上一篇
Day15 - 一起來看 Kubernetes 官方文件吧!- Disruptions (干擾)
下一篇
Day17 - 一起來看 Kubernetes 官方文件吧!- Node status
系列文
一起來看 Kubernetes 官方文件吧!19
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言