App Service の VNet 統合で Cosmos DB のプライベート エンドポイントに繋いでみる


本記事は [Microsoft Azure Tech Advent Calendar 2020](https://qiita.com/advent-calendar/2020/microsoft-azure-tech) の 16 日目です。
早いもので今年の Advent Calendar もそろそろ折り返しです。

# はじめに
Microsoft Azure Tech Advent Calendar 2020 ということで、せっかくなのでいくつかの Azure 製品が組み合わさりそうなテーマにしてみました。Azure PaaS (WebApps / Cosmos DB)、Azure Network (VNet / Private Endpoint) の組み合わせです。

具体的には Azure App Service (Windows) のリージョン VNet 統合を利用して、Azure Cosmos DB のプライベート エンドポイント (Private Endpoint) に接続するまでの方法の一例を紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/f1997223-8701-0cc3-e226-f218fab0c9ce.png)


なお、プライベート エンドポイント先はプライベート エンドポイントをサポートしている他の PaaS サービスに適宜置き換えて頂いても問題ないです。

## 今回出てくる主な Azure リソース
- Azure App Service (Windows / Azure Web Apps)
- Azure Cosmos DB
- Azure Virtual Network (VNet)



# 概要
今回利用するリージョン VNet 統合は簡単に述べると、マルチテナントの PaaS サービスである App Service から同じリージョン内にある Azure Virtual Network (仮想ネットワーク、以下 VNet) に接続することができる機能です。ちなみに、あくまでこれは App Service からの送信に関する機能で、VNet からの受信に適用されるわけではありません。

また、Azure プライベート エンドポイントを利用することで、Public IP ではなく Private IP 経由で PaaS サービスにアクセスすることが可能です。なお、その Private IP は Azure Virtual Network のサブネットから払い出される仕組みのため、上記の App Service の VNet 統合先の VNet に PaaS サービスの Private Endpoint を構成することで結果的に App Service から Private IP 経由で PaaS サービスにアクセスができるようになります。

では早速手順を含めて、その一例として Cosmos DB (PaaS) のケースを本記事でご紹介いたします。


# 前提
今回のテーマはプライベート エンドポイント関連の接続構成やリソース作成がメインとなるため、以下を前提とします。

- Azure Cosmos DB が App Service と同じリージョンに既にデプロイされている
- その Azure Cosmos DB に接続する Web アプリが既に Azure App Service (Windows) に デプロイされている
- Azure App Service の App Service Plan が Premium V2 である
- 同 App Service Plan 内の App Service では VNet 統合は未構成

※ 下記のように工夫を行うことで、Standard でも利用可能ですが今回はシンプルに検証を行うため Premium V2 としておきます。Standard を利用したい方は以下のやり方で実施ください。

> この機能は、Premium V2 と Premium V3 のすべての App Service スケール ユニットから使用できます。 また、Standard でも使用できますが、新しい App Service のスケール ユニットからのみ利用できます。 以前のスケール ユニットを使用している場合は、Premium V2 App Service プランの機能のみを使用できます。 Standard App Service プランでこの機能を使用できるようにするには、Premium V3 App Service プランでアプリを作成します。 それらのプランは、最新のスケール ユニットでのみサポートされます。 その後、必要に応じてスケールダウンできます。

(https://docs.microsoft.com/ja-jp/azure/app-service/web-sites-integrate-with-vnet#regional-vnet-integration より)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/e1471ec3-29ac-8cd7-d870-0f8e4e45dd1f.png)


# 1. Azure virtual network を作成
App Service と同じリージョンに virtual network をデプロイします。
後で作ってもよいですが、ついでに VNet 作成時に App Service の VNet 統合用とプライベートエンドポイント用にサブネットを 2 つ作成しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/0d8458dd-0fcb-597f-c985-d18171c89483.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/d3ee9caf-6abb-f368-831a-5e5035f9e234.png)


※1. 2 の App Service の VNet 統合の構成時にサブネットを新規作成できるのでこの後作成しても良いです
※2. またいずれか片方は新規作成せずに VNet 作成時にデフォルトで作成される default のサブネットを利用しても問題ないです

# 2. App Service でリージョン VNet 統合を構成
[ネットワーク] パネルを選択し、VNet 統合の [構成するにはここをクリック] をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/af5a9e5b-a010-ab8f-d8ad-e5934bd842c6.png)


[+ VNet の追加] ボタンをクリックし、先ほど作成した VNet のサブネットを選択し、[OK] を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/b6e9acd2-6878-d72d-87c3-c423f7b346d1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/ef5ba80d-7cd8-76cb-aa31-509feb496f08.png)

# 3. Cosmos DB でプライベート エンドポイントを構成
Cosmos DB のリソースに移動し、[プライベート エンドポイント接続] パネルを選択し、[+ プライベート エンドポイント] をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/06707871-1f4f-af87-c7b6-d1fe54468f9d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/e60fd712-f25a-a6fc-0c83-f9cfb1ce5513.png)

プライベート エンドポイントで接続する Comsos DB を選択します。
該当の Cosmos DB は SQL API で接続するので Sql が表示されそれを選択しますが、MongoDB など別 API であればその API 名が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/61093d81-8641-7cb9-6c2a-22010c5b2562.png)

1 で作成した VNet を選択し、プライベート エンドポイント用に作成したサブネットを選択します。

また、[プライベート DNS ゾーンと統合する] も既定の [はい] の選択のままにし、Private DNS Zone とレコードを作成するようにしておきます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/18e08758-a9a2-882b-85e7-7cb6184c770b.png)


最後の [作成] ボタンで作成を行います。


# 4. Azure App Service の構成にて DNS 用のパラメータを追加

この状態だと Cosmos DB のドメインをまだ Public IP へ解決してしまうので結果的に Cosmos DB に接続ができません。
(上記プライベートエンドポイント構成時に自動的にファイアウォールの設定がプライベートエンドポイントに限定されるため、アクセスが拒否されます)

すべての送信トラフィックを VNet にルーティングし、作成した Private Endpoint 用の NIC の Private IP に Private DNS Zone を用いて解決できるようにするため、以下の DNS サーバーと VNET 統合に関するパラメータを App Service のアプリケーション設定に設定します。

まず、Cosmos DB にアクセスするアプリケーションがホストされている該当の App Service リソースのページに戻り、[構成] パネルへ移動します。

[+ 新しいアプリケーション設定] から WEBSITE_DNS_SERVER という名前で 168.63.129.16 の値を設定します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/5f2c542a-91b3-a4c5-96dd-3926ef86f11a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/08603b77-e9c8-cf1b-9d43-189c05981aa6.png)

同様に、[+ 新しいアプリケーション設定] から WEBSITE_VNET_ROUTE_ALL という名前で 1 の値を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/40a249ab-50ce-14a0-4009-8f9c6a49c3fd.png)

# 5. プライベートエンドポイントのメトリックで確認
App Service のアプリ経由で Cosmos DB にアクセスを行い、正常にアクセスできることを確認します。

念の為、Cosmos DB に結び付けている [プライベート エンドポイント] のページに行き、[メトリック] のパネルを開き、プライベート エンドポイント経由で該当の Cosmos DB にアクセスが発生していることが確認します。以下のようにメトリックが出て、正常に経由してアクセスが来ていることが簡易的に確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/97a36384-6ff7-94aa-73b8-b4b0a1ed852d.png)

# 補足. Cosmos DB の Firewall の設定
Azure Cosmos DB リソースの [ファイアウォールと仮想ネットワーク] パネル内の [Azure Portal からのアクセスを許可する] をチェックしておくことをおすすめします。これをチェックして行わないと、プライベートエンドポイントを設定した後に、アクセスが制限され、Portal 上の [データ エクスプローラ] パネルでの操作等が正常にできなくなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150728/6081f53d-44bf-0275-bc8e-e361c7be101c.png)


# 最後に
今回の記事では Azure App Service の VNet 統合を利用して、Azure Cosmos DB の Private Endpoint 経由で Cosmos DB に Private IP でアクセスする方法をご紹介しました！
今回の記事が少しでも今後の構築や検討の際のご参考になれば幸いです。

なお、これらは App Service か他の PaaS サービスに Private Endpoint 経由でアクセスしたい場合にも応用できる方法と考えられますので、ぜひ他のサービスも試してみていただければと思います。


## 参考情報
- Azure プライベート エンドポイントとは
https://docs.microsoft.com/ja-jp/azure/private-link/private-endpoint-overview
- Integrate your app with an Azure virtual network
https://docs.microsoft.com/en-us/azure/app-service/web-sites-integrate-with-vnet