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é)點(diǎn)的同時(shí)保證高可用。

在開(kāi)始之前

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

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

用 PodDisruptionBudget 來(lái)保護(hù)應(yīng)用

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

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

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

  • Deployment
  • ReplicationController
  • ReplicaSet
  • StatefulSet

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

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

用戶也可以用 PDB 來(lái)保護(hù)不受上述控制器控制的 Pod,或任意的 Pod 集合。

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

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

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

指定百分比時(shí)的舍入邏輯

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

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

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

指定 PodDisruptionBudget 

一個(gè) ?PodDisruptionBudget ?有 3 個(gè)字段:

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

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

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

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

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

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

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

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

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

用戶可以在下面看到 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? 選擇的是一個(gè)規(guī)格為 3 的 StatefulSet 對(duì)應(yīng)的 Pod, 那么上面兩種規(guī)范的含義完全相同。 推薦使用 ?maxUnavailable ?,因?yàn)樗詣?dòng)響應(yīng)控制器副本數(shù)量的變化。

創(chuàng)建 PDB 對(duì)象 

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

kubectl apply -f mypdb.yaml

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

檢查 PDB 的狀態(tài)

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

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

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

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

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,對(duì)匹配的 Pod 進(jìn)行統(tǒng)計(jì), 并更新了 PDB 的狀態(tài)。

用戶可以通過(guò)以下命令獲取更多 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) 對(duì)應(yīng)的 PDB,也就是 PDB 的選擇算符與 控制器的選擇算符相匹配,那么可以跳過(guò)這一節(jié)。

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

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

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


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)