Azure Kubernetes Service(AKS)で計画メンテナンスや更新ウィンドウを設定しているのに、数秒〜数十秒の瞬断が発生して困っていませんか?本記事では、VMSS の UpgradePolicy=Manual が原因で起こるダウンタイムの仕組みと、Automatic への変更や max‑surge 設定によってほぼ無停止でメンテナンスする具体的な手順を解説します。
AKS 更新ウィンドウ中の瞬断問題とは
Azure Kubernetes Service(AKS) では、基盤側のメンテナンスを「更新ウィンドウ(計画メンテナンス)」としてスケジュールできます。本来であれば、この時間帯に AKS クラスターやノードプールのアップグレード・パッチ適用が行われても、アプリケーション側にはほとんど影響が出ないように設計されています。
しかし現場では、「更新ウィンドウ中に Web アプリが数秒〜数十秒だけ 503 を返す」「監視グラフ上で RPS が谷を描く」といった短い瞬断が数回〜十数回発生するという相談が少なくありません。Azure Change Analysis を見ると、ちょうどそのタイミングで VMSS(仮想マシン スケールセット)や OS ディスクのアップグレードが発生していることが確認できます。
このようなケースでは、AKS が管理するノードプールの裏側にある VMSS が Uniform Orchestration / UpgradePolicy=Manual になっており、しかもその VMSS を AKS が管理している、という条件が重なっていることがほとんどです。つまり、プラットフォームの更新と VMSS の更新ロジックがうまく噛み合っておらず、その結果として短いダウンタイムが何度も顔を出してしまう状態です。
VMSS UpgradePolicy=Manual が引き起こすダウンタイムの正体
まず、なぜ UpgradePolicy=Manual だと瞬断が起きるのかを、仕組みから整理します。VMSS には主に「Manual」「Automatic」といったアップグレード モードがあり、AKS のノードプールはこの VMSS の上に構築されています。
AKS 側の更新(コントロールプレーンの更新やノードイメージ更新など)によって VMSS のモデルが新しいバージョンに書き換えられると、VMSS の「定義」と「実体(インスタンス)」の間に不一致が生まれます。UpgradePolicy=Manual の場合、この不一致を解消するためのインスタンス更新は AKS ではなく VMSS 側のロジックで行われます。その結果、以下のような流れでダウンタイムが発生します。
- VMSS モデルは新バージョンに更新される
- インスタンスは旧モデルのままなので「モデル不一致」が発生
- プラットフォーム側が VMSS インスタンスを順番に再起動/再イメージして整合性をとろうとする
- この再起動は AKS の cordon/drain ロジックを通らないため、一時的にポッドが全滅し、Web アプリが瞬断する
一方で、UpgradePolicy=Automatic にしておくと、AKS 側で認識しているノードプールの更新処理と VMSS の更新モードが合致し、AKS がノード単位で cordon → drain → 更新 → uncordon のローリングアップデートを実行できるようになります。その結果、ポッドは別ノードに順次退避しながら更新されるため、ダウンタイムをほぼゼロに近づけることができます。
| 項目 | UpgradePolicy=Manual | UpgradePolicy=Automatic | AKS 観点での違い |
|---|---|---|---|
| インスタンス更新のトリガー | 運用者の手動操作 or プラットフォームの整合性解消 | AKS のアップグレード処理から自動的に実行 | Automatic の方が AKS の想定フローと一致 |
| ノード更新時の手順 | 単純な再起動/再イメージ(cordon・drain 無し)になることが多い | cordon → drain → 更新 → uncordon を 1 ノードずつ実行 | Automatic はワークロードへの影響が小さい |
| ダウンタイム発生リスク | 高い(ポッドが一時的に全滅しやすい) | 低い(ローリングアップデートで分散) | 特にシングルノードや少数ノード構成で差が顕著 |
| 運用の自由度 | 細かく順番を制御できるが難易度高 | AKS 標準ロジックに任せる運用が基本 | ほとんどのケースでは Automatic 推奨 |
対策1: VMSS の UpgradePolicy を Automatic に変更する
もっとも簡単で効果が大きいのが、VMSS の UpgradePolicy を Manual → Automatic に変更する方法です。これにより、更新ウィンドウ中に AKS が VMSS に対してノードの更新を指示したとき、AKS の安全なローリングアップデート ロジックが正しく動作するようになります。
ポイントは、UpgradePolicy を Automatic に変えても、AKS クラスターやノードプールのアップグレードが勝手に走るわけではないという点です。従来と同様に、運用者が az aks upgrade や az aks nodepool upgrade を実行してはじめてバージョンアップが行われます。Automatic はあくまで「VMSS インスタンス更新のモード」であり、「いつ更新するか」を決めるのは引き続き運用側の役割です。
設定変更の大まかな手順は以下の通りです。
- AKS クラスターの Node Resource Group 名を確認する
- Node Resource Group 内にある VMSS 名を特定する
- 対象 VMSS の UpgradePolicy を Automatic に変更する
Azure CLI の例を示します(実際には環境に合わせて値を置き換えてください)。
# Node Resource Group 名を確認
az aks show \
--resource-group <AKS_RG> \
--name <AKS_CLUSTER_NAME> \
--query nodeResourceGroup \
-o tsv
# VMSS 一覧を確認
az vmss list \
--resource-group <NODE_RESOURCE_GROUP> \
--query "[].name" \
-o tsv
# 対象 VMSS の UpgradePolicy を Automatic に変更
az vmss update \
--resource-group <NODE_RESOURCE_GROUP> \
--name <VMSS_NAME> \
--set upgradePolicy.mode=Automatic
これだけで、以降の更新ウィンドウでは AKS がノードを 1 台ずつ cordon/drain しながら更新を進めてくれるようになります。結果として、Web アプリはレプリカを維持したままトラフィックを処理し続けることができ、計画メンテナンス中の瞬断はほぼゼロに抑えられます。
なお、UpgradePolicy を変更しても、既存ノードが即座に再起動されるわけではありません。次回以降のアップグレードやイメージ更新から新しいポリシーが適用されるイメージです。とはいえ、すぐに効果を確認したい場合は、テスト用ノードプールを用意して意図的にノードイメージのアップグレードを走らせ、挙動を検証することをおすすめします。
対策2: Manual 運用を続ける場合は max-surge で余剰ノードを確保
「組織のポリシーやセキュリティ要件上、どうしても UpgradePolicy=Manual を維持したい」というケースもあります。その場合でも、事前に余剰ノード(サージノード)を確保したうえで自分たちでローリングアップデートを制御することで、ダウンタイムリスクを大きく減らすことができます。
AKS のノードプールには max-surge という設定があり、アップグレード時に一時的にどれだけ余剰ノードを増やすかを指定できます。事前に max-surge を設定しておけば、「新ノードを先に追加 → ワークロードを移動 → 旧ノードを削除」という流れでノードが入れ替わるため、常に必要な数のノードが維持されやすくなります。
たとえば、次のようなコマンドで max-surge を 5 に設定できます。
az aks nodepool update \
--resource-group <AKS_RG> \
--cluster-name <AKS_CLUSTER_NAME> \
--name <NODEPOOL_NAME> \
--max-surge 5
Manual 運用を選択する場合の、典型的な更新フローは以下のようになります。
| ステップ | 内容 | ポイント |
|---|---|---|
| 1. 事前準備 | max-surge を設定して余剰ノードを確保できるようにする | サージノード分のコスト増を事前に説明・合意 |
| 2. 更新ウィンドウ開始 | 監視・ログを確認しつつ更新を開始する | 必要ならアプリ側で一時的にトラフィック制御 |
| 3. ノード単位で VMSS インスタンスを更新 | az vmss update-instances 等で、ノードを 1〜2 台ずつ更新 | PodDisruptionBudget を尊重するようにポッド数と順番を調整 |
| 4. 動作確認 | 各バッチごとにアプリの疎通・エラーレートをチェック | 問題があればその時点でロールバックや一時中断 |
| 5. 余剰ノードを削減 | アップグレード完了後、不要になったサージノードを削減 | コスト最適化のために自動化しておくと便利 |
Automatic に比べると運用負荷は高くなりますが、ローリング順序や更新タイミングをより細かく制御できるため、「本番トラフィックの状況を見ながら、少しずつ更新したい」といったニーズには向いています。その場合でも、後述する PodDisruptionBudget やアプリ側の耐障害設計は必須です。
PodDisruptionBudget(PDB) でポッドの同時停止を抑制する
インフラ側の工夫だけではなく、Kubernetes リソースとして PodDisruptionBudget(PDB) を設定しておくことも重要です。PDB は「同時に落ちてもよいポッド数」や「最低限残しておきたいポッド数」を宣言する仕組みであり、ノードの drain やスケール操作時に Kubernetes がそれを考慮して処理を行ってくれます。
よく使われるのは minAvailable と maxUnavailable の 2 つの指定方法です。
- minAvailable: 常にこれだけは残しておきたいポッド数
- maxUnavailable: 同時に落ちてもよいポッド数
たとえば、Replica 数 3 の Deployment で「最低 2 個は常に動いていてほしい」場合、以下のような PDB を定義できます。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: webapp-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: webapp
同様に、「同時に 1 個までなら落ちてもよい」という表現をしたければ、maxUnavailable: 1 を指定します。
| ケース | Replica 数 | 推奨 PDB 設定 | 備考 |
|---|---|---|---|
| 標準的な Web アプリ | 3〜5 | minAvailable: 2 または maxUnavailable: 1 | 1 ノード障害+アップグレードを想定 |
| ミッションクリティカル API | 4 以上 | minAvailable: 75% 相当を維持 | レプリカ数と相談して決定 |
| バッチ系ワークロード | 任意 | PDB 無し or 緩めの設定 | 多少の停止が許容されるなら簡素化 |
PDB を適切に設定しておくことで、ノード再起動や VMSS のアップグレード時でも、Kubernetes が「このまま drain すると PDB を満たせない」と判断した場合に処理を待ってくれます。その結果、インフラ側の更新がアプリケーションに与える影響をさらに低減できます。
アプリケーション側で行うべき耐障害設計
更新ウィンドウ中の瞬断を本気で無くしたいのであれば、インフラ側の設定に加えてアプリケーション側の設計も見直す必要があります。代表的な項目を整理すると、次のようになります。
| 設計ポイント | 概要 | 期待できる効果 |
|---|---|---|
| Replica 数を 2 以上にする | Deployment / StatefulSet のレプリカを 2 以上に設定 | 単一ノード障害時もトラフィックを別ポッドに逃がせる |
| Readiness / Liveness Probe を厳密に定義 | 起動直後のウォームアップ時間や依存サービスの状態を見て Ready を切り替える | 未準備のポッドにトラフィックが流れることを防止 |
| 多 AZ(可用性ゾーン) 構成 | ノードプールを複数アベイラビリティゾーンに分散 | ゾーン障害やゾーン単位のメンテナンスにも強くなる |
| Graceful Shutdown の実装 | SIGTERM 受信時にリクエスト受付を締め切り、処理中リクエストを完了させてから終了 | ノード drain 時のリクエスト途中切断を回避 |
| 外部ストレージ・セッションの扱い | セッションや一時ファイルを外部ストレージ/キャッシュに逃がす | ポッド再スケジュール時の状態喪失を防ぐ |
特に Readiness Probe は、ノードのローリングアップデート時の挙動に大きな影響を与えます。アプリケーションが完全に起動し、依存する DB や外部 API との接続も安定してから Ready を true にするようにしておけば、AKS が新ノードのポッドをトラフィックに乗せる前に十分なウォームアップ時間を確保できます。
また、AZ をまたいだ構成が取れる環境であれば、ノードプールを複数ゾーンに分散させておくことで、ゾーン単位でのメンテナンスや障害が発生しても残りのゾーンでサービスを継続できます。更新ウィンドウを 1 つのゾーンずつ順番に適用する、といった戦略も取りやすくなります。
ステートフル ワークロードに特有のポイント
データベース、メッセージキュー、ストレージゲートウェイなど、ステートフルなワークロードはノード更新の影響を受けやすく、慎重な設計が必要です。AKS では多くの場合、これらは StatefulSet + PersistentVolume で構成されますが、ローリングアップデートの戦略によって挙動が大きく変わります。
- RollingUpdate 戦略で 1 台ずつ入れ替える
リーダー/フォロワー構成の DB などでは、1 台ずつ順番にノードとポッドを更新し、フェイルオーバーを確認しながら進めるのが基本です。 - PodDisruptionBudget で同時停止数を 1 に制限
フォロワーが複数いる場合でも、「同時に 1 台までしか落とさない」という制約を PDB でかけておくと安心です。 - ボリュームのデタッチ/アタッチ時間を考慮
クラウドディスクを使う場合、ノード間のアタッチ/デタッチに数十秒〜数分かかることがあります。更新ウィンドウの時間配分にこのレイテンシを織り込んでおくことが重要です。
Automatic に変更した後でも、ステートフル ワークロードでは「一時的に Pod が別ノードに再スケジュールされる」ことは避けられません。そのため、StatefulSet の RollingUpdate 戦略と PDB を組み合わせたうえで、アプリケーション側のフェイルオーバーや再接続ロジックを十分にテストしておく必要があります。
Windows ノードプール・複数ノードプール構成での注意点
Linux ノードプールと Windows ノードプールが混在している AKS クラスターでは、ノードプールごとにアップグレードのタイミングや挙動が異なります。特に以下の点には注意が必要です。
- Linux と Windows で VMSS が別々に存在し、それぞれ個別にローリングされる
- max-surge や UpgradePolicy はノードプール単位で設定する必要がある
- Windows ノードは再起動やパッチ適用に時間がかかることが多い
そのため、Windows ノードプールで重要なワークロードを動かしている場合、次のような運用が考えられます。
- まず Linux ノードプールで Automatic + max-surge + PDB の組み合わせを検証し、そのパターンを Windows ノードプールに展開する
- Windows 側はより長めの更新ウィンドウを確保し、バッチサイズを小さめにして慎重にローリングする
- 可能なら Web フロントは Linux、バックエンドや特定要件のみ Windows に分離し、トラフィック制御で影響を最小化する
複数ノードプール構成では、「どのノードプールにどのアプリが載っているか」「更新ウィンドウ中にどのプールから順番にアップグレードするか」を明確に設計しておくことで、予期せぬ全体停止を避けることができます。
計画メンテナンス前の実践チェックリスト
ここまでの内容を踏まえ、AKS の計画メンテナンス(更新ウィンドウ)に入る前に確認しておきたいチェック項目を整理します。実運用では、以下のようなチェックリストをドキュメントや Runbook として残しておくと便利です。
| カテゴリ | チェック項目 | 確認の目安 |
|---|---|---|
| VMSS 設定 | UpgradePolicy が Automatic になっているか | 対象ノードプールの VMSS で mode=Automatic を確認 |
| VMSS 設定 | Manual を継続する場合、max-surge が設定されているか | ノード数に対して十分なサージノードを確保できる値か |
| PDB | ミッションクリティカルな Deployment / StatefulSet に PDB があるか | kubectl get pdb -A などで対象が網羅されているか確認 |
| アプリ設計 | Replica 数が 2 以上になっているか | 単一ノード障害時にもサービスを継続できるか |
| アプリ設計 | Readiness / Liveness Probe が適切に設定されているか | 起動直後や依存サービス障害時の挙動をテスト済みか |
| 監視・アラート | エラー率・レスポンスタイム・Pod 再起動数にアラートが設定されているか | 更新ウィンドウ中に異常を即座に検知できるか |
| ロールバック | 万が一のときのロールバック手順が用意されているか | 具体的なコマンドと判断基準が Runbook 化されているか |
これらをあらかじめ整備しておけば、更新ウィンドウ中も落ち着いて作業でき、問題が発生した場合も素早く原因を切り分けられます。
まとめ:AKS 更新ウィンドウを「ほぼ無停止」に近づける
AKS の更新ウィンドウ中に発生する瞬断の多くは、AKS 自体の不具合ではなく、VMSS の UpgradePolicy=Manual と AKS の更新ロジックのミスマッチが原因です。プラットフォーム側が VMSS モデルとインスタンスの整合性を取ろうとしてノードを再起動し、その裏でポッドが一時的に全停止してしまう、という構造を理解すれば、対策の方向性は自ずと見えてきます。
具体的には、次のポイントを押さえることが重要です。
- 可能な限り VMSS の UpgradePolicy を Automatic に変更し、AKS の cordon/drain ロジックに更新を任せる
- どうしても Manual が必要な場合は、max-surge で余剰ノードを確保したうえで、慎重にローリングアップデートを実施する
- PodDisruptionBudget を設定し、ノード更新時に同時に落ちるポッド数を制限する
- アプリケーション側でも Replica 数、Probe、多 AZ、Graceful Shutdown などの耐障害設計を徹底する
- ステートフル ワークロードや Windows ノードプールなど、影響が大きい部分は個別に戦略を立てる
これらを組み合わせることで、計画メンテナンス中のダウンタイムを「まったくゼロ」にすることは難しくても、「ユーザーが気づかないレベル」にまで小さくすることは十分可能です。AKS と VMSS の仕組みを正しく理解し、自社のサービス特性に合わせて運用ルールと設定を整えていけば、更新ウィンドウは「怖いイベント」から「安全に品質を高めるための時間」に変わっていくはずです。

コメント