こんばんは。今日は、Microsoft Azure App Serviceの中でも、ILB ASEにWebアプリをデプロイする方法について整理しておこうと思います。
なぜ、ILB ASEにフォーカスしているかといいますと、ILB ASEは、以下のドキュメントの通り、デフォルトではインターネットとの通信が完全に遮断されているため、VSCodeを含め、インターネットを経由するデプロイは行えず、デプロイを可能にするためには構成や設定における考慮が必要なためです。自分もハマったため、ここに整理しておこうと思います。
https://docs.microsoft.com/ja-jp/azure/app-service/environment/create-ilb-ase
それでは、早速参ります。
Contents
前提:ILB ASEを使ってデプロイする際の構成
はじめに、ILB ASEへアプリをデプロイする際に前提となる構成について整理しておきます。
インターネットへの接続を前提としているELB ASEではなくILB ASEを選択している時点で、アプリへのアクセスはオンプレミス、またはAzureネットワーク内のリソースからプライベートに接続したい要件があるはずです。
ということで、デプロイについても、以下のようにオンプレミスのクライアントからVPN経由、またはAzureネットワークのリソースからプライベートに(インターネットを介さずに)行うシナリオの前提で話を進めます。
https://docs.microsoft.com/ja-jp/azure/app-service/environment/network-info
VSCodeからILB ASEにアプリをデプロイする方法
今回は、構成の検証にあたり、上記をより簡易にした、以下の構成を作りました。
[確認] 初期構成でデプロイ (失敗します)
さて、まずVMとASEを作成した状態で、VM上のVSCodeからILB ASEへのデプロイを試してみます。
まず、VSCode上の表示。普通にASEリソースは一覧から見えています。このアプリに適当なアプリをデプロイ!
すると、以下のようなエラーが出ました。どうやらデプロイ先である”<アプリ名>.scm.asetest014.appserviceenvironment.net”の名前解決ができていない様子。
The deployment failed with error: request to https://asetest014app.scm.asetest014.appserviceenvironment.net/api/zipdeploy?isAsync=true&author=VS%20Code failed, reason: getaddrinfo ENOTFOUND asetest014app.scm.asetest014.appserviceenvironment.net. Please take a few minutes to help us improve the deployment experience
実は、これはこの状態では想定されたエラーです。Microsoft公式ドキュメントのILB ASEの説明には、以下の説明があります。
https://docs.microsoft.com/ja-jp/azure/app-service/environment/create-ilb-ase#dns-configuration
ILB ASE を使う場合は、独自の DNS を管理する必要があります。 これは、独自の DNS サーバーで、または Azure DNS プライベート ゾーンを使用して行うことができます。
ASEのSubnetにプライベートDNSを構成する
というわけで、上記のガイダンスに従い、ASEをデプロイしているVNETにプライベートDNSを構成していきます。
Azure PortalからプライベートDNSゾーンの作成を選択し、<ASE名>.appserviceenvironment.net用のDNSゾーンを作成します。
DNSゾーンのデプロイが完了したら、レコードを追加していきます。
上記公式ドキュメントより、追加すべきDNSレコードは以下の通りです。
Azure DNS プライベート ゾーンで DNS を構成するには、次の操作を行ってください。
- <ASE 名>.appserviceenvironment.net という名前の Azure DNS プライベート ゾーンを作成する
- そのゾーンに、ILB の IP アドレスに * を指定する A レコードを作成する
- そのゾーンに、ILB の IP アドレスに @ を指定する A レコードを作成する
- そのゾーンに、ILB の IP アドレスに *.scm を指定する A レコードを作成する
ILBのIPアドレスは、App Service EnvironmentリソースのIPアドレスブレードより確認できます。
レコード追加後のDNSゾーンの構成。
最後に、このDNSゾーンをASEをデプロイしているVNETにリンクします。
と、これで準備完了です!!
再びVSCodeからのデプロイを実行
プライベートDNSの構成を行った後、再びVSCodeからのデプロイを行います。
おお、今度はデプロイが開始されました!!(ソースコードが適当なファイルだったので、最終的にはデプロイは失敗していますが、少なくともASE上のWebAppsにはデプロイのリクエストが到達するようになりました。
5:04:42 PM ASETest014App: Starting deployment…
5:04:43 PM ASETest014App: Creating zip package…
5:04:43 PM ASETest014App: Ignoring files from "appService.zipIgnorePattern"
"pycache{,/}" ".py[cod]" "$py.class" ".Python{,/}"
"build{,/}" "develop-eggs{,/}"
"dist{,/}" "downloads{,/}"
"eggs{,/}" ".eggs{,/}"
"lib{,/}" "lib64{,/}"
"parts{,/}" "sdist{,/}"
"var{,/}" "wheels{,/}"
"share/python-wheels{,/}" ".egg-info{,/}"
".installed.cfg"
".egg"
"MANIFEST"
".env{,/}" ".venv{,/}"
"env{,/}" "venv{,/}"
"ENV{,/}" "env.bak{,/}"
"venv.bak{,/}" ".vscode{,/}"
5:04:43 PM ASETest014App: Zip package size: 319 B
5:04:47 PM ASETest014App: Updating submodules.
5:04:48 PM ASETest014App: Preparing deployment for commit id '8460003d09'.
5:04:48 PM ASETest014App: Repository path is /tmp/zipdeploy/extracted
5:04:48 PM ASETest014App: Running oryx build…
5:04:48 PM ASETest014App: Command: oryx build /tmp/zipdeploy/extracted -o /home/site/wwwroot --platform python --platform-version 3.8 -i /tmp/8d929d65bc0db9a --compress-destination-dir -p virtualenv_name=antenv --log-file /tmp/build-debug.log
5:04:49 PM ASETest014App: Operation performed by Microsoft Oryx, https://github.com/Microsoft/Oryx
5:04:49 PM ASETest014App: You can report issues at https://github.com/Microsoft/Oryx/issues
5:04:49 PM ASETest014App: Oryx Version: 0.2.20210420.1, Commit: 85c6e9278aae3980b86cb1d520aaad532c814ed7, ReleaseTagName: 20210420.1
5:04:49 PM ASETest014App: Build Operation ID: |6QTkcNtSoEk=.bc854630_
5:04:49 PM ASETest014App: Repository Commit : 8460003d096046de91fbbfaaec8ed3ac
5:04:49 PM ASETest014App: Detecting platforms…
5:04:49 PM ASETest014App: Could not detect any platform in the source directory.
5:04:51 PM ASETest014App: Error: Couldn't detect a version for the platform 'python' in the repo.
5:04:51 PM ASETest014App: /opt/Kudu/Scripts/starter.sh oryx build /tmp/zipdeploy/extracted -o /home/site/wwwroot --platform python --platform-version 3.8 -i /tmp/8d929d65bc0db9a --compress-destination-dir -p virtualenv_name=antenv --log-file /tmp/build-debug.log
5:04:51 PM ASETest014App: Deployment failed.
ASE上のWebAppsからもデプロイの実績が確認できました!これで、無事にILB ASEにデプロイできる環境が整ったことになります!
番外編 ILB ASEへのデプロイ エラーパターン
ついでに、ILB ASEに関わるさまざまな構成に問題があるとき、デプロイの結果がどのようになるのか、実験してみました。同様のエラーメッセージが表示されてお困りの方の参考になりましたら幸いです。
NSGルールにより通信が遮断されている場合
最初は、NSGで通信が遮断されているパターンです。
事象を再現するため、ASE用に作成されるNSGの受信規則の優先度101に、以下のようにDeny ALLのルールを追加しておきます。
この状態でASEへのデプロイを試してみると、以下のエラーが発生しました。ETIMEDOUTエラーが発生し、コンソールログはzipファイル作成以降のログ(WebApps側の更新ログ)が出力されませんでした。
The deployment failed with error: request to https://asetest014app.scm.asetest014.appserviceenvironment.net/api/zipdeploy?isAsync=true&author=VS%20Code failed, reason: connect ETIMEDOUT 10.9.5.11:443. Please take a few minutes to help us improve the deployment experience
5:07:41 PM ASETest014App: Starting deployment...
5:08:53 PM ASETest014App: Creating zip package...
5:08:53 PM ASETest014App: Ignoring files from "appService.zipIgnorePattern"
"__pycache__{,/**}"
"*.py[cod]"
"*$py.class"
".Python{,/**}"
"build{,/**}"
"develop-eggs{,/**}"
"dist{,/**}"
"downloads{,/**}"
"eggs{,/**}"
".eggs{,/**}"
"lib{,/**}"
"lib64{,/**}"
"parts{,/**}"
"sdist{,/**}"
"var{,/**}"
"wheels{,/**}"
"share/python-wheels{,/**}"
"*.egg-info{,/**}"
".installed.cfg"
"*.egg"
"MANIFEST"
".env{,/**}"
".venv{,/**}"
"env{,/**}"
"venv{,/**}"
"ENV{,/**}"
"env.bak{,/**}"
"venv.bak{,/**}"
".vscode{,/**}"
5:08:53 PM ASETest014App: Zip package size: 319 B
実際に、このエラーに直面した場合には、どのNSGルールより遮断されているかを特定する必要がありますので、NSGフローログを活用いただくことになるかと思います。
WebAppsにIP制限が構成されている場合
次は、WebApps側にIP制限が構成されている場合です。この状況を再現するため、適当に以下のようにIP制限を構成しています。
*クライアントのIPではないIPのみを許可・SCMサイトにも同じ規則を適用
この状態でデプロイを行うと、すぐに以下のエラーが返りました。コンソールログは、先ほどのNSGのケースと同じです。
The deployment failed with error: Error 403 - Forbidden The web app you have attempted to reach has blocked your access.. Please take a few minutes to help us improve the deployment experience
5:20:34 PM ASETest014App: Starting deployment...
5:20:34 PM ASETest014App: Creating zip package...
5:20:34 PM ASETest014App: Ignoring files from "appService.zipIgnorePattern"
"__pycache__{,/**}"
"*.py[cod]"
"*$py.class"
".Python{,/**}"
"build{,/**}"
"develop-eggs{,/**}"
"dist{,/**}"
"downloads{,/**}"
"eggs{,/**}"
".eggs{,/**}"
"lib{,/**}"
"lib64{,/**}"
"parts{,/**}"
"sdist{,/**}"
"var{,/**}"
"wheels{,/**}"
"share/python-wheels{,/**}"
"*.egg-info{,/**}"
".installed.cfg"
"*.egg"
"MANIFEST"
".env{,/**}"
".venv{,/**}"
"env{,/**}"
"venv{,/**}"
"ENV{,/**}"
"env.bak{,/**}"
"venv.bak{,/**}"
".vscode{,/**}"
5:20:34 PM ASETest014App: Zip package size: 319 B
WebAppsが停止している場合
以下のように、WebAppsが停止した状況でデプロイしてみます。
実はこの場合は、アプリのデプロイには影響しません。問題なく成功するはずです。
以上、VSCodeからILB ASEにプライベートなデプロイを行うために必要な構成のまとめでした!少しでも参考になりましたら幸いです!