Kubernetes 為應(yīng)用程序設(shè)置干擾預(yù)算(Disruption Budget)

2022-06-14 13:35 更新

為應(yīng)用程序設(shè)置干擾預(yù)算(Disruption Budget)

特性狀態(tài): Kubernetes v1.21 [stable]

本文展示如何限制應(yīng)用程序的并發(fā)干擾數(shù)量,在允許集群管理員管理集群節(jié)點的同時保證高可用。

在開始之前

您的 Kubernetes 服務(wù)器版本必須不低于版本 v1.21. 要獲知版本信息,請輸入 ?kubectl version?。

  • 你是 Kubernetes 集群中某應(yīng)用的所有者,該應(yīng)用有高可用要求。
  • 你應(yīng)了解如何部署無狀態(tài)應(yīng)用 和/或有狀態(tài)應(yīng)用。
  • 你應(yīng)當(dāng)已經(jīng)閱讀過關(guān)于 Pod 干擾 的文檔。
  • 用戶應(yīng)當(dāng)與集群所有者或服務(wù)提供者確認(rèn)其遵從 Pod 干擾預(yù)算(Pod Disruption Budgets)的規(guī)則。

用 PodDisruptionBudget 來保護應(yīng)用

  1. 確定想要使用 PodDisruptionBudget (PDB) 來保護的應(yīng)用。
  2. 考慮應(yīng)用對干擾的反應(yīng)。
  3. 以 YAML 文件形式定義 PDB 。
  4. 通過 YAML 文件創(chuàng)建 PDB 對象。

確定要保護的應(yīng)用

用戶想要保護通過內(nèi)置的 Kubernetes 控制器指定的應(yīng)用,這是最常見的使用場景:

  • Deployment
  • ReplicationController
  • ReplicaSet
  • StatefulSet

在這種情況下,在控制器的 ?.spec.selector? 字段中做記錄,并在 PDB 的 ?.spec.selector? 字段中加入同樣的選擇算符。

從 1.15 版本開始,PDB 支持啟用 scale 子資源 的自定義控制器。

用戶也可以用 PDB 來保護不受上述控制器控制的 Pod,或任意的 Pod 集合。

考慮應(yīng)用對干擾的反應(yīng) 

確定在自發(fā)干擾時,多少實例可以在短時間內(nèi)同時關(guān)閉。

  • 無狀態(tài)的前端:
    • 關(guān)注:不能降低服務(wù)能力 10% 以上。
      • 解決方案:例如,使用 PDB,指定其 minAvailable 值為 90%。
  • 單實例有狀態(tài)應(yīng)用:
    • 關(guān)注:不要在不通知的情況下終止該應(yīng)用。
      • 可能的解決方案 1:不使用 PDB,并忍受偶爾的停機。
      • 可能的解決方案 2:設(shè)置 maxUnavailable=0 的 PDB。 意為(Kubernetes 范疇之外的)集群操作人員需要在終止應(yīng)用前與用戶協(xié)商, 協(xié)商后準(zhǔn)備停機,然后刪除 PDB 表示準(zhǔn)備接受干擾,后續(xù)再重新創(chuàng)建。
  • 多實例有狀態(tài)應(yīng)用,如 Consul、ZooKeeper 或 etcd:
    • 關(guān)注:不要將實例數(shù)量減少至低于仲裁規(guī)模,否則將出現(xiàn)寫入失敗。
      • 可能的解決方案 1:設(shè)置 maxUnavailable 值為 1 (適用于不同規(guī)模的應(yīng)用)。
      • 可能的解決方案 2:設(shè)置 minAvailable 值為仲裁規(guī)模(例如規(guī)模為 5 時設(shè)置為 3)。 (允許同時出現(xiàn)更多的干擾)。
  • 可重新啟動的批處理任務(wù):
    • 關(guān)注:自發(fā)干擾的情況下,需要確保任務(wù)完成。
      • 可能的解決方案:不創(chuàng)建 PDB。 任務(wù)控制器會創(chuàng)建一個替換 Pod。

指定百分比時的舍入邏輯

?minAvailable ?或 ?maxUnavailable ?的值可以表示為整數(shù)或百分比。

  • 指定整數(shù)值時,它表示 Pod 個數(shù)。例如,如果將 minAvailable 設(shè)置為 10, 那么即使在干擾期間,也必須始終有 10 個Pod可用。
  • 通過將值設(shè)置為百分比的字符串表示形式(例如 “50%”)來指定百分比時,它表示占總 Pod 數(shù)的百分比。 例如,如果將 "minUnavailable" 設(shè)置為 “50%”,則干擾期間只允許 50% 的 Pod 不可用。

如果將值指定為百分比,則可能無法映射到確切數(shù)量的 Pod。例如,如果你有 7 個 Pod, 并且你將 ?minAvailable ?設(shè)置為 ?"50%"?,具體是 3 個 Pod 或 4 個 Pod 必須可用 并非顯而易見。 Kubernetes 采用向上取整到最接近的整數(shù)的辦法,因此在這種情況下,必須有 4 個 Pod。 你可以檢查控制此行為的 代碼。

指定 PodDisruptionBudget 

一個 ?PodDisruptionBudget ?有 3 個字段:

  • 標(biāo)簽選擇算符 ?.spec.selector? 用于指定其所作用的 Pod 集合,該字段為必需字段。
  • ?.spec.minAvailable? 表示驅(qū)逐后仍須保證可用的 Pod 數(shù)量。即使因此影響到 Pod 驅(qū)逐 (即該條件在和 Pod 驅(qū)逐發(fā)生沖突時優(yōu)先保證)。 ?minAvailable ?值可以是絕對值,也可以是百分比。
  • ?.spec.maxUnavailable? (Kubernetes 1.7 及更高的版本中可用)表示驅(qū)逐后允許不可用的 Pod 的最大數(shù)量。其值可以是絕對值或是百分比。
說明:
?policy/v1beta1? 和 ?policy/v1? API 中 PodDisruptionBudget 的空選擇算符的行為 略有不同。在 ?policy/v1beta1? 中,空的選擇算符不會匹配任何 Pods,而 ?policy/v1? 中,空的選擇算符會匹配名字空間中所有 Pods。

用戶在同一個 ?PodDisruptionBudget ?中只能夠指定 ?maxUnavailable ?和 ?minAvailable ?中的一個。 ?maxUnavailable ?只能夠用于控制存在相應(yīng)控制器的 Pod 的驅(qū)逐(即不受控制器控制的 Pod 不在 ?maxUnavailable ?控制范圍內(nèi))。在下面的示例中, “所需副本” 指的是相應(yīng)控制器的 ?scale?,控制器對 ?PodDisruptionBudget ?所選擇的 Pod 進行管理。

示例 1:設(shè)置 ?minAvailable ?值為 5 的情況下,驅(qū)逐時需保證 PodDisruptionBudget 的 ?selector ?選中的 Pod 中 5 個或 5 個以上處于健康狀態(tài)。

示例 2:設(shè)置 ?minAvailable ?值為 30% 的情況下,驅(qū)逐時需保證 Pod 所需副本的至少 30% 處于健康狀態(tài)。

示例 3:設(shè)置 ?maxUnavailable ?值為 5 的情況下,驅(qū)逐時需保證所需副本中最多 5 個處于不可用狀態(tài)。

示例 4:設(shè)置 ?maxUnavailable ?值為 30% 的情況下,驅(qū)逐時需保證所需副本中最多 30% 處于不可用狀態(tài)。

在典型用法中,干擾預(yù)算會被用于一個控制器管理的一組 Pod 中 —— 例如:一個 ReplicaSet 或 StatefulSet 中的 Pod。

說明: 干擾預(yù)算并不能真正保證指定數(shù)量/百分比的 Pod 一直處于運行狀態(tài)。例如: 當(dāng) Pod 集合的 規(guī)模處于預(yù)算指定的最小值時,承載集合中某個 Pod 的節(jié)點發(fā)生了故障,這樣就導(dǎo)致集合中可用 Pod 的 數(shù)量低于預(yù)算指定值。預(yù)算只能夠針對自發(fā)的驅(qū)逐提供保護,而不能針對所有 Pod 不可用的誘因。

設(shè)置 ?maxUnavailable ?值為 0%(或 0)或設(shè)置 ?minAvailable ?值為 100%(或等于副本數(shù)) 可能會阻塞節(jié)點,導(dǎo)致資源耗盡。按照 ?PodDisruptionBudget ?的語義,這是允許的。

用戶可以在下面看到 pod 干擾預(yù)算定義的示例,它們與帶有 ?app: zookeeper? 標(biāo)簽的 pod 相匹配:

使用 minAvailable 的PDB 示例:

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

使用 maxUnavailable 的 PDB 示例:

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

例如,如果上述 ?zk-pdb? 選擇的是一個規(guī)格為 3 的 StatefulSet 對應(yīng)的 Pod, 那么上面兩種規(guī)范的含義完全相同。 推薦使用 ?maxUnavailable ?,因為它自動響應(yīng)控制器副本數(shù)量的變化。

創(chuàng)建 PDB 對象 

你可以使用 kubectl 創(chuàng)建或更新 PDB 對象。

kubectl apply -f mypdb.yaml

PDB 對象無法更新,必須刪除后重新創(chuàng)建。

檢查 PDB 的狀態(tài)

使用 kubectl 來確認(rèn) PDB 被創(chuàng)建。

假設(shè)用戶的名字空間下沒有匹配 ?app: zookeeper? 的 Pod,用戶會看到類似下面的信息:

kubectl get poddisruptionbudgets
NAME     MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
zk-pdb   2               N/A               0                     7s

假設(shè)有匹配的 Pod (比如說 3 個), 那么用戶會看到類似下面的信息:

kubectl get poddisruptionbudgets
NAME     MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
zk-pdb   2               N/A               1                     7s

?ALLOWED-DISRUPTIONS? 值非 0 意味著干擾控制器已經(jīng)感知到相應(yīng)的 Pod,對匹配的 Pod 進行統(tǒng)計, 并更新了 PDB 的狀態(tài)。

用戶可以通過以下命令獲取更多 PDB 狀態(tài)相關(guān)信息:

kubectl get poddisruptionbudgets zk-pdb -o yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  anntation: {}
  creationTimestamp: "2020-03-04T04:22:56Z"
  generation: 1
  name: zk-pdb
…
status:
  currentHealthy: 3
  desiredHealthy: 2
  disruptionsAllowed: 1
  expectedPods: 3
  observedGeneration: 1

任意控制器和選擇算符 

如果你只使用與內(nèi)置的應(yīng)用控制器(Deployment、ReplicationController、ReplicaSet 和 StatefulSet) 對應(yīng)的 PDB,也就是 PDB 的選擇算符與 控制器的選擇算符相匹配,那么可以跳過這一節(jié)。

你可以使用這樣的 PDB:它對應(yīng)的 Pod 可能由其他類型的控制器控制,可能由 "operator" 控制, 也可能為“裸的(不受控制器控制)” Pod,但該類 PDB 存在以下限制:

  • 只能夠使用 ?.spec.minAvailable? ,而不能夠使用 ?.spec.maxUnavailable?。
  • 只能夠使用整數(shù)作為 ?.spec.minAvailable? 的值,而不能使用百分比。

你可以令選擇算符選擇一個內(nèi)置控制器所控制 Pod 的子集或父集。 然而,當(dāng)名字空間下存在多個 PDB 時,用戶必須小心,保證 PDB 的選擇算符之間不重疊。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號