つばろぐ

主に C#, .NET, Azure の備忘録です。たまに日記。

Project Tye でデプロイするアプリケーションで Azure SQL Database を使う

これまで Project Tye の記事で扱っていたサンプルコードでは、 RDB を使っておらず Redis だけがデータストアでした。
実際にアプリケーションを書く場合は RDB を使わないというケースはあまりないので、今回は SQL Server や Azure SQL Database を使ってオーケストレーションしてみます。

ASP.NET Core Razor Page のチュートリアルのアプリケーションを使って Project Tye の構成を作っていきます。

AspNetCore.Docs/aspnetcore/tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie30 at master · dotnet/AspNetCore.Docs · GitHub

なお、今回のローカル開発環境は SQL Server Express Local DB を使うため、 Windows 限定の内容になっています。
ちゃんとクロスプラットフォームな構成にしたかったので SQL Server Linux を Docker を使っていたのですが、どうにもエラーが解消しきれない状態なので一旦 Windows 向けの手順になります。
このあたりはまた別の記事で書きたいと思います。

データベースのオートマイグレーションを有効にする

Project Tye でオーケストレーションを行うにあたり、データベースのオートマイグレーションが有効になるようコードを書き換えます。
RazorPagesMovie30 では Entity Framework Core を使ったマイグレーションファイルが用意されています。
ただしこのマイグレーションファイルを適用するためにはコマンドラインdotnet ef database update を行う必要があり、 Tye でのオーケストレーションには不向きです。

そこで Program.cs を以下のように変更します。変更箇所はコメントを入れています。

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using RazorPagesMovie.Models;
using System;

// 追加 ここから
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
// 追加 ここまで

namespace RazorPagesMovie
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();

            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;

                try
                {
                    // 追加 ここから
                    var context = services.GetRequiredService<RazorPagesMovieContext>();
                    context.Database.Migrate();
                    // 追加 ここまで

                    SeedData.Initialize(services);
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred seeding the DB.");
                }
            }

            host.Run();

        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

context.Database.Migrate() でアプリケーション実行時にマイグレーションが行われるようになります。

tye.yaml を作成して実行

RazorPagesMovie30 を Project Tye で実行するには、まず tye.yaml を作成します。

tye init
Created 'D:\src\yuta\netcore\project-tye\RazorPagesMovie30\tye.yaml'.
Time Elapsed: 00:00:00:07

生成された tye.yaml はこのような内容になっています。

name: razorpagesmovie
services:
- name: razorpagesmovie
  project: RazorPagesMovie.csproj

では tye を実行します。

> tye run
Loading Application Details...
Launching Tye Host...

[16:16:17 INF] Executing application from D:\src\yuta\netcore\project-tye\RazorPagesMovie30\tye.yaml
[16:16:17 INF] Dashboard running on http://127.0.0.1:8000
[16:16:17 INF] Building projects
[16:16:18 INF] Launching service razorpagesmovie_c59ea1fd-7: D:\src\yuta\netcore\project-tye\RazorPagesMovie30\bin\Debug\netcoreapp3.1\RazorPagesMovie.exe
[16:16:18 INF] razorpagesmovie_c59ea1fd-7 running on process id 35244 bound to http://localhost:56350, https://localhost:56351
[16:16:18 INF] Replica razorpagesmovie_c59ea1fd-7 is moving to a ready state
[16:16:19 INF] Selected process 35244.
[16:16:19 INF] Listening for event pipe events for razorpagesmovie_c59ea1fd-7 on process id 35244

起動しました。ただ、画面が崩れている理由はよくわかりません。
ダッシュボードから RazorPagesMovie30 にアクセスして、きちんとデータが表示されることを確認しました。
ローカルDBもマイグレーションとデータシードが実行されたことも確認できました。

f:id:tech-tsubaki:20201108170011p:plain

f:id:tech-tsubaki:20201108170024p:plain

Azure SQL Database を使用する状態で AKS にデプロイする

ではアプリケーションに変更を加えずに AKS にデプロイします。このときデータベースがローカルDBのままでは正しく動かないので、Azure SQL Databaseを使うように設定を上書きします。

あらかじめ Azure SQL Database は作成しておきます。

docs.microsoft.com

次に tye.yaml を変更します。
RazorPagesMovie30 ではデータベースの接続文字列は appsettings.json に記載されているので、同名の環境変数を tye.yaml で上書きします。

ちなみに通常 .NET Core ではネストした環境変数を指定するときには :(コロン)を使います。
なので ConnectionStrings:RazorPagesMovieContext と書くのが一般的ですが、AKSではコロンを含んだ名前を環境変数に使用することができません。
なので __ (アンダースコア2つ)を区切り文字に使用します。

Project Tye における環境変数の参照順序は以前の記事にまとめてますので、よかったらご覧ください。

tsubalog.hatenablog.com

name: razorpagesmovie
services:
- name: razorpagesmovie
  project: RazorPagesMovie.csproj
  env:
    - name: ConnectionStrings__RazorPagesMovieContext
      value: (接続文字列)

AKS へのデプロイ方法も詳しくは以前の記事をご覧ください。

tsubalog.hatenablog.com

$ tye deploy --interactive
Loading Application Details...
Verifying kubectl installation...
Verifying kubectl connection to cluster...
Enter the Container Registry (ex: 'example.azurecr.io' for Azure or 'example' for dockerhub): acrprojecttye.azurecr.io
Processing Service 'razorpagesmovie'...
    Applying container defaults...
    Compiling Services...
    Publishing Project...
    Building Docker Image...
            #2 [internal] load build definition from Dockerfile
            #2 transferring dockerfile: 159B done
            #2 DONE 0.0s

            #1 [internal] load .dockerignore
            #1 transferring context: 2B done
            #1 DONE 0.0s

            #3 [internal] load metadata for mcr.microsoft.com/dotnet/core/aspnet:3.1
            #3 DONE 0.2s

            #4 [1/3] FROM mcr.microsoft.com/dotnet/core/aspnet:3.1@sha256:4030ec40f9b5c...
            #4 DONE 0.0s

            #6 [internal] load build context
            #6 transferring context: 29.76MB 0.1s done
            #6 DONE 0.2s

            #5 [2/3] WORKDIR /app
            #5 CACHED

            #7 [3/3] COPY . /app
            #7 CACHED

            #8 exporting to image
            #8 exporting layers done
            #8 writing image sha256:77b158309f52d8bfac30696f04ace2d2195f377b3fdcd1c167f0dcdba8f17d0b done
            #8 naming to acrprojecttye.azurecr.io/razorpagesmovie:1.0.0 done
            #8 DONE 0.0s
        Created Docker Image: 'acrprojecttye.azurecr.io/razorpagesmovie:1.0.0'
    Pushing Docker Image...
        Pushed docker image: 'acrprojecttye.azurecr.io/razorpagesmovie:1.0.0'
    Validating Secrets...
    Generating Manifests...
Deploying Application Manifests...

        Verifying kubectl installation...
        Verifying kubectl connection to cluster...
        Writing output to '/tmp/tmp9DRZyP.tmp'.
        Deployed application 'razorpagesmovie'.
Time Elapsed: 00:00:13:68

$ kubectl port-forward svc/razorpagesmovie 5000:80
Forwarding from 127.0.0.1:5000 -> 80
Forwarding from [::1]:5000 -> 80

AKS にデプロイされたアプリケーションにアクセスすることができました。
このときデータベースは tye.yaml で指定した Azure SQL Database に接続しています。

f:id:tech-tsubaki:20201108170043p:plain