[Azure] Functions と DB for PostgreSQL を VNet 統合してみる
2021/09/07
Table of Contents
Vnet(Azure Virtual Network)統合とは?
通常、Azure App Service は仮想ネットワーク上のリソースにはアクセスできません。
VNet 統合とは、App Service Service がインターネット経由のルーティングを使用せずに仮想ネットワーク内のリソースにアクセスできる機能です。
今回は Functions を VNet 統合し、パブリックアクセスができない DB にプライベート IP でアクセスする構成を作成しました。
これにより、Functions はインターネット上に公開されているものの、その先の DB への通信はインターネットを介さず、また DB へのアクセスは Functions からのプライベート IP のみとなり、一定のセキュリティを担保できます。
参考にしたドキュメントはこちら
ざっくりこうすればできそう
- リソース (Database for Postgres、FunctionApp、Storage Account、VNet など) を作成する
- DB にプライベートエンドポイント接続設定をする
- FunctionsApp にプライベートエンドポイント接続設定をする
- プライベート DNS ゾーン の設定をする
- FuncsionsApp をデプロイして試す
これを今回は AzurePortal の画面ポチポチで作っていきます。
くわしく
まずリソースグループを作成し、すべてその中で作業します。
1. FunctionApp を作成する
リソースの作成>関数アプリ>諸々入力
プラン
に注意!
FunctionsPremium
のみ対応しています。スペックは一番下のEP1
にします。
(一緒に StorageAccount も作っておきましょう)
ここで Azure がはじき出した Functions の推定コストは 2 万、、うぅむ
EP1
ACU 合計 210
3.5 GB メモリ
Dv2 シリーズ コンピューティングと同等
20031.20 JPY/月のベースライン (推定)
2. Database for Postgres を作成する
次に Database for Postgres を作ります。
リソースの作成>Azure Database for Postgres>単一サーバー
なるべく費用を抑えようとコア数を減らしました。ただ、汎用のままにしましょう。(Basic だと次に設定する パブリックアクセスの拒否
ができません)
接続のセキュリティからパブリックアクセスを拒否にしておきます。
※ただし今の構成だと誰も DB の中を見れないので、テストのときはパブリックアクセスを許可し、IP アドレスで制限かける SSH するといった方法を取ります。
Azure がはじき出した推定コストは DB も月 2 万、、うぅむ
価格の概要
Gen 5 コンピューティング世代
コスト/ vCore 10375.34
仮想コア 選択項目 × 2
+
汎用のストレージ
コスト/ GB / 月 15.46
選択されたストレージ (GB 単位) × 100
毎月のコストの見積もり 22296.29 JPY
3. VNet、プライベート DNS ゾーンを作成する
VirtualNetwork を作成し、サブネットを 2 つ作ります。
Functions を受けるサブネットと、DB にアクセスするプライベートエンドポイント用のサブネットです。
subnet 名 | アドレス |
---|---|
subnet-db | 10.0.0.0/24 |
subnet-functions | 10.0.1.0/24 |
次にプライベート DNS ゾーンを作成します。
DNS ゾーン作成> privatelink.postgres.database.azure.com
という名前で作成。
作成後、A レコードを設定します。
Database for Postgres のサーバー名で作成します。
Aレコード名
+プライベートDNSゾーン名
がFQDN
になります。
仮想ネットワークとリンクさせます
4. DB にプライベートエンドポイント接続設定をする
Database for Postgres>プライベートエンドポイント接続
項目名 | 設定値 |
---|---|
リソースの種類 | Microsoft.DBforPostgreSQL/servers |
リソース | 作成した DB サーバー |
対象サブリソース | postgresqlServer |
サブネット | 作成したDB用 のサブネット |
プライベート DNS ゾーンと統合する | はい |
プライベート DNS ゾーン | 作成したプライベート DNS ゾーン |
5. FunctionsApp にプライベートエンドポイント接続設定をする
FunctionApp>Network >送信トラフィック>VNET 統合より プライベートエンドポイントを追加します
項目 | 設定値 |
---|---|
サブネット | 10.0.1.0/24 |
サブネットの委任 | Microsoft.Web/serverFarms |
5. FuncsionsApp をデプロイする
AzureLearn を参考にサンプル関数を作成します。
HttpTrigger で関数発火し、DB に書き込めれば OK です。
今回は EntityFrameworkCore の練習も兼ねていたので下記を参考にサンプル関数を作りました。
この関数の中で一つ重要なことは、Azure Database for Postgres
への接続情報は先程作成したプライベートエンドポイントで設定することです。
通常の DB の接続文字列等を利用するとインターネットを介したアクセスになってしまいます。
xxxxxxxx.privatelink.postgres.database.azure.com
へ繋いでいることをチェックしましょう。
DB 接続情報部分.cs
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseNpgsql("Host=<プライベートエンドポイントFQDNを設定>;Database=<DB名>;Username=<ユーザー名>;Password=<パスワード>");
DB 読み書き部分.cs
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
DbTest();
return new OkObjectResult("OK");
}
private static void DbTest()
{
using (var db = new BloggingContext())
{
db.Database.EnsureCreated();
// Create
Console.WriteLine("Inserting a new blog");
db.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
db.SaveChanges();
// Read
Console.WriteLine("Querying for a blog");
var blog = db.Blogs
.OrderBy(b => b.BlogId)
.First();
Console.WriteLine(blog);
db.SaveChanges();
}
}
Zip デプロイで作成した関数をデプロイします。コマンドでできるのでいいですね!
これを知らないときはわざわざ VisualStudio からデプロイしていました。。(開発は VScode…)
cd App_Root
$FUNCTIONAPP=(デプロイ先の関数アプリ名)
func azure functionapp publish $FUNCTIONAPP --dotnet CLI_DEBUG=1
参考
Entity Framework Core
Azure Functions Core Tools の操作
デプロイに失敗するとき確認
.NET Core 3.1 インストールしていますか?
https://dotnet.microsoft.com/download
実際に関数を呼んでみる
関数がデプロイされたら URL を取得して叩いてみる。
うまくいくと関数のログが成功になり、関数が OK を返します。
- DB にデータが入るか?(Database for Postgres のパブリックアクセスを拒否しているので中身が見れません。一旦 IP アドレス制限付きの穴をあけるなどして確認します)
- Functions の DB 接続部分をパブリックな接続文字列に変えて実行すると怒られるか?
お掃除
最終的なコストは 1 日あたり 1,000 円位はかかりそうなので忘れずに消しましょう。
Azure はリソースグループごと消せばいいので楽です!
まとめ
今回はある程度のセキュリティを担保しつつ、小さい範囲で実現できる VNet 統合を試しました。
とはいえ AppServicePlan, Database for Postgres ともにそこそこ上のプランでないと設定そのものができません。
ランニングコストとセキュリティを考えて決める必要があります。
また、今回は同一リージョン内、1AppService 対 1DB なのでゲートウェイは構築しませんでした。
リージョンまたぎなどもっと大規模な構成だとゲートウェイやルートテーブルも必要になると思います。
yukabeoka
カスタマーサポートからエンジニアにジョブチェンジ。脳の老化に抗いがんばる。最近はAzureにいじめられている。