アプリケーションにDisruption Budget指定する

FEATURE STATE: Kubernetes v1.21 [stable]

このページでは、アプリケーションで同時に発生するDisruptionの数を制限する方法を説明します。 これによりクラスター管理者は、クラスターのノードを管理しながら、高い可用性を実現できます。

始める前に

作業するKubernetesサーバーは次のバージョン以降のものである必要があります: v1.21.

バージョンを確認するには次のコマンドを実行してください: kubectl version.

PodDisruptionBudgetを使用してアプリケーションを保護する

  1. PodDisruptionBudget(PDB)で保護したいアプリケーションを特定します。
  2. アプリケーションがDisruptionにどのように反応するかを検討します。
  3. PDB定義をYAMLファイルとして作成します。
  4. YAMLファイルからPDBオブジェクトを作成します。

保護するアプリケーションを特定する

ビルトインのKubernetesコントローラーのいずれかによって指定されたアプリケーションを保護する場合の最も一般的なユースケースは次の通りです:

  • Deployment
  • ReplicationController
  • ReplicaSet
  • StatefulSet

このケースでは、コントーラーの.spec.selectorをメモし、同じセレクターをPDBの.spec.selectorに設定します。

バージョン1.15以降では、PDBはscale subresourceが有効になっているカスタムコントローラーをサポートします。

上記のコントローラーのいずれかによって制御されていないPodや、任意のPodグループでPDBを使用することもできますが、任意のワークロードと任意のセレクターで説明されているように、いくつかの制限があります。

アプリケーションがDisruptionにどのように反応するかを検討する

自発的なDisruptionによって短期間に同時に停止できるインスタンス数を決定してください。

  • ステートレスフロントエンド:
    • 留意事項: サービス提供能力を10%以上低下させない。
      • 解決策: 例えば、minAvailable 90%のPDBを使用する。
  • 単一インスタンスのステートフルアプリケーション:
    • 留意事項: 相談なしにこのアプリケーションを終了しない。
      • 可能な解決策1: PDBを使用せず、偶発的なダウンタイムを許容する。
      • 可能な解決策2: maxUnavailable=0のPDBを設定する。 クラスター管理者が終了する前に、あなたに相談する必要があることを(Kubernetesの外部で)理解する。 クラスター管理者から連絡があれば、ダウンタイムに備え、Disruptionの準備ができたことを示すためにPDBを削除する。 その後、PDBを再作成する。
  • Consul、ZooKeeper、etcdのような複数インスタンスのステートフルアプリケーション:
    • 留意事項: インスタンス数をクォーラム以下に減らない、さもなければ書き込みが失敗する。
      • 可能な解決策1: maxUnavailableを1に設定する(アプリケーションの規模が変化する場合に機能する)。
      • 可能な解決策2: minAvailableをクォーラムサイズ(スケールが5の場合は3)に設定する(一度により多くのDisruptionを許可する)。
  • 再起動可能なバッチジョブ:
    • 留意事項: 自発的なDisruptionの場合にジョブが完了する必要がある。
      • 可能な解決策: PDBを作成しない。 Jobコントローラーが代替Podを作成する。

パーセンテージを指定する場合の丸めロジック

minAvailableまたはmaxUnavailableの値は整数またはパーセンテージで表すことができます。

  • 整数を指定すると、Podの数を表します。 インスタンスのminAvailableを10に設定すると、Disruptionの間も常に10個のPodが利用可能である必要があります。
  • パーセンテージを表現する文字列(例. "50%")によってパーセンテージを指定すると、Podの合計パーセンテージを表します。 例えば、インスタンスのminAvailable"50%"に設定すると、Disruptionの間に少なくとも50%のPodが利用可能である必要があります。

パーセンテージを指定すると、Podの数には正確にマッピングされない場合があります。 例えば、7個のPodがありminAvailable"50%"に設定されている場合、利用可能である必要があるPodの数が3個か4個かはすぐにはわかりません。 Kubernetesは最も近い整数に切り上げるため、このケースでは4個のPodが利用可能である必要があります。 パーセンテージとしてmaxUnavailableの値を指定すると、KubernetesはDisruptionされるPodの数を切り上げます。 その結果、定義されたmaxUnavailableのパーセンテージを超えるDisruptionが発生する可能性があります。 この挙動を制御するコードを確認できます。

PodDisruptionBudgetを定義する

PodDisruptionBudgetには3つのフィールドがあります:

  • .spec.selectorラベルセレクターは、適用されるPodのセットを指定します。 このフィールドは必須です。
  • .spec.minAvailableは、退避されたPodがない場合であっても、退避後もそのセットで利用可能である必要があるPodの数を記述します。 minAvailableは絶対数またはパーセンテージのいずれかを指定できます。
  • .spec.maxUnavailable(Kubernetes 1.7以上で利用可能)は、退避後にそのセットで利用できないことを許容するPodの数を記述します。 絶対数またはパーセンテージのいずれかを指定できます。

単一のPodDisruptionBudgetには、maxUnavailableminAvailableのいずれか1つだけを指定できます。 maxUnavailableは、コントローラーによって管理されているPodについてのみ、退避を制御するために使用できます。 以下の例において"理想的なレプリカ数"は、PodDisruptionBudgetによって選択されるPodを管理しているコントローラーのscaleです。

例1: minAvailableが5に設定されている場合、PodDisruptionBudgetのselectorによって選択されたPodの中で、少なくとも5つ以上の健全なPodが残る限り、退避が許可されます。

例2: minAvailableが30%に設定されている場合、少なくとも理想的なレプリカ数の30%が健全である限り、退避が許可されます。

例3: maxUnavailableが5に設定されている場合、理想的なレプリカの総数のうち、不健全なレプリカが最大5つである限り、退避が許可されます。

例4: maxUnavailableが30%に設定されている場合、不健全なレプリカ数が、最も近い整数に切り上げられた理想的なレプリカの総数の30%を超えない限り、退避が許可されます。 理想的なレプリカの総数が1の場合、その単一のレプリカも退避可能となり、実質的な利用不可率が100%になります。

通常の用途では、単一のバジェットはコントローラーによって管理されるPodのコレクション(例えば、単一のReplicaSetまたはStatefulSet内のPod)に使用されます。

maxUnavailableを0%または0に設定するか、minAvailableを100%またはレプリカ数に設定すると、自発的な退避を一切要求しません。 この設定をReplicaSetのようなワークロードオブジェクトに適用すると、それらのPodが実行されているノードを正常にドレインできなくなります。 退避できないPodが実行されているノードをドレインしようしても、ドレインは完了しません。 これはPodDisruptionBudgetの仕様上、正しい挙動です。

以下にPodDisruptionBudgetの例を示します。 これらの例は、ラベルapp: zookeeperを持つPodに一致します。

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

例えば、上記のzk-pdbオブジェクトがサイズ3のStatefulSetのPodを選択する場合、どちらの仕様もまったく同じ意味を持ちます。 maxUnavailableの使用が推奨されており、これは対応するコントローラーのレプリカ数の変更に自動的に対応するためです。

PDBオブジェクトを作成する

kubectlを使用してPDBオブジェクトを作成または更新できます。

kubectl apply -f mypdb.yaml

PDBのステータスを確認する

kubectlを使用してPDBが作成されたことを確認します。

Namespace内にapp: zookeeperに一致するPodがないと仮定すると、次のようになります:

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

一致するPod(例えば3つ)があれば、次のように表示されます:

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

ALLOWED DISRUPTIONSの値がゼロ以外である場合、DisruptionコントローラーはPodを確認し、一致するPodをカウントし、PDBのステータスを更新しています。

PDBのステータスについての詳細情報を取得するには、次のコマンドを使用します:

kubectl get poddisruptionbudgets zk-pdb -o yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  annotations:

  creationTimestamp: "2020-03-04T04:22:56Z"
  generation: 1
  name: zk-pdb

status:
  currentHealthy: 3
  desiredHealthy: 2
  disruptionsAllowed: 1
  expectedPods: 3
  observedGeneration: 1

Podの健全性

現在の実装では、type="Ready"かつstatus="True".status.conditions項目を持つPodが健全なPodと見なされます。 これらのPodは、PDBステータスの.status.currentHealthyフィールドで追跡されます。

不健全なPodの退避ポリシー

FEATURE STATE: Kubernetes v1.31 [stable] (enabled by default: true)

アプリケーションを保護するPodDisruptionBudgetは、健全なPodの退避を許可しないことで、.status.currentHealthyのPod数が.status.desiredHealthyで指定された数を下回らないようにします。 .spec.unhealthyPodEvictionPolicyを使用すると、不健全なPodを退避する基準を定義できます。 ポリシーが指定されていない場合のデフォルトの動作は、IfHealthyBudgetポリシーに準じます。

ポリシー:

IfHealthyBudget
Podが実行中(.status.phase="Running")であるがまだ健全ではない場合、保護されたアプリケーションが中断されていない(.status.currentHealthyが少なくとも.status.desiredHealthyと等しい)場合にのみ退避できます。

このポリシーによって、すでに中断されているアプリケーションで実行中のPodが健全になる可能性が最も高くなります。 これは、PDBによって保護されている異常なアプリケーションによってノードのドレインがブロックされる悪影響をもたらします。 具体的には、(バグや設定ミスによって)PodがCrashLoopBackOff状態にあるアプリケーション、またはReady条件を正しく報告できないPodがあるアプリケーションが該当します。

AlwaysAllow
Podが実行中(.status.phase="Running")であるがまだ健全ではないPodは、中断されているとみなされ、PDBの基準が満たされているかどうかに関係なく退避されます。

これは、中断されたアプリケーションで実行中のPodが健全にならない可能性があることを意味します。 このポリシーによって、クラスター管理者はPDBによって保護されている異常なアプリケーションを簡単に退避できます。 具体的には、(バグや設定ミスによって)PodがCrashLoopBackOff状態にあるアプリケーション、またはReady条件を正しく報告できないPodがあるアプリケーションが該当します。

任意のワークロードと任意のセレクター

ビルトインのワークロードリソース(Deployment、ReplicaSet、StatefulSet、ReplicationController)、またはscaleサブリソースを実装したカスタムリソースでのみPDBを使用し、PDBセレクターがPodを所有するリソースのセレクターと完全に一致する場合は、このセクションをスキップできます。

他のリソースや"オペレーター"に制御されるPodまたはベアPodにおいてもPDBを使用することができますが、次の制限があります:

  • .spec.minAvailableのみ使用でき、.spec.maxUnavailableは使用できません
  • .spec.minAvailableは整数値のみ使用でき、パーセンテージは使用できません

Kubernetesはサポートされている所有リソースがない場合にPodの合計数を導き出せないため、他の可用性構成を使用することはできません。

セレクターを使用して、ワークロードリソースに属するPodのサブセットまたはスーパーセットを選択できます。 退避APIは、複数のPDBにカバーされるPodの退避を許可しないため、ほとんどのユーザーはセレクターの重複を避けるべきです。 重複するPDBの合理的な使用方法の1つは、Podが1つのPDBから別のPDBに移行している場合です。