こんにちは!クラウドインフラ・SREの世界へようこそ。
日々のインフラ運用、本当にお疲れ様です。
「夜中のノードアップグレード中に、なぜかサービスが数秒間断絶した……」
「Kubernetesのオートスケーリングやメンテナンスのたびになぜかピクッとエラーが出る……」
そんな冷や汗をかいた経験はありませんか?
Kubernetesを触り始めると、Podのデプロイやスケーリングには夢中になりますが、「インフラのメンテナンスや障害時に、どうやってサービスを無停止で守るか」という領域に踏み込んだ途端、思わぬ落とし穴にハマりがちです。
今回は、そんなインフラエンジニアの夜間呼び出しを劇的に減らしてくれる、Kubernetesの隠れた名脇役「PodDisruptionBudget(PDB)」について、現場の生きた知見を交えながら優しく、そして深く解説していきます。これをマスターすれば、あなたの管理するクラスタの信頼性は一段と跳ね上がりますよ。
—
1. そもそも PodDisruptionBudget (PDB) ってなに?
Kubernetesを使っていると、次のようなイベントが日常茶飯事に発生します。
- クラウド事業者によるマネージドKubernetes(EKSやGKEなど)のノードOSパッチ適用・ローリングアップデート
- SREチームによるクラスタノードの世代交代(インスタンスタイプの変更など)
- `kubectl drain` コマンドによる手動でのノード退避
これらはすべて「意図的な(Disruptionな)」Podの駆逐です。
デフォルトのままだと、Kubernetesは「あ、このノード消すね」と言って、その上で動いていたアプリのPodを一切の慈悲なく同時に終了させます。もしそのノードに、あなたのWebサービスの最後の砦となっていたPodが全機乗っていたら……? はい、盛大にダウンタイムの完成です。
そこで登場するのが PDB です。
PDBは、「同時に壊していい(エビクションしていい)Podの数や割合」に制限をかける安全装置(リミッター)です。「最低でも〇個は動かしておいてね!」とKubernetesに誓約書を突きつけるイメージですね。
—
2. インストールや特別な準備は不要! 今日から使える標準機能
PDBを使うために、何か特殊なコントローラーを追加インストールする必要はありません。Kubernetesのコア機能(API)として標準備蓄されています。
まずは、最もシンプルな「Hello World」的なPDBの定義を見てみましょう。
動作確認の前提
- `app: my-web-app` というラベルがついたWebアプリケーションのDeployment(レプリカ数:3)が動いているとします。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-web-app-pdb
spec:
# 常に最低2つのPodが稼働し続けることを保証する
minAvailable: 2
selector:
matchLabels:
app: my-web-app
たったこれだけです。このマニフェストを `kubectl apply -f` するだけで、Kubernetesはこのアプリケーションに対して「ノードメンテナンス時に同時に落としてよいのは最大1つまで(3 – 2 = 1)」と認識します。
—
3. `minAvailable` と `maxUnavailable` の正しい使い分け
PDBの設定で初心者が一番悩むのが、`minAvailable`(最低限必要な数/割合)と `maxUnavailable`(最大壊していい数/割合)のどちらを使うべきかという点です。
先輩エンジニアとしての結論をお伝えします。
パターンA: `minAvailable` を使うべきケース
- 「レプリカ数が固定、またはビジネス上絶対に死守したい下限値が決まっている場合」
- 例: 「バッチ処理ではなくWebフロントエンドなので、ユーザー体験のために絶対に2インスタンスは生きていてほしい」
- 指定方法: 数値(`2`)またはパーセンテージ(`70%`)
パターンB: `maxUnavailable` を使うべきケース
- 「レプリカ数がオートスケーリング(HPAなど)で変動する場合」
- 例: 「今レプリカ数が3個かもしれないし、負荷が高くて10個に増えているかもしれない。とにかく、全体の20%までなら同時に落としても耐えられる設計にしている」
- 指定方法: 数値(`1`)またはパーセンテージ(`20%`)
> 💡 実務の知見:
> オートスケーリング(HPA)を有効にしているワークロードに対して `minAvailable` を固定値(例: `2`)で設定してしまうと、スケールイン・アウトの挙動とコンフリクトを起こしてデプロイやメンテナンスが詰まる原因になります。HPAと組むときは基本的に `maxUnavailable`(例: `1` や `25%`)を使うのが鉄則です。
—
4. 現場で絶対に避けるべき「最悪のデッドロック状態」
さて、ここからが本記事の最も重要なパートです。
PDBを導入したものの、設定ミスによってクラスタ全体のアップグレードが永久にフリーズする(デッドロック)という事故が、現場では後を絶ちません。
⚠️ 陥りがちなアンチパターン
1. レプリカ数「1」のPodに `minAvailable: 1` を設定する
- 何が起きるか: 「常に1つ動かせ」というPDBがある状態で、そのPodがいるノードを `drain` しようとすると、Kubernetesは「新しいノードにPodを逃がしてから古いノードのPodを消そう」とします。しかし、リソース不足などで新しいPodがすぐに起動できない場合、古いPodを消すことがPDB違反になるため、永遠にノードのドレインが終わりません(タイムアウト待ちになり、管理者が絶望します)。
2. レプリカ数「0」の放置
- デプロイの失敗やスケールダウンで、一時的に実稼働Podが「0」になっているにもかかわらず、厳格なPDBが残っていると、ノードメンテナンスが完全にブロックされます。
🛡️ デッドロックを防ぐための鉄則
- シングルポイント(レプリカ数1)のステートレスアプリに、無理やり厳格なPDBを貼らない。(そもそもレプリカ1つなら、ダウンタイムは避けられないため、アプリケーション側の設計を見直すべきです)
- どうしても単一Podを守りたい場合や、メンテナンス時の挙動をコントロールしたい場合は、PDBの挙動を過信せず、ローリングアップデート戦略(`RollingUpdate`)の `maxSurge` や `maxUnavailable` とセットで綿密に検証しましょう。
—
5. 精度高い「PDB動作確認」のステップ
設定したPDBがちゃんと機能するか、安全にテストしてみましょう。手元に検証用クラスタ(KindやMinikubeなど)があれば、以下の手順で今すぐ追体験できます。
1. デプロイとPDBの作成
# 3レプリカのnginxをデプロイ
kubectl create deployment test-nginx –image=nginx:alpine –replicas=3
# PDBを作成 (最低2つは死守)
kubectl create poddisruptionbudget test-nginx-pdb –min-available=2 –selector=app=test-nginx
# ※ 事前に deployment にラベルが付いていることを確認、または –selector=’app=test-nginx’ に合わせるよう deployment 側を調整してください
2. PDBの状態確認
kubectl get pdb
出力結果の `ALLOWED DISRUPTIONS` が `1` になっていることを確認してください。「今、何機までなら壊していいか」がリアルタイムで表示されます。
3. ドレイン(強制退去)の挙動テスト
特定のPodが乗っているノードに対して、意図的にdrainをかけてみます。
# ノード名を調べる
kubectl get pods -o wide
# ドレインを実行(例: min-available の制限を超えるような操作をシミュレート)
kubectl drain
PDBが正しく機能していれば、許容量を超えるPodの削除要求はブロックされ、Kubernetesは安全な範囲でしかノードの解放を行わないことが確認できます。
—
おわりに
KubernetesのPodDisruptionBudgetは、一見地味なリソースに見えますが、「プロダクション環境の信頼性(SLA)」を担保するための最後の砦です。
- オートスケーリングと組み合わせる時は `maxUnavailable`
- 絶対に死守したい固定レプリカには `minAvailable`
- そして、レプリカ数1のアプリに厳格な制限をかけてデッドロックさせない勇気!
これらを意識するだけで、あなたのインフラストラクチャは劇的に堅牢になります。「深夜のメンテナンスで冷や汗をかく日々」とは今日でお別れしましょう。
あなたのKubernetesライフが、より安定して快適なものになりますように。それではまた次の現場でお会いしましょう!