Top View


Author yukabeoka

[Azure] Functions と DB for PostgreSQL を VNet 統合してみる

2021/09/07

Vnet(Azure Virtual Network)統合とは?

通常、Azure App Service は仮想ネットワーク上のリソースにはアクセスできません。
VNet 統合とは、App Service Service がインターネット経由のルーティングを使用せずに仮想ネットワーク内のリソースにアクセスできる機能です。
今回は Functions を VNet 統合し、パブリックアクセスができない DB にプライベート IP でアクセスする構成を作成しました。
これにより、Functions はインターネット上に公開されているものの、その先の DB への通信はインターネットを介さず、また DB へのアクセスは Functions からのプライベート IP のみとなり、一定のセキュリティを担保できます。

参考にしたドキュメントはこちら

ざっくりこうすればできそう

  1. リソース (Database for Postgres、FunctionApp、Storage Account、VNet など) を作成する
  2. DB にプライベートエンドポイント接続設定をする
  3. FunctionsApp にプライベートエンドポイント接続設定をする
  4. プライベート DNS ゾーン の設定をする
  5. 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-db10.0.0.0/24
subnet-functions10.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

yukabeoka

カスタマーサポートからエンジニアにジョブチェンジ。脳の老化に抗いがんばる。最近はAzureにいじめられている。