AKS の VMSS ノードプールが Ready にならない原因と解決策|在庫不足・クォータ・TLS 証明書エラーのトラブルシューティング

AKS でオートスケールを使っていると、「ノードプールの Target は増えているのに Ready が 0 のまま」「Pod が Pending のまま動かない」「しばらくすると Target も 0 に戻ってしまう」という事象に遭遇しがちです。この記事では、VMSS ノードプール(例: D8s v6 / 最小 0 / 最大 3)がまさにこの状態に陥るケースを題材に、原因の切り分け方・ログの見方・リージョン/ゾーン在庫不足の見極め方、さらに TLS 証明書エラーを含む具体的な対処方法までを、実運用を意識して詳しく解説します。

目次

AKS の VMSS ノードプールが「Ready にならない」とはどういう状態か

まず、症状を少し整理しておきます。代表的なパターンは次のようなものです。

  • AKS クラスターには複数のノードプールが存在する(例: 3 つ)。
  • そのうち 1 つの VMSS ノードプール(例: D8s v6、最小 0/最大 3)がオートスケーラーにより Target=2 までスケールアウトしようとする。
  • しかし、kubectl get nodes で見ると、該当プールのノードは一向に Ready にならないか、そもそもノード一覧に出てこない。
  • 対象の Pod は Pending のままスケジュールされない。
  • 数分〜十数分経過すると、オートスケーラーが「ノードを増やせない」と判断し、Target が再び 0 に戻る。

このとき、VM 自体は Azure 上で起動しかけているため、ポータルや VMSS 画面では一見「増えている」ように見えますが、AKS の制御プレーンにノードとして参加できていない状態です。

さらに、別のユーザーがノードから API サーバーに curl した際に、次のようなエラーが出ていると報告する場合があります。

SSL certificate problem: unable to get local issuer certificate

これは TLS 証明書の信頼に関する問題で、kubelet が API サーバーと安全に通信できず、ノードが参加できない状況と密接に関係します。

よくある原因パターンを整理する

このような「Target は増えるが Ready にならない」現象は、最終的には次のいずれかに集約されます。

  • 容量/在庫・SKU・ゾーンの制約
  • クォータ不足(反映遅延含む)
  • 仮想ネットワーク/サブネットの制約
  • ノード側(イメージ・kubelet・containerd 等)の不調
  • Azure ポリシー(Deny)によるブロック
  • TLS/証明書エラー、TLS インスペクション等

まずは、「どの層で詰まっているのか」を切り分けることが重要です。以下の表は、主な原因と症状の対応関係をざっくり俯瞰したものです。

原因カテゴリ典型的な症状よく見るエラー/ログ最初に確認すべき場所
容量/在庫・SKU/ゾーンVMSS インスタンスが “Creating” のまま or すぐ削除Insufficient capacity, VM SKU not available, AllocationFailedアクティビティ ログ、VMSS のインスタンス状態
クォータ不足VM 作成が失敗、オートスケールがすぐロールバックOperation could not be completed as it results in exceeding approved standardDSv6Family Cores quota などアクティビティ ログ、az vm list-usage
VNet/サブネットVM は起動しているがノードとして参加しないサブネット IP 不足エラー、API サーバー疎通エラーサブネットの IP 使用状況、NSG/UDR/FW のルール
ノード側不調ノードは “NotReady” のまま or そもそも登録されないkubelet 起動失敗、containerd 起動失敗ノード内の journalctl、ブート診断
Azure ポリシー特定 SKU やゾーンのみ失敗Policy violation, Request is disallowed by policyポリシーの割り当て状況、コンプライアンス
TLS/証明書API サーバーへ curl で証明書エラーSSL certificate problem: unable to get local issuer certificate企業 FW/プロキシ設定、ノードの CA ストア

次の章では、これらの原因を切り分けるために、どの順番で何を見ていけばよいかを具体的に解説します。

原因を特定するための切り分け手順

アクティビティ ログでスケール失敗の理由を確認する

最初に見るべきは Azure のアクティビティ ログです。VM の作成やスケール操作が Azure 側でどう扱われたかが記録されています。

  • 対象リソースグループは AKS のマネージド RG(例: MC_<リソースグループ>_<クラスター名>_<リージョン>)。
  • 操作名としては Microsoft.Compute/virtualMachines/write や Microsoft.Compute/virtualMachineScaleSets/write、または AKS の Microsoft.ContainerService/managedClusters のスケール操作などを探します。
  • 結果が Failed になっているイベントを重点的に確認します。

CLI から確認する場合は、次のようなコマンドが使えます。

az monitor activity-log list \
  --resource-group MC_&lt;RG&gt;_&lt;CLUSTER&gt;_&lt;REGION&gt; \
  --status Failed --max-events 50 -o table

ここで、Insufficient capacity や VM SKU not available、AllocationFailed があれば、リージョン/ゾーンの在庫不足または SKU 非対応を疑います。逆に、could not be completed as it results in exceeding approved... のようなメッセージであれば、クォータ不足が濃厚です。

VMSS インスタンスの状態を直接確認する

次に、問題のノードプールが紐づく VMSS を確認します。VMSS の「インスタンス」ビューで、各インスタンスの Provisioning state と拡張機能(Extension)の状態をチェックします。

az vmss list-instances -g MC_&lt;RG&gt;_&lt;CLUSTER&gt;_&lt;REGION&gt; -n &lt;POOL_VMSS_NAME&gt; \
  --query "[].{id:instanceId,state:provisioningState}" -o table

az vmss get-instance-view -g MC_&lt;RG&gt;_&lt;CLUSTER&gt;_&lt;REGION&gt; -n &lt;POOL_VMSS_NAME&gt; \
  --instance-id 0 -o jsonc

ProvisioningState が Failed や Creating のまま止まっている場合、VM レベルで何かしらエラーが起きている可能性があります。VM 拡張機能のステータスに Provisioning failed が出ていれば、kubelet のセットアップやネットワーク構成など、AKS のエージェントノードとしての構成に失敗している可能性が高くなります。

クラスターオートスケーラーのログを確認する

AKS の自動スケールは、cluster-autoscaler というコンポーネントが制御しています。このログを見ることで、「なぜ Target を増やしたのか」「なぜ諦めて 0 に戻したのか」が分かります。

kubectl -n kube-system logs deploy/cluster-autoscaler

ここでは次のようなメッセージに注目します。

  • 特定ノードプールをスケールアウトしようとした理由(Pending Pod の数など)。
  • スケールアウトの試行が、SKU 在庫不足やクォータ不足などの理由で拒否された記録。
  • 複数回のリトライの末に断念しているかどうか。

オートスケーラーは Azure 側の失敗理由までは詳細に把握できませんが、「どのノードプールを対象にスケールしようとしたか」「それが継続中か、諦めたのか」が分かるだけでも大きなヒントになります。

ノード内部の kubelet/containerd の状態を確認する

VM 自体は起動しているように見えるのに、AKS クラスターにノードとして参加していない場合、ノード内部で kubelet や containerd が正常に動いていない可能性があります。

シリアルコンソールや SSH で VM に入り、次のようにログを確認します。

sudo journalctl -u kubelet -b --no-pager | tail -n 200
sudo journalctl -u containerd -b --no-pager | tail -n 200

ここで、API サーバーへの接続エラーや証明書エラー、コンテナランタイムの起動失敗などがないかを確認します。特に、x509: certificate signed by unknown authority などのメッセージは、TLS 証明書周りの問題を示唆します。

SKU 在庫とクォータを客観的に確認する

「昔クォータエラーになったが、今は引き上げ済み」というケースでも、実は別のクォータ枠や SKU 家族の上限に引っかかっていることが少なくありません。代表的な確認ポイントは次の通りです。

  • リージョン全体の vCPU クォータ
  • 対象 SKU ファミリ(例: standardDSv6Family)の vCPU クォータ
  • Public IP のクォータ
  • Managed Disk(Premium / Standard)のクォータ

CLI では次のコマンドを使います。

# 指定リージョンの SKU が使えるか、ゾーン対応しているか
az vm list-skus -l &lt;REGION&gt; --size D8s_v6 --zone -o table

# vCPU 等のクォータ状況
az vm list-usage -l &lt;REGION&gt; -o table

ここで「現在の使用量」と「上限値」を比べ、スケールアウトに必要な vCPU 数を確保できるかを確認します。クォータを増やした直後は反映に少し時間がかかる場合もあるため、アクティビティ ログと照らし合わせて時系列で見ると分かりやすくなります。

ネットワーク(VNet/サブネット・NSG・FW)の確認

VM が起動しているのにノードとして参加できない場合、ネットワーク周りも重要なチェックポイントです。

  • サブネットの空き IP が残っているか(IP 枯渇していないか)。
  • NSG や UDR、企業ファイアウォールで、AKS 制御プレーンやコンテナレジストリへの通信がブロックされていないか。
  • Private DNS を利用している場合、AKS API サーバーの FQDN が誤った宛先に解決されていないか。

API サーバーに対して名前解決と TLS を確認するには、次のようなコマンドが有効です。

nslookup &lt;API_FQDN&gt;

openssl s_client -connect &lt;API_FQDN&gt;:443 -servername &lt;API_FQDN&gt;

さらに、curl で実際にアクセスしてみることで、「SSL certificate problem: unable to get local issuer certificate」などの TLS エラーが出ていないかを確認できます。

curl -v https://&lt;API_FQDN&gt;

ここで unknown CA や証明書チェーンのエラーが出る場合、企業の TLS インスペクションやプロキシ設定、あるいはノードイメージの CA ストアに問題がある可能性が高いです。

状況別の具体的な解決策

リージョン/ゾーンの在庫不足・SKU 非対応が原因の場合

アクティビティ ログや VMSS のエラーメッセージで Insufficient capacity や AllocationFailed が確認できた場合は、該当リージョン/ゾーンで D8s v6 が一時的に在庫切れ、またはそのゾーンではサポート外である可能性が高いです。

対処の方向性は次の通りです。

  • 同リージョン内で 別のアベイラビリティゾーン に新しいノードプール(同サイズ or 近い SKU)を作成する。
  • D8s v6 にこだわる必要がなければ、D8s v5 や他の互換 SKU を使ったノードプールを追加する。
  • 重要なワークロードは、別の常設ノードプールにスケジュールするよう、nodeSelector や nodeAffinity、taints/tolerations を設定して逃がしておく。

在庫不足は Azure 側の事情であり、ユーザーが直接解消することはできません。そのため、複数ゾーン・複数 SKU を組み合わせて在庫リスクを分散する設計が重要になります。

クォータ不足が原因の場合

クォータ不足は、単に「一度上限を上げたから大丈夫」というものではなく、別のクォータ枠に引っかかるケースも多い点に注意が必要です。

対応のポイントは次の通りです。

  • 該当 SKU ファミリの vCPU 枠(例: standardDSv6Family Cores)を十分な値まで引き上げる。
  • リージョン全体の vCPU 上限も忘れずに確認する。
  • Public IP や Managed Disk(Premium / Standard)など、VM 作成に付随するクォータも確認する。
  • クォータ申請後、アクティビティ ログでスケール操作が成功するようになったかを確認する。

クォータ申請は Azure ポータルの「クォータ」メニューから行うことができ、数分〜数時間で承認されることが多いですが、即時反映ではない場合もあるため、時刻を意識して検証するとよいでしょう。

VNet/サブネットの IP 枯渇や NSG・UDR が原因の場合

VNet 周りの問題は、VM 自体は成功しているものの、ノードとして参加できないケースでよく見られます。

代表的な対処は次の通りです。

  • サブネットの空き IP が不足している場合は、サブネットのアドレス範囲を拡張するか、別のサブネットを用意して新しいノードプールを作成する。
  • NSG や UDR、企業ファイアウォールのルールを確認し、AKS 制御プレーン(*.azmk8s.io 等)とコンテナレジストリ(mcr.microsoft.com や利用中の ACR)との通信を許可する。
  • 特に、プライベート クラスターの場合は、Private Endpoint と Private DNS の設定が正しいかを再確認する。

ネットワーク要件を整理すると、次のようなチェックリストになります。

項目チェック内容
サブネット IPスケールアウト後に必要なノード数分の IP が空いているか
NSGアウトバウンドで 443/TCP が AKS 制御プレーンとレジストリに到達できるか
UDR0.0.0.0/0 をオンプレ FW 経由にしている場合、AKS への疎通が許可されているか
DNSAPI FQDN が正しい IP(Private Endpoint を使うならその IP)に解決されるか
TLS インスペクションAKS 制御プレーン FQDN が SSL 検査の対象から除外されているか

ノードイメージ/kubelet/containerd の不調が原因の場合

特定のノードだけが Ready にならない、あるいは全く登録されない場合、ノードイメージ側の問題や kubelet/containerd の起動失敗が疑われます。

典型的な対処としては次のようなものがあります。

  • ノードイメージのみアップグレードして OS や証明書を最新化する。
az aks nodepool upgrade \
  --resource-group &lt;RG&gt; \
  --cluster-name &lt;CLUSTER&gt; \
  --name &lt;POOL&gt; \
  --node-image-only
  • それでも解消しないノードは、cordon → drain → 削除 → 再作成という流れでリフレッシュする。
  • 時刻同期(NTP)が大きくずれていると TLS まわりで問題が出るため、時刻も合わせて確認する。

ノードイメージの更新を定期的に行うことで、古い CA 証明書や OS の不具合に起因するトラブルを未然に防ぐことができます。

Azure ポリシー(Deny)が原因の場合

サブスクリプションやリソースグループに Azure Policy を適用している場合、特定 SKU・リージョン・タグ・VM サイズを禁止するポリシーによって、ノードの作成が拒否されることがあります。

この場合、アクティビティ ログやポリシーのコンプライアンス画面に、Request is disallowed by policy のようなメッセージが表示されます。

対処の方向性は次の通りです。

  • 該当クラスターやノードプールが属するリソースグループ/サブスクリプションに割り当てられたポリシーを確認する。
  • テスト目的で、一時的に「監査(Audit)」モードに変更し、deny が発生しないかを検証する。
  • 本番環境として適切なポリシーに調整した上で、AKS で使いたい SKU/ゾーンが許可されるようにルールを更新する。

TLS/証明書エラーが原因の場合(SSL certificate problem)

ノードから API サーバーに curl した際に、次のようなエラーが出るという報告がある場合は、TLS 証明書エラーが原因の可能性が非常に高いです。

SSL certificate problem: unable to get local issuer certificate

このエラーは、「サーバー証明書は存在するが、証明書チェーンを検証するための中間 CA などが信頼されていない」ことを意味します。AKS の場合、主な原因は次のようなものです。

  • 企業ファイアウォールやプロキシによる TLS インスペクション(SSL オフロード)により、API サーバーの証明書が企業独自の CA で再署名されている。
  • ノードイメージの CA ストアが古い/破損しているため、新しい中間 CA を信頼できない。
  • Private DNS の誤設定により、意図しない宛先に接続している(結果として証明書が一致しない)。

対処の基本方針は次の通りです。

  • AKS 制御プレーンの FQDN を、TLS インスペクションの対象から除外する。
  • 企業プロキシを経由せずに、直接 API サーバーに到達できる経路を確保する。
  • ノードイメージを最新化し、CA ストアを更新する(前述の node-image-only アップグレード)。
  • Private DNS ゾーンで、AKS API FQDN が正しい Private Endpoint / パブリック IP に解決されているか確認する。

特に企業ネットワークでは、「セキュリティのために全 HTTPS 通信を検査する」設定が広く使われていますが、AKS の制御プレーン FQDN を含めると、証明書のすり替えが発生し、kubelet からは「信頼できない証明書」と見なされてしまいます。AKS を安定運用する上では、AKS 関連 FQDN を TLS インスペクションから除外するポリシーを設計段階で定義しておくことが重要です。

確認するログとコマンドのまとめ

ここまでで登場したログ・コマンドを一覧にまとめると、次のようになります。実際のトラブルシュート時には、この表を上から順に確認していくと効率的です。

レイヤー目的コマンド/場所
Azure コントロールプレーンスケールアウトの失敗理由を確認するaz monitor activity-log list ...
ポータルのアクティビティ ログ
VMSSVM インスタンスの状態と拡張機能のエラーを確認するaz vmss list-instances ...
az vmss get-instance-view ...
オートスケーラーどのプールをどの理由でスケールしようとしたか確認するkubectl -n kube-system logs deploy/cluster-autoscaler
ノード内部kubelet/containerd の起動状況を確認するjournalctl -u kubelet
journalctl -u containerd
SKU/クォータSKU が利用可能か、クォータが足りているか確認するaz vm list-skus ...
az vm list-usage ...
ネットワーク/TLSAPI サーバーへの疎通と証明書を確認するnslookup <API_FQDN>
openssl s_client ...
curl -v https://<API_FQDN>

設計・運用での再発防止策とベストプラクティス

AKS の VMSS ノードプールが Ready にならない問題は、原因を潰していけば必ず解決できますが、できれば本番環境ではそうした事態を事前に防ぎたいところです。ここでは、設計・運用の観点からのポイントをまとめます。

最小ノード数 0 のプールはリスクを理解して使う

オートスケールのコスト最適化のために、最小ノード数を 0 に設定するケースはよくありますが、在庫不足や起動時間の影響を受けやすいというリスクがあります。

  • 基盤的なワークロード(システム系 Pod や SLA が厳しいサービス)は、常にノードを 1 台以上保持するプールに載せる。
  • バッチ処理やスポット的なワークロード専用に、最小 0 のプールを用意する。
  • クリティカルなサービスを最小 0 のプールにのみ置かないよう、affinity や taint を設計する。

複数ゾーン・複数 SKU で在庫リスクを分散する

在庫不足はユーザー側で制御できないため、ゾーンと SKU を分散することで影響を最小限に抑えることが重要です。

  • 3 ゾーン対応リージョンでは、可能な限り 複数ゾーンにまたがるノードプールを構成する。
  • 1 つの SKU に依存しすぎず、性能や料金が近い別 SKUを併用する。
  • ノードアフィニティを使って、重要な Pod を特定ゾーンや特定 SKU に偏らせすぎない。

ノードイメージの定期更新とヘルスチェック

ノードイメージの更新を放置すると、OS の脆弱性だけでなく、CA 証明書チェーンの陳腐化による TLS エラーなど、地味に厄介な問題を引き起こします。

  • 月次または四半期ごとに node-image-only アップグレードを実施する運用ルールを決める。
  • 更新直後に簡易的なヘルスチェックを行い、問題があればすぐに気付けるようにする。
  • CI/CD や GitOps のパイプラインに、ノードイメージ更新のタスクを組み込むことも検討する。

企業ネットワークの TLS インスペクションと AKS の相性を理解する

企業ネットワークで TLS インスペクションを導入している場合、AKS の制御プレーンには原則として TLS インスペクションをかけないのが安全です。

  • AKS 関連の FQDN を列挙し、それらを TLS インスペクションの 除外リストに登録する。
  • どうしてもインスペクションをかける必要がある場合は、ノードイメージに企業 CA を信頼させるなど、より高度な設計が必要になる。
  • Private Endpoint と Private DNS を併用する場合は、オンプレ/クラウド間のルーティングと合わせて総合的に設計する。

実践シナリオでイメージする:2 つのケーススタディ

ケース 1: D8s v6 の在庫不足で Target が 0 に戻る

ある日、D8s v6(最小 0/最大 3)のノードプールで急に Pod が Pending のままになり、オートスケーラーが Target=2 まで増やすものの、数分後に 0 に戻ってしまう現象に遭遇しました。

  1. アクティビティ ログを確認すると、AllocationFailed と Insufficient capacity のメッセージが記録されている。
  2. az vm list-skus で確認すると、当該リージョンの特定ゾーンでは D8s v6 が利用不可になっていることが分かった。
  3. 同リージョンの別ゾーンでは D8s v6 が利用可能だったため、そのゾーンに新しいノードプールを作成した。
  4. 重要な Pod には preferredDuringSchedulingIgnoredDuringExecution の nodeAffinity を設定し、在庫が安定している別 SKU プールを優先するように変更した。

この結果、Pending の Pod は新しいノードプールにスケジュールされ、Ready ノード数も安定しました。

ケース 2: TLS インスペクションによる SSL certificate problem

別の環境では、ノードから API サーバーに curl を実行すると、次のエラーが必ず発生していました。

SSL certificate problem: unable to get local issuer certificate
  1. 同じコマンドをインターネット直結の検証 VM から実行すると、問題なく接続できる。
  2. 企業ネットワークのルールを確認すると、すべての HTTPS 通信がプロキシ経由+ TLS インスペクションの対象になっていることが判明。
  3. プロキシログや FW の設定を確認すると、AKS の API FQDN に対しても企業 CA で再署名された証明書が返されていることが分かった。
  4. ネットワークチームと調整し、AKS 制御プレーン FQDN を TLS インスペクションの除外対象に追加した。
  5. 除外設定反映後に再度 curl を実行すると、証明書エラーは解消し、kubelet も正常に API サーバーに接続できるようになった。

最終的に、Ready ノード数が期待通りに増え、Pending の Pod も解消しました。このケースでは、AKS 側ではなく企業ネットワークの設計がボトルネックになっていたことが分かります。

まとめ:Target が増えるのに Ready にならないときの考え方

AKS の VMSS ノードプールで、Target が増えるのに Ready が 0 のまま、Pod が Pending のまま動かないという現象は、一見すると「AKS が壊れた」ように見えます。しかし、実際には次のような原因のどれかに必ず行き着きます。

  • リージョン/ゾーンの在庫・SKU 非対応
  • クォータ不足(SKU 家族 vCPU、リージョン vCPU、Public IP、Managed Disk 等)
  • VNet/サブネットの IP 枯渇や NSG・UDR・FW による疎通不可
  • ノードイメージ・kubelet/containerd の不調
  • Azure ポリシーの Deny
  • TLS インスペクションや CA ストアに起因する証明書エラー

重要なのは、アクティビティ ログ → VMSS → オートスケーラー → ノード内部 → ネットワーク/TLS の順に、レイヤーごとに事実を積み上げていくことです。一つひとつの証拠を確認していけば、必ず「どこで」「なぜ」止まっているのかが見えてきます。

設計段階で在庫リスクや TLS インスペクションを意識し、複数ゾーン・複数 SKU を組み合わせた構成や、ノードイメージの定期更新、TLS 除外ルールの整備を行っておくことで、この種のトラブルは大幅に減らすことができます。この記事の内容を、自身の AKS クラスターの設計レビューやトラブルシュートのチェックリストとして役立てていただければ幸いです。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次