Azure Container Appsのネットワークオプションとアクセス可能なパターン

Posted on Jul 6, 2022

何の話か

Azure Container Appsには、以下のネットワークオプションがあります。

  • VNet:
    • マネージド
    • カスタム
      • 外部からのアクセスを許可
      • 内部
  • アプリケーション
    • Ingress: 有効 or 無効
      • External: 有効 or 無効

Azure Container Appsはマネージドサービスなので、詳細な内部構造は明らかにされていません。もちろん、それぞれのオプションについて、ドキュメントで説明はされています。しかし、内部構造や構成要素が見えないので、オプションを選択し、組み合わせた場合の効果やふるまいがピンとこない人も多いでしょう。

そこでこのエントリでは、公開されている、もしくは取得可能な情報をベースに、構成要素やオプションの効果を整理します。まずはAzure Container Appsのネットワークオプション別に、その構成要素と関わりを図にまとめます。加えて、アプリケーションをユーザや他アプリケーションから利用する際の基本となるFQDNでアクセス可能なパターンのリストを作ります。

なおAzure Container Appsは進化著しいサービスであるため、本日(2022/7/6〉時点での整理であることをお断りしておきます。

マネージドVNet

graph TB subgraph VNet-Invisible subgraph ContainerApps-Env LB-External --> Ingress Ingress --> Rule-Target-FQDN Rule-Target-FQDN --> FQDN-External Rule-Target-FQDN --> FQDN-Internal FQDN-External --> External-True([Is Ingress External true?]) FQDN-Internal --> From-Env([From the same Contaner Apps Env?]) External-True --> App-with-Ingress From-Env --> App-with-Ingress App --> Ingress App --> DNS-ACA-Internal DNS-ACA-Internal end end Public-IP --> LB-External Client-Public --> Public-IP Client-Public --> DNS-Azure-Public

VNetを指定せずにContainer Apps環境を作ると、VNetはAzureによって管理され、その中は非可視になります。利用者からVNetを識別できる情報がないため、他のVNetやVPN、ExpressRouteを経由したプライベートネットワークとは接続できません。つまりマネージドVNet構成のContainer Apps環境に作ったアプリケーションには、環境内部、もしくはパブリック(インターネット)からアクセスします。

Container Appsでは、環境内外、VNet、パブリックを問わず、アプリケーションのIngress設定をを有効にすることで、アプリケーションにFQDNでアクセスできるようになります。Ingress無効で作成したアプリケーションには、FQDNでのアクセスはできません。なお、コンソールインターフェイスとDapr経由でのアクセスは可能です。

加えて、Ingressにはexternalフラグがあります。trueにすると、環境外部からアクセスできるようになります。いっぽうfalseの場合は、環境内部からのアクセスに限定されます。

Ingressを有効にしたアプリケーション向けには、ルールに従ってFQDNが生成されます

  • Ingressのexternalフラグ
    • true: <APP_NAME>.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io
    • false: <APP_NAME>.internal.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io

既定で内部向けFQDNが作成され、externalフラグをtrueにすると、追加で外部向けも作られます。存在しないFQDNに対するアクセスには、HTTPステータスコード404(Not Found)が返ります。

externalフラグを有効にすると、Container Apps環境の一部として作られるAzure Load Balancer経由で、環境外部からのアクセスができます。KubernetesのLoadBalancerタイプのServiceと同じ位置づけです。

マネージドVNet構成において、環境の外部とはインターネットを意味します。ロードバランサにパブリックIPが付与され、AzureのパブリックDNSでFQDNを名前解決します。そしてロードバランサは、バックエンドにあるIngressにトラフィックを送ります。Ingressの実体はEnvoyで、複数のレプリカで構成されています。

ところで、複数のアプリケーションとFQDNがあっても、Container Apps環境が外部向けに割り当てるIPアドレスは1つです。アプリケーションへの振り分けはIngressが行います。

なお、環境内部からFQDNを名前解決すると、外部向けFQDNであってもパブリックIPではなくプライベートIPが返ってきます。Container Apps環境が持つDNSに問い合わせるためです。解決したIPアドレスは、Kubernetesで言えばClusterIPです。ドキュメントに

FQDN を使用して同じ環境で別のコンテナーを呼び出す場合、ネットワーク トラフィックが環境から出ることはありません

とありますが、この仕組みが背景にあります。

ところで、環境内部でのふるまいを確認するには、シェルが使えてツールの導入も容易な、Ubuntuなどのコンテナを環境に作成し、コンソールアクセスしてみてください。curlやdigなどで、環境内からアクセス可能か、どのように名前解決されるのか、体験できます。

では、マネージドVNetの場合のFQDNアクセスパターンをまとめてみましょう。

Ingress external Source Target FQDN Resolved Target IP
true Same Container App Env <APP_NAME>.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Container App Env Internal
<APP_NAME>.internal.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Container App Env Internal
Public <APP_NAME>.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Public
false Same Container App Env <APP_NAME>.internal.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Container App Env Internal

カスタムVNet - 外部からのアクセスを許可

VNetを指定してContainer Apps環境を作るとどうなるでしょうか。

外部からのアクセスを許可するか、内部に閉じるかの選択肢があります。ここでいう外部とは、Container Apps環境の外部ではなく、インターネットのことです。ちょっとややこしいですが、ドキュメントでの表現に従います。

まずは外部からのアクセスを許可する場合です。

graph TB subgraph VNet-Custom subgraph ContainerApps-Env LB-External --> Ingress Ingress --> Rule-Target-FQDN Rule-Target-FQDN --> FQDN-External Rule-Target-FQDN --> FQDN-Internal FQDN-External --> External-True([Is Ingress External true?]) FQDN-Internal --> From-Env([From the same Contaner Apps Env?]) External-True --> App-with-Ingress From-Env --> App-with-Ingress App --> Ingress App --> DNS-ACA-Internal DNS-ACA-Internal end Client-Private end Client-Private --> DNS-Azure-Private Client-Private --> Public-IP Public-IP --> LB-External Client-Public --> Public-IP Client-Public --> DNS-Azure-Public

カスタムVNetの代表的なユースケースは、他マネージドサービスへのプライベートネットワーク経由でのアクセスです。図をシンプルにするために省略しましたが、Container Apps環境のアプリケーションから、プライベートエンドポイントを使ってストレージアカウントへアクセスしたい、というケースが分かりやすいでしょう。マネージドVNetと違い、VNetをユーザが識別、操作できるため、可能となる構成です。

Container Apps環境が参加するVNetをユーザが操作できる他は、マネージドVNetの構成と大きく変わりません。ですが1点、意識すべきことがあります。同じVNet内の要素、たとえば仮想マシンからContainer Apps環境内のアプリケーションにアクセスする場合の名前解決です。

カスタムVNet構成でContainer Apps環境を作る際、既定で外部からのアクセスは許可されます。この場合、Container Apps環境の内外をつなぐロードバランサには、パブリックIPが割り当てられます。よって、同じVNet内にある仮想マシンであっても、Container Apps環境内のアプリケーションには、パブリックIP経由でアクセスする必要があります。

なお、公式ドキュメントにはプライベートDNSゾーンを使った名前解決方法が紹介されています。Container App環境は属性として、ドメイン名(defaultDomain)と外部アクセス向けIPアドレス(staticIp)を持ちます。これらの情報を組み合わせ、環境内すべてのアプリケーションの名前解決ができるワイルドカード DNS Aレコードを作れます。

*.<defaultDomain> IN A <staticIp>

繰り返しになりますが、アプリケーションへの振り分けはIngressが行います。よって複数のアプリケーションやFQDNがあっても、必要なAレコードはロードバランサに割り当てたIP向けに、1つのみです。

アクセスパターンを以下にまとめます。

Ingress external Source Target FQDN Resolved Target IP
true Same Container App Env <APP_NAME>.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Container App Env Internal
<APP_NAME>.internal.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Container App Env Internal
Same VNet <APP_NAME>.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Public
Public <APP_NAME>.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Public
false Same Container App Env <APP_NAME>.internal.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Container App Env Internal

カスタムVNet - 内部

では最後のVNet構成、カスタムVNetでインターネットからのアクセスを拒否するオプションです。“internal-only”オプションを付けてContainer Apps環境を作成します。

graph TB subgraph VNet-Custom subgraph ContainerApps-Env LB-Internal --> Ingress LB-External Ingress --> Rule-Target-FQDN Rule-Target-FQDN --> FQDN-External Rule-Target-FQDN --> FQDN-Internal FQDN-External --> External-True([Is Ingress External true?]) FQDN-Internal --> From-Env([From the same Contaner Apps Env?]) External-True --> App-with-Ingress From-Env --> App-with-Ingress App --> Ingress App --> DNS-ACA-Internal DNS-ACA-Internal Outbound([Outbound Traffic]) --> LB-External end Private-Link-Service --> LB-Internal Client-Private --> LB-Internal end subgraph VNet-Other Client-Private-Other --> Private-Endpoint Private-Endpoint --> Private-Link-Service end Client-Private --> DNS-Azure-Private Client-Private-Other --> DNS-Azure-Private-Other LB-External --> Internet((Internet))

これまでの構成との大きな違いは、Container Apps環境の入口となるロードバランサに割り当てるIPアドレスが、VNetのプライベートIPになることです。ロードバランサも、内部向けの専用ロードバランサが追加されます。他構成で使われていた外部向けロードバランサは残りますが、Container Apps環境からのアウトバウンド通信のみを担当します。なお、カスタムVNet構成ではロードバランサなど関連するマネージドリソースが“MC_“プレフィックスを持つリソースグループ内に作られ、見ることができます。関心があれば覗いてみてください。

この構成ではContainer Apps環境への入口がプライベートネットワークなので、プライベートネットワークからインターネットに出ることなくアプリケーションへのアクセスが可能です。図の通り、同じVNetにあるクライアント、たとえば仮想マシンからのトラフィックは、VNetに閉じます。

なお、別のVNet、VPNやExpressRouteを用いたリモートネットワークからもアクセスが可能です。VNetをピアリングする、ゲートウェイを置く、もしくはプライベートリンクサービスで実現できます。図はプライベートリンクサービスを使った例です。

では最後に、この構成のアクセスパターンをまとめます。

Ingress external Source Target FQDN Resolved Target IP
true Same Container App Env <APP_NAME>.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Container App Env Internal
<APP_NAME>.internal.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Container App Env Internal
Same VNet <APP_NAME>.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Private (Same VNet)
Other VNet <APP_NAME>.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Private (Same/Other VNet)
false Same Container App Env <APP_NAME>.internal.<UNIQUE_IDENTIFIER>.<REGION_NAME>.azurecontainerapps.io Container App Env Internal

おまけ

各オプション別に環境構築用のTerraform HCLコードをGitHubに置いていますので、合わせて参考にしてください。