PodDisruptionBudgetを100%にすると、ノード排出が終わらない

|著者: QUASA編集チーム|2 分で読めます
PodDisruptionBudgetを100%にすると、ノード排出が終わらない

KubernetesのPDB設定ガイドによると、PodDisruptionBudget(PDB)のminAvailableを100%にすると、Readyな対象Podの計画的な退避は許可されない。そのPodが載るノードを排出しようとしても、退避を完了できない。排出を進めながら必要な可用性を守るには、まず同時に失ってよいPod数を決め、その値をmaxUnavailableかminAvailableのどちらか一方で表す。

PDBが制御するのは、kubectl drainなどがEviction APIを通じて行う退避だ。KubernetesのPod中断に関する説明では、ノード障害はPDBで防げず、Podの直接削除やワークロードの更新もPDBによって一律には止まらないとされている。更新中や障害で利用不能になったPodは予算の計算に影響するため、PDBの値を決める際は通常時のレプリカ数だけでは足りない。

残すPod数か、失ってよいPod数か

minAvailableは退避後にも利用可能であるべきPod数、maxUnavailableは退避後に利用不能でもよいPod数を指定する。同じPDBに両方は設定できない。たとえば条件付きで、ReadyなPodが3つあり、そのうち常に2つ必要ならminAvailable: 2を選べる。同時に1つまで停止できるという運用上の条件ならmaxUnavailable: 1でも、最初に退避できる数は同じく1つになる。

違いが現れるのはレプリカ数を変えたときだ。minAvailable: 2を固定したまま2レプリカに縮小すると退避の余地はなく、5レプリカに拡大すると最大3つまで利用不能にできる計算になる。maxUnavailable: 1なら、規模が変わっても許す停止数は1つのままだ。必要な稼働数が固定されているサービスには整数のminAvailable、停止許容量を固定したいサービスには整数のmaxUnavailableが判断の出発点になる。

割合を使う場合は、両方とも計算結果を整数に切り上げる。ただし切り上げる対象は異なり、minAvailableでは残す数、maxUnavailableでは失ってよい数を切り上げる。小さな構成ほどこの差が効く。たとえば3レプリカでminAvailable: 67%なら3×0.67=2.01を切り上げて3つを残す必要がある。一方、maxUnavailable: 25%なら3×0.25=0.75を切り上げ、1つの停止を許す。

単一・3レプリカ・可変構成の判断表

次の例は、対象PodがすべてReadyで、進行中の退避がない場合の初期値だ。ここでいう退避可能数は、ノード上の対象PodをEviction APIで退避できる余地を表す。すでに異常なPodがある場合や退避処理が進んでいる場合は、同じ設定でも実際の許可数が変わる。

  • 単一レプリカでminAvailable: 100%または1なら、必要数は1、退避可能数は0。ReadyなPodを残す条件と、そのPodが載るノードの排出は両立しない。
  • 単一レプリカでmaxUnavailable: 1なら、退避可能数は1。ただし退避中に利用可能なレプリカが0になる。単一Podのまま継続提供したいサービスにとって、PDBの値だけでは解決にならない。
  • 3レプリカでminAvailable: 100%または3なら、必要数は3、退避可能数は0。maxUnavailable: 0でも、ReadyなPodの退避は許されない。
  • 3レプリカでminAvailable: 2またはmaxUnavailable: 1なら、最初の退避可能数は1。退避後に残るReadyなPodが2つなら、代替PodがReadyになるまで次の退避は待つ。
  • 3レプリカでminAvailable: 67%なら、必要数は切り上げで3、退避可能数は0。割合だけを見ると余裕がありそうでも、整数に直すと余裕はない。
  • 可変構成でmaxUnavailable: 25%なら、3レプリカでは切り上げで1つ、5レプリカでは切り上げで2つまで利用不能にできる。許容停止数はレプリカ数に応じて段階的に変わる。

単一レプリカで停止を避けたいなら、そのアプリケーションを複数レプリカで動かせるかが先に決まる。複製できず、計画的な停止を受け入れる構成なら、排出する時間帯と復旧条件を運用側で決める必要がある。PDBで単一Podを常に残す設定を続ける限り、そのPodがあるノードの計画的な排出は進まない。

selectorと設定値を同じワークロードに合わせる

3レプリカのDeploymentが1つの停止に耐えられるなら、PDBにはapiVersion: policy/v1、kind: PodDisruptionBudget、spec.maxUnavailable: 1を指定し、spec.selector.matchLabelsを対象Podのラベルに合わせる。固定して残す数が2つなら、maxUnavailableの代わりにspec.minAvailable: 2を指定する。設定ファイルを適用しただけで保護が成立するわけではなく、selectorが意図したPodを選んでいるかを確かめる必要がある。

selectorが広すぎると別のワークロードのPodまで予算に含め、狭すぎると守りたいPodを選べない。複数のPDBが同じPodを選ぶ場合、そのPodのEviction APIによる退避は許可されない。とくにラベルを変更した直後やPDBを移行する際は、古い設定と新しい設定の選択範囲が重なっていないか確認したい。空のselectorも名前空間内の全Podを選ぶため、対象を省略するつもりで指定してはいけない。

maxUnavailableを使えるのは、選ばれたPodが同じ対応コントローラーに管理され、予定レプリカ数を計算できる場合だ。単独Podや異なる管理元のPodをまとめる構成では、整数のminAvailableを使う。この制約を無視して割合を当てはめると、計算上は妥当に見える値でも、PDBが意図したワークロードの規模を基準にできない。

ReadyでないPodは別の退避方針で扱う

PodDisruptionBudgetのAPIリファレンスでは、spec.unhealthyPodEvictionPolicyの既定動作をIfHealthyBudgetとしている。この設定では、RunningだがReadyでないPodを退避できるのは、現在のReadyなPod数が必要数以上のときだけだ。アプリケーションがすでに必要数を下回っている場合、そのPodが回復する余地を残すため、ノード排出が待たされる。

AlwaysAllowを指定すると、RunningだがReadyでないPodは予算の充足状況にかかわらず退避できる。起動と失敗を繰り返すPodや、Readyを報告できないPodが排出を妨げる場面で役立つ。一方、退避したPodがその場で回復する機会は失われる。ReadyなPodには引き続きPDBの制限が適用されるので、minAvailable: 100%によってReadyなPodの退避が止まる問題は、AlwaysAllowだけでは解消しない。

どちらを選ぶかは、不調なPodを残して回復を待つ価値と、ノード保守を進める必要性で決める。異常Podを退避できても、代替Podを配置する空き容量がなければ、必要なReady数は回復しない。退避方針とレプリカ数は別々に判断し、アプリケーションが実際に必要とする稼働数を基準にする。

drain前に許可数と対象Podを照合する

設定から求めた数は、すべてのPodがReadyという前提での計算結果だ。排出直前にはPDBのstatus.currentHealthy、status.desiredHealthy、status.disruptionsAllowedを確認する。順に現在ReadyなPod数、維持すべきReady数、その時点で許される退避数を表す。設定変更直後のstatusは古い状態を示すことがあるため、status.observedGenerationがmetadata.generationに追いついていることも確かめる。

  1. kubectl -n NAMESPACE get pdbで対象PDBとALLOWED DISRUPTIONSを見る。0なら、まず設定が全Podを残す値なのか、ReadyなPodが不足しているのかを分けて考える。
  2. kubectl -n NAMESPACE get pdb NAME -o yamlでselectorと設定値を読み、currentHealthy、desiredHealthy、disruptionsAllowedを照合する。たとえば必要数が2で現在ReadyなPodも2なら、正常なPodをさらに退避する余地はない。
  3. kubectl get pods -A --field-selector spec.nodeName=NODE -o wideで排出対象ノードのPodを確認する。どのPodがどのPDBに選ばれるかを調べ、同じPodに複数のPDBが重なっていないかを見る。

許可数が1でも、対象ノードに同じアプリケーションのPodが複数あれば、一度にすべては退避できない。代替PodがReadyになり、次の退避が許されるまでdrainは待つ。許可数が0で全PodがReadyなら必要数の指定を、ReadyでないPodがあるならその原因と退避方針を見直す。代替Podが起動できない場合は、配置先のノード容量やスケジューリング条件まで確認してから保守を進める。

関連記事:

共有:

ニュースレターを購読

Web3、AI、暗号資産の最新ニュースを受信箱にお届けします。

0