Azure App ServiceでマネージドIDを使ってコンテナレジストリのイメージをpullする
私の働いている会社では、Azure App Service Web App for Containersでアプリケーションをホストしています。
Azure App Serviceには、Azure PipelinesでビルドしたDocker imageをAzure Container Registryにpushしてデプロイしてるのですが、以下のようなエラーでAzure App Serviceからのpullができませんでした。
2021-03-23T21:26:19.442Z ERROR - DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Get https://hoge.azurecr.io/v2/redacted/manifests/0.1.0: unauthorized: authentication required, visit https://aka.ms/acr/authorization for more information."}
2021-03-23T21:26:19.445Z ERROR - Image pull failed: Verify docker image configuration and credentials (if using private repository)
上記エラーは、クレデンシャルが適切でない場合や、マネージドIDを使用している場合にスコープや割当が適切でない場合に発生します。
この記事では、このエラーを解消するため、マネージドIDを使ったAzure App Serviceからのコンテナのpullを行う方法を紹介します。
前提条件
- Azure Pipelinesやローカル環境から、Azure Container Registry(以下ACR)にイメージをすでにpushしている
- Azure App Service Web App for Containers(以下App Service)のリソースをすでに作成している
ACRの認証方法には2つの方法がある
ACRの認証方法は2つあります。
- 管理者ユーザーを使用する方法
- マネージドID(IAM)を使用する方法
管理者ユーザーを使用するほうが、基本的には楽で
ここの管理者ユーザーを有効にして、出てきたIDとパスワードを、App Serviceの環境変数
- DOCKER_REGISTRY_SERVER_USERNAME
- DOCKER_REGISTRY_SERVER_PASSWORD
にそれぞれ設定するだけです。
しかし、細かく設定したかったり、管理者ユーザーを作成することに抵抗がある場合もあるでしょう。
そういった場合には、2のマネージドIDを使った方法で認証することになります。
マネージドIDとは
自分もあんまり詳しくよくわかってないですが、リソースに対して、Azure EntraIDでいうところのユーザーみたいなのを割り当てられるやつです。
こいつを割り当てられると、ユーザーに割当られるような権限をマネージドIDを使ってリソースに対して割り当てることができます。
これにより、柔軟かつ厳格な権限管理を、リソースに対して行えてとってもセキュアで便利です。
ハマったポイント
手順をご紹介する前に、今回マネージドIDを使ってApp ServiceからACRのイメージをpullする時にハマったことを紹介します。
基本的に、うまくいってないと、冒頭で紹介したような以下のようなエラーが出ます。
2021-03-23T21:26:19.442Z ERROR - DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Get https://hoge.azurecr.io/v2/redacted/manifests/0.1.0: unauthorized: authentication required, visit https://aka.ms/acr/authorization for more information."}
2021-03-23T21:26:19.445Z ERROR - Image pull failed: Verify docker image configuration and credentials (if using private repository)
デプロイスロットから認証ができない
これはまぁ当たり前っちゃ当たり前かもしれませんが、App Serviceのデプロイスロットにも、個別にマネージドIDを作成して、ロールを割り当ててあげる必要がありました。
なので、デプロイスロットを使っている場合は、すべてのスロットに対して、ロールを割り当ててあげましょう。
マネージドIDにIAMを設定しても認証できない
マネージドIDに対してIAMを適切なスコープで設定しても、なぜか認証できませんでした。
実は、Azure CLIから設定してあげる必要があって、以下のようなコマンドで設定できます。
az webapp config set --resource-group <group-name> --name <app-name> --generic-configurations '{"acrUseManagedIdentityCreds": true}'
デプロイスロットでの設定をする場合は以下のようにできます。
az webapp config set --resource-group <group-name> --name <app-name> --slot <slot-name> --generic-configurations '{"acrUseManagedIdentityCreds": true}'
以下のページで一応これが説明されてますが、あまりにも1文すぎて探すのめっちゃ大変でした。
なかなか反映されない
なんかちゃんと上記の設定をしてても認証できなかったんですよね。
何が悪かったんかなぁと思っていたら、放置してたらうまくいきました。
その後いろいろ試してみて、以下のことをやると、うまくいく可能性がありそうでした。
ただうまくいかないこともあって、よくわかってないです。こういうとこAzureの悪いとこだぞ
- リソースを停止→起動する
- リソースを再起動する
- 停止・起動も、再起動も、実行した後にアプリケーションに接続(ブラウザで開く)と起動コマンドがトリガーされるみたい。再起動したのに起動ログが出てこないなぁと思ったら、アプリケーションに接続してみてください。
- 放置する
- 最終手段。ちゃんと設定してるはずなのにうまくいかなかったら、1時間くらい放置してみるとうまくいったりします。
設定手順
1. マネージドIDを発行する
App Serviceから、設定>IDを開きます。
マネージドIDの状態をオンに設定して、マネージドIDをリソースに対して発行・設定します。
こんな感じになれば発行は完了です。
2. マネージドIDにAcrPullを割り当てる
発行したマネージドIDに対して、ACRからpullできるロールを割り当てます。
Azureロールの割り当てを開きます。
ロールの割り当ての追加を開きます。
スコープをサブスクリプションかリソースグループに設定し、役割をAcrPullにして保存します。
3. App Serviceに対してマネージドIDを使うように設定する
Azure CLIもしくはCloudShellを使用して、以下のようにマネージドIDを使うように設定します。
az webapp config set --resource-group resource-group-name --name app-service-name --slot staging --generic-configurations '{"acrUseManagedIdentityCreds": true}'
これでApp Serviceの設定は完了です。
4. デプロイの設定を行う
これはAzure Pipelinesなどでデプロイパイプラインを作ってる場合は不要です。
Azure Pipelinesなどでデプロイパイプラインを構築していない場合は、App Serviceのデプロイセンターより以下のようにしてデプロイの設定をします。
(SCMのBasic認証を有効にする必要があります)
イメージとタグは、イメージがリポジトリ、タグはそのままタグになります。
(自動では入らないので、自分で設定します)
確認してみる
ログストリームを開きながら、設定しても認証できないを参考に、アプリケーションの再起動を実行します。
イメージが正常にpullされ、起動すれば完了です。
おわりに
今回は、App ServiceでACRからマネージドIDを使ってイメージをpullする方法を紹介しました。
ほんとにマジで色々検証するの大変でした。Azureは情報がなさすぎる。
誰かの役に立てば幸いです。それでは。
参考にしたもの
Discussion