先にVNetを用意してAKSを作ると苦しむかも?
2020-03-06
azblob://2022/11/11/eyecatch/2020-03-05-creating-vnet-first-and-then-creating-aks-may-suffer-000.jpg

概要

サクッとWindowsコンテナ用のAKSを立てたくてMSドキュメントを参考に、深く考えずに少しアレンジして環境構築したらハマった話です。
問題の原因がハッキリ特定できていませんが、解決方法があるようなので情報共有のためブログ化します。

言いたいこと

  • コマンドのデフォルト動作は基本的に良い感じに周辺リソースを作ってくれるが、要件によっては泥沼にはまる原因になる
  • 急がば回れ、環境構築は実績のある方法を使おう

やってしまったこと

この部分は読み飛ばしても良いですが、言いたいことを実感いただくためには読んでいただいた方が良いかと思います。

検証用にWindowsコンテナが動くAKS環境を作りたく、下記ページを参考にAKS環境を構築していました。

https://docs.microsoft.com/ja-jp/azure/aks/windows-container-cli

普通に作る分にはこれでOKなのですが、今回は既に用意している他の環境とのVNetピアリングが必要だったので、VNetが使用するアドレス範囲のバッティングでNGとなりました。

困ったなぁ・・・と思いつつ、コマンドのリファレンスを見てみます。

https://docs.microsoft.com/en-us/cli/azure/aks?view=azure-cli-latest#az-aks-create

az aks create のパラメータに --vnet-subnet-id というのがあるではないですか。先に良い感じのアドレス範囲になっているVNetを用意して、その中のサブネットIDを渡せばいいのね!と認識し、意気揚々とコマンドを再実行しました。

無事AKS環境が作成され、VNetピアリングもでき、よっしゃやってやるでとAKSクラスタにDeploymentとInternal Loadbalancer用のServiceを作成ました。
Podが作成されたのを確認できたので、ServiceのExternal-IPの割り当てまだかな~?と待っていたのですが、10分ほど待っても作成されず、 kubectl describe service で状態を確認したところ、無情にもエラーメッセージが。。

既に脳みそが溶けかけていたのでメッセージの内容を保存することすら忘れ、必死でググったところ、下記の記事に巡り合いました。

ページを日本語に翻訳してみたところ「 AKSクラスターを完全に再インストールした後、最終的にこの問題を回避する方法を見つけました。 」と出たので心臓が止まりかけましたが、ちゃんと読むとどうやら権限周りの問題と分かり、記載通りに進めることで解消できました。

(改めて)発生した問題と解決策

ほぼ上記の参考リンクと同じ状況と思いますが、整理してみます。

実施した事項

  • AzureポータルからVNetを作成した
  • az aks create コマンドを使用しAKSクラスタを作成した
    • この時、--vnet-subnet-id パラメータに上記のVNet内のサブネットを指定した
  • az aks nodepool add コマンドを使用しWindowsノードプールを作成した
    • この時、--vnet-subnet-id パラメータに上記のVNet内のサブネットを指定した
  • kubectl apply を使用し、Windowsコンテナを使用するDeploymentとServiceを作成した

発生した問題

  • Serviceの EXTERNAL-IP が割り当てられない

問題の原因

  • AKSクラスタに自動的に割り当てられたサービスプリンシパルの権限が、事前に作成したVNetを取り扱うためには不足しており、 EXTERNAL-IP の割り当て処理の実行が失敗した(っぽい)

解決方法

【方法1】VNetのアクセス制御(IAM)で、AKSクラスタに割り当てられたサービスプリンシパルに対してOwner権限を与える

参考ブログに記載されていますので、ざっと手順を書きます。

  • 下記コマンドを実行し、AKSが使用しているサービスプリンシパルのClient IDを取得します。
> az aks show -n 【AKS名】 -g 【AKSの所属するリソースグループ名】 | findstr clientId
"clientId": "xxx-xxx-xxx-xxx-xxx"
  • 得られたClient IDをAzureポータルのAzure Active Directoryのアプリの登録から検索し、アプリケーションの名前を確認します。
  • VNetのアクセス制御で、上記のアプリケーションに対してOwner権限を付与します

【方法2】terraformで、同じ権限でVNetとAKSを作成する

AKSクラスタ作成時に使用するサービスプリンシパルにContributor権限のサービスプリンシパルを使用した場合、VNetとAKSをterraformで作成すれば同じトラブルが発生したことが無いです。

terraformで作成されたVNetのIAMを見ると、AKS用に用意したサービスプリンシパルが Contributorとして追加されていました。ここが影響しているのでしょうか。

元のブログ記事と比較すると何とも言えないところですが、リソースの作成方法を揃えることは重要なのではないかと思います。

まとめ

非常に曖昧な内容になってしまい恐縮ですが、同じ問題に直面している方に向けて情報共有ができる状態にしてみました。
また詳しい原因が分かれば修正したいと思いますが、Azureリソースを作成する際はterraformを使って構築していくと失敗が少なく済むのではないかと思います。