Azure Functions Premium プランのリージョン仮想ネットワークの統合を試してみた


Azure Functions Puremium プランでリージョン仮想ネットワークの統合というのが一般提供されたみたいですね。

Azure Functions Premium プランのリージョン仮想ネットワークの統合

仮想ネットワークまわりはめんどくさい印象しかなくて、なるべく遠ざけてきたのですが、この機会に触ってみたいと思います。

確認方法

仮想ネットワークのサービス エンドポイントっていうのを使って Azure Functions Premium から SQL Database にアクセスしてみようと思います。
なんとなく、Database がインターネットにつながっているのを嫌がる人も多いし自分も、なんとなく理解できるので。

ということで Azure ポータルでポチポチリソースを作っていきます。全部同じリージョンに作りましょう。

  • Azure Functions Premium plan
  • SQL Database (安いサーバーレスモデル)
  • 仮想ネットワーク
    • サブネット 2 つ (default: 10.0.0.0/24, functions: 10.0.1.0/24)

サブネットを作るときにサービス エンドポイントを構成できて、そこで Microsoft.SQL を 10.0.1.0/24 のほうに追加します。(作ったあとからでも設定できます)

SQL Database の方を完全にふさいでしまう前に DB 作ってしまいます。自分の IP アドレスを SQL Database のファイアウォールに追加して、SQL Database のクエリエディター(プレビュー)から以下の SQL を実行してテーブルとデータを作っておきました。

CREATE TABLE MESSAGES (
  ID INTEGER PRIMARY KEY,
  MESSAGE NVARCHAR(256)
);

INSERT INTO MESSAGES(ID, MESSAGE) VALUES(1, 'Hello from SQL Database');

Azure Functions の構成

とりあえず Azure Functions で VNet 統合をします。Azure Functions のネットワークの設定を開いて NNet 統合の「構成するにはここをクリック」を選択しましょう。

そして「VNet の追加」を選択して、先ほど作っておいた functions という名前のサブネットを選びます。

適当に Azure Functions のコードを作成します。とりあえず SQL Database につながればいいので手抜きな感じで、こんなコードを書きました。

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Data.SqlClient;
using Microsoft.Extensions.Configuration;

namespace PrivateNetFunc
{
    public class Function1
    {
        public Function1(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        private IConfiguration Configuration { get; }

        [FunctionName("Function1")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            string result = null;
            using (var conn = new SqlConnection(Configuration.GetConnectionString("DB_CON")))
            {
                await conn.OpenAsync();
                log.LogInformation("Opened");
                using (var command = conn.CreateCommand())
                {
                    command.CommandText = "SELECT TOP 1 MESSAGE FROM MESSAGES";
                    log.LogInformation($"Execugint Query: {command.CommandText}");
                    using (var r = await command.ExecuteReaderAsync())
                    {
                        log.LogInformation($"Executed ExecuteReaderAsync");
                        await r.ReadAsync();
                        log.LogInformation($"Executed ReadAsync");
                        result = r.GetString(0);
                        log.LogInformation($"Get data: {result}");
                    }
                }

                await conn.CloseAsync();
            }

            return new OkObjectResult($"{DateTime.UtcNow}: {result}");
        }
    }
}

SQL Database の接続文字列をポータルからゲットして Azure Functions の接続文字列に DB_CON という名前でついかしましょう。

そして、Azure Functions にコードをデプロイします。

動作確認(動かないことを確認)

まだ、ちゃんと設定が終わっていないのでエラーになるはずです。試してみましょう。
叩くとこんな感じのエラーが出ました。

SQL Server の仮想ネットワークからの接続受け入れ設定

仮想ネットワークのサービスエンドポイントで Microsoft.Sql を追加しましたが、まだ SQL Server 側で仮想ネットワークからの通信を行け入れるようにしていなかったので SQL Server のファイアウォールと仮想ネットワークで、既存の仮想ネットワークを追加を選択して、 functions の仮想ネットワークを追加します。

再度動作確認(動くことを確認)

この設定まで完了すると、関数のエンドポイントを叩くことで、ちゃんと動くようになります。

余談

Azure Functions は、仮想ネットワーク上にあるわけじゃないので、その点は注意です。
あと、Azure Functions の全ての送信側の通信を仮想ネットワーク側に回して、ネットワークセキュリティグループとかで制御したい場合には、アプリケーション設定に以下の項目を追加することで、RFC 1918 以外の通信も仮想ネットワークにルーティングするようになります。

  • WEBSITE_VNET_ROUTE_ALL という名前で値に 1 を設定

まとめ

こんだけ、簡単に仮想ネットワークに統合できて、仮想ネットワークからのアクセスのみに SQL Db やらなんやら対応サービスを構成するだけで接続元を絞れるなら仮想ネットワーク使うのもいいですね。