次の方法で共有


Azure Container Apps に Orleans をデプロイする

このチュートリアルでは、ショッピング カート アプリケーション Orleans サンプルを Azure Container Apps にデプロイする方法について説明します。 このチュートリアルでは、「Orleansを Azure App Service にデプロイする」で紹介したサンプル Orleansショッピング カート アプリの機能を拡張します。 サンプル アプリは、Azure Active Directory (AAD) の企業間 (B2C) 認証を追加し、Azure Container Apps にデプロイします。

GitHub Actions、.NET と Azure CLI、Azure Bicep を使用してデプロイする方法について説明します。 さらに、コンテナー アプリの HTTP イングレスを構成する方法について説明します。

このチュートリアルでは、以下の内容を学習します。

  • Orleans アプリケーションを Azure Container Apps にデプロイする
  • GitHub Actions と Azure Bicep を使用してデプロイを自動化する
  • HTTP イングレスを構成する

[前提条件]

アプリをローカルで実行する

アプリをローカルで実行するには、 Azure Samples: Orleans ショッピング カートを Azure Container Apps リポジトリに フォークし、ローカル コンピューターに複製します。 複製が完了したら、任意の IDE でソリューションを開きます。 Visual Studio を使用している場合は、Orleansを右クリックします。ShoppingCart.Silo プロジェクトで、[スタートアップ プロジェクトとして設定] を選択し、アプリを実行します。 それ以外の場合は、次の .NET CLI コマンドを使用してアプリを実行します。

dotnet run --project Silo\Orleans.ShoppingCart.Silo.csproj

詳細については、の "dotnet run" を参照してください。 アプリを実行すると、ランディング ページでアプリの機能について説明します。 右上隅にサインイン ボタンが表示されます。 アカウントにサインアップするか、既に存在する場合はサインインします。 サインインしたら、移動してその機能をテストします。 ローカルで実行するすべてのアプリ機能は、メモリ内の永続化とローカル クラスタリングに依存します。 また、 Bogus NuGet パッケージを使用して偽の製品を生成します。 Visual Studio で [デバッグの停止] オプションを選択するか、.NET CLI で Ctrl+キーを押して、アプリを停止します。

AAD B2C

認証の概念については、このチュートリアルでは説明していませんが、 Azure Active Directory B2C テナントを作成し、それを使用する Web アプリを登録 する方法について説明します。 このショッピング カートのサンプル アプリでは、結果としてデプロイされた Container Apps の URL を B2C テナントに登録します。 詳細については、「 ASP.NET Core Blazor の認証と承認」を参照してください。

Von Bedeutung

コンテナー アプリがデプロイされたら、B2C テナントにアプリの URL を登録します。 ほとんどの運用シナリオでは、アプリの URL は変更されないため、登録が必要なのは 1 回だけです。

Azure Container Apps 環境内でアプリがどのように分離されているかを視覚化するには、次の図を参照してください。

Azure Container Apps の HTTP イングレス。

前の図では、アプリへの受信トラフィックはすべて、セキュリティで保護された HTTP イングレスを介してファネルされます。 Azure Container Apps 環境にはアプリ インスタンスが含まれており、アプリ インスタンスには ASP.NET Core ホストが含まれており、Blazor サーバーと Orleans アプリの機能が公開されています。

Azure Container Apps へのデプロイ

Azure Container Apps にアプリをデプロイするために、リポジトリでは GitHub Actions が使用されます。 このデプロイを行う前に、いくつかの Azure リソースが必要であり、GitHub リポジトリを正しく構成する必要があります。

アプリをデプロイする前に、Azure リソース グループを作成します (または、既存のものを使用できます)。 新しい Azure リソース グループを作成するには、次のいずれかの記事を使用します。

選択したリソース グループ名を書き留めます。後でアプリをデプロイするために必要になります。

サービス プリンシパルを作成する

アプリのデプロイを自動化するには、サービス プリンシパルを作成する必要があります。 これは、ユーザーに代わって Azure リソースを管理するアクセス許可を持つ Microsoft アカウントです。

az ad sp create-for-rbac --sdk-auth --role Contributor \
  --name "<display-name>"  --scopes /subscriptions/<your-subscription-id>

作成される JSON 資格情報は次のようになりますが、クライアント、サブスクリプション、テナントの実際の値を使用します。

{
  "clientId": "<your client id>",
  "clientSecret": "<your client secret>",
  "subscriptionId": "<your subscription id>",
  "tenantId": "<your tenant id>",
  "activeDirectoryEndpointUrl": "https://login.microsoftonline.com/",
  "resourceManagerEndpointUrl": "https://brazilus.management.azure.com",
  "activeDirectoryGraphResourceId": "https://graph.windows.net/",
  "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
  "galleryEndpointUrl": "https://gallery.azure.com",
  "managementEndpointUrl": "https://management.core.windows.net"
}

コマンドの出力をクリップボードにコピーし、次の手順に進みます。

GitHub シークレットを作成する

GitHub には、暗号化されたシークレットを作成するためのメカニズムが用意されています。 作成したシークレットは、GitHub Actions ワークフローで使用できます。 GitHub Actions を使用して、Azure Bicep と組み合わせてアプリのデプロイを自動化する方法について説明します。 Bicep は、宣言型の構文を使用して Azure リソースをデプロイするドメイン固有言語 (DSL) です。 詳細については、「Bicep とは」を参照してください。 サービス プリンシパルの作成手順の出力を使用して、JSON 形式の資格情報を使用して AZURE_CREDENTIALS という名前の GitHub シークレットを作成する必要があります。

GitHub リポジトリ内で、[>>します。 AZURE_CREDENTIALS名前を入力し、前の手順の JSON 資格情報を [値] フィールドに貼り付けます。

GitHub リポジトリ: シークレット > 設定

詳細については、「 GitHub: 暗号化されたシークレット」を参照してください。

Azure デプロイの準備

デプロイ用にアプリをパッケージ化します。 Orleans.ShoppingCart.Silos プロジェクトでは、Target ステップの後に実行されるPublish要素が定義されます。 このターゲットは、発行ディレクトリを silo.zip ファイルに圧縮します。

<Target Name="ZipPublishOutput" AfterTargets="Publish">
    <Delete Files="$(ProjectDir)\..\silo.zip" />
    <ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ProjectDir)\..\silo.zip" />
</Target>

.NET アプリを Azure Container Apps にデプロイする方法は多数あります。 このチュートリアルでは、GitHub Actions、Azure Bicep、および .NET と Azure の CLI を使用します。 GitHub リポジトリのルートにある ./github/workflows/deploy.yml ファイルについて考えてみましょう。

name: Deploy to Azure Container Apps

on:
  push:
    branches:
    - main

env:
  UNIQUE_APP_NAME: orleanscart
  SILO_IMAGE_NAME: orleanscart-silo
  AZURE_RESOURCE_GROUP_NAME: orleans-resourcegroup
  AZURE_RESOURCE_GROUP_LOCATION: eastus

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Setup .NET 6.0
      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: 6.0.x

    - name: .NET publish shopping cart app
      run: dotnet publish ./Silo/Orleans.ShoppingCart.Silo.csproj --configuration Release

    - name: Login to Azure
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}

    - name: Flex ACR Bicep
      run: |
        az deployment group create \
          --resource-group ${{ env.AZURE_RESOURCE_GROUP_NAME }} \
          --template-file '.github/workflows/flex/acr.bicep' \
          --parameters location=${{ env.AZURE_RESOURCE_GROUP_LOCATION }}

    - name: Get ACR Login Server
      run: |
        ACR_NAME=$(az deployment group show -g ${{ env.AZURE_RESOURCE_GROUP_NAME }} -n acr \
        --query properties.outputs.acrName.value | tr -d '"')
        echo "ACR_NAME=$ACR_NAME" >> $GITHUB_ENV
        ACR_LOGIN_SERVER=$(az deployment group show -g ${{ env.AZURE_RESOURCE_GROUP_NAME }} -n acr \
        --query properties.outputs.acrLoginServer.value | tr -d '"')
        echo "ACR_LOGIN_SERVER=$ACR_LOGIN_SERVER" >> $GITHUB_ENV

    - name: Prepare Docker buildx
      uses: docker/setup-buildx-action@v1

    - name: Login to ACR
      run: |
        access_token=$(az account get-access-token --query accessToken -o tsv)
        refresh_token=$(curl https://${{ env.ACR_LOGIN_SERVER }}/oauth2/exchange -v \
        -d "grant_type=access_token&service=${{ env.ACR_LOGIN_SERVER }}&access_token=$access_token" | jq -r .refresh_token)
        # The null GUID 0000... tells the container registry that this is an ACR refresh token during the login flow
        docker login -u 00000000-0000-0000-0000-000000000000 \
        --password-stdin ${{ env.ACR_LOGIN_SERVER }} <<< "$refresh_token"

    - name: Build and push Silo image to registry
      uses: docker/build-push-action@v2
      with:
        push: true
        tags: ${{ env.ACR_LOGIN_SERVER }}/${{ env.SILO_IMAGE_NAME }}:${{ github.sha }}
        file: Silo/Dockerfile

    - name: Flex ACA Bicep
      run: |
        az deployment group create \
          --resource-group ${{ env.AZURE_RESOURCE_GROUP_NAME }} \
          --template-file '.github/workflows/flex/main.bicep' \
          --parameters location=${{ env.AZURE_RESOURCE_GROUP_LOCATION }} \
            appName=${{ env.UNIQUE_APP_NAME }} \
            acrName=${{ env.ACR_NAME }} \
            repositoryImage=${{ env.ACR_LOGIN_SERVER }}/${{ env.SILO_IMAGE_NAME }}:${{ github.sha }} \
          --debug

    - name: Get Container App URL
      run: |
        ACA_URL=$(az deployment group show -g ${{ env.AZURE_RESOURCE_GROUP_NAME }} \
        -n main --query properties.outputs.acaUrl.value | tr -d '"')
        echo $ACA_URL

    - name: Logout of Azure
      run: az logout

上記の GitHub ワークフローでは、次の処理が行われます。

  • dotnet publish コマンドを使用して、ショッピング カート アプリを zip ファイルとして発行します。
  • サービス プリンシパルの作成手順の資格情報を使用して Azure にログインします。
  • acr.bicep ファイルを評価し、az deployment group create を使用してデプロイ グループを開始します。
  • デプロイ グループから Azure Container Registry (ACR) ログイン サーバーを取得します。
  • リポジトリの AZURE_CREDENTIALS シークレットを使用して ACR にログインします。
  • サイロ イメージをビルドして ACR に発行します。
  • main.bicep ファイルを評価し、az deployment group create を使用してデプロイ グループを開始します。
  • サイロをデプロイします。
  • Azure からログアウトします。

ワークフローは、 main ブランチへのプッシュでトリガーされます。 詳細については、 GitHub Actions と .NET を参照してください。

ヒント

ワークフローの実行時に問題が発生した場合は、サービス プリンシパルに必要なすべてのプロバイダー名前空間が登録されていることを確認する必要があります。 次のプロバイダー名前空間が必要です。

  • Microsoft.App
  • Microsoft.ContainerRegistry
  • Microsoft.Insights
  • Microsoft.OperationalInsights
  • Microsoft.Storage

詳細については、「リソース プロバイダー登録エラーの解決」を参照してください。

Azure では、リソースの名前付け制限と規則が適用されます。 次の環境変数の deploy.yml ファイル内の値を更新します。

  • UNIQUE_APP_NAME
  • SILO_IMAGE_NAME
  • AZURE_RESOURCE_GROUP_NAME
  • AZURE_RESOURCE_GROUP_LOCATION

これらの値を、一意のアプリ名と Azure リソース グループの名前と場所に設定します。

詳細については、「Azure リソースの名前付け規則と制限事項」を参照してください。

Bicep テンプレートを調べる

az deployment group create コマンドを実行すると、指定された .bicep ファイル参照が評価されます。 このファイルには、デプロイする Azure リソースの詳細を示す宣言型情報が含まれています。 この手順は、デプロイのためにすべてのリソース をプロビジョニングすると 考えてください。

Von Bedeutung

Visual Studio Code を使用している場合、Bicep 拡張機能を使用すると 、Bicep 作成エクスペリエンスが向上します。

評価される最初の Bicep ファイルは acr.bicep ファイルです。 このファイルには、Azure Container Registry (ACR) ログイン サーバー リソースの詳細が含まれています。

param location string = resourceGroup().location

resource acr 'Microsoft.ContainerRegistry/registries@2021-09-01' = {
  name: toLower('${uniqueString(resourceGroup().id)}acr')
  location: location
  sku: {
    name: 'Basic'
  }
  properties: {
    adminUserEnabled: true
  }
}

output acrLoginServer string = acr.properties.loginServer
output acrName string = acr.name

この Bicep ファイルは、ACR ログイン サーバーと対応する名前を出力します。 次に検出された Bicep ファイルには、単一の resource以上のものが含まれています。 主に定義の委任で構成される module ファイルについて考えてみましょう。

param appName string
param acrName string
param repositoryImage string
param location string = resourceGroup().location

resource acr 'Microsoft.ContainerRegistry/registries@2021-09-01' existing = {
  name: acrName
}

module env 'environment.bicep' = {
  name: 'containerAppEnvironment'
  params: {
    location: location
    operationalInsightsName: '${appName}-logs'
    appInsightsName: '${appName}-insights'
  }
}

var envVars = [
  {
    name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
    value: env.outputs.appInsightsInstrumentationKey
  }
  {
    name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
    value: env.outputs.appInsightsConnectionString
  }
  {
    name: 'ORLEANS_AZURE_STORAGE_CONNECTION_STRING'
    value: storageModule.outputs.connectionString
  }
  {
    name: 'ASPNETCORE_FORWARDEDHEADERS_ENABLED'
    value: 'true'
  }
]

module storageModule 'storage.bicep' = {
  name: 'orleansStorageModule'
  params: {
    name: '${appName}storage'
    location: location
  }
}

module siloModule 'container-app.bicep' = {
  name: 'orleansSiloModule'
  params: {
    appName: appName
    location: location
    containerAppEnvironmentId: env.outputs.id
    repositoryImage: repositoryImage
    registry: acr.properties.loginServer
    registryPassword: acr.listCredentials().passwords[0].value
    registryUsername: acr.listCredentials().username
    envVars: envVars
  }
}

output acaUrl string = siloModule.outputs.acaUrl

上記の Bicep ファイルでは、次の処理が行われます。

  • existing ACR リソースを参照します。 詳細については、「 Azure Bicep: 既存のリソース」を参照してください。
  • module env 定義ファイルに委任するを定義します。
  • module storageModule 定義ファイルに委任するを定義します。
  • サイロ モジュールで使用される複数の共有 envVars を宣言します。
  • module siloModule 定義ファイルに処理を委任するを定義します。
  • ACA URL を出力します (既存の AAD B2C アプリ登録のリダイレクト URI を更新するために使用される可能性があります)。

main.bicep は、他のいくつかの Bicep ファイルにデリゲートします。 1 つ目は environment.bicep ファイルです。

param operationalInsightsName string
param appInsightsName string
param location string

resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: appInsightsName
  location: location
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: logs.id
  }
}

resource logs 'Microsoft.OperationalInsights/workspaces@2021-06-01' = {
  name: operationalInsightsName
  location: location
  properties: {
    retentionInDays: 30
    features: {
      searchVersion: 1
    }
    sku: {
      name: 'PerGB2018'
    }
  }
}

resource env 'Microsoft.App/managedEnvironments@2022-03-01' = {
  name: '${resourceGroup().name}env'
  location: location
  properties: {
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logs.properties.customerId
        sharedKey: logs.listKeys().primarySharedKey
      }
    }
  }
}

output id string = env.id
output appInsightsInstrumentationKey string = appInsights.properties.InstrumentationKey
output appInsightsConnectionString string = appInsights.properties.ConnectionString

この Bicep ファイルでは、Azure Log Analytics リソースと Application Insights リソースを定義します。 appInsights リソースはwebの種類であり、logs リソースはPerGB2018の種類です。 appInsightsリソースとlogs リソースの両方がリソース グループの場所にプロビジョニングされます。 appInsights リソースは、logs プロパティを使用してWorkspaceResourceId リソースにリンクします。 この Bicep ファイルは、後で Container Apps moduleによって使用される 3 つの出力を定義します。 次に、 storage.bicep ファイルについて考えてみましょう。

param name string
param location string

resource storage 'Microsoft.Storage/storageAccounts@2021-08-01' = {
  name: name
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
}

var key = listKeys(storage.name, storage.apiVersion).keys[0].value
var protocol = 'DefaultEndpointsProtocol=https'
var accountBits = 'AccountName=${storage.name};AccountKey=${key}'
var endpointSuffix = 'EndpointSuffix=${environment().suffixes.storage}'

output connectionString string = '${protocol};${accountBits};${endpointSuffix}'

上記の Bicep ファイルでは、次のものが定義されています。

  • リソース グループ名とアプリ名の 2 つのパラメーター。
  • ストレージ アカウントの resource storage 定義。
  • ストレージ アカウントの接続文字列を構築する 1 つの output

最後の Bicep ファイルは container-app.bicep ファイルです。

param appName string
param location string
param containerAppEnvironmentId string
param repositoryImage string = 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
param envVars array = []
param registry string
param registryUsername string
@secure()
param registryPassword string

resource containerApp 'Microsoft.App/containerApps@2022-03-01' = {
  name: appName
  location: location
  properties: {
    managedEnvironmentId: containerAppEnvironmentId
    configuration: {
      activeRevisionsMode: 'multiple'
      secrets: [
        {
          name: 'container-registry-password'
          value: registryPassword
        }
      ]
      registries: [
        {
          server: registry
          username: registryUsername
          passwordSecretRef: 'container-registry-password'
        }
      ]
      ingress: {
        external: true
        targetPort: 80
      }
    }
    template: {
      revisionSuffix: uniqueString(repositoryImage, appName)
      containers: [
        {
          image: repositoryImage
          name: appName
          env: envVars
        }
      ]
      scale: {
        minReplicas: 1
        maxReplicas: 1
      }
    }
  }
}

output acaUrl string = containerApp.properties.configuration.ingress.fqdn

前述の Bicep 用 Visual Studio Code 拡張機能には、ビジュアライザーが含まれています。 これらすべての Bicep ファイルは、次のように視覚化されます。

Orleans: ショッピング カートのサンプル アプリ Bicep プロビジョニング ビジュアライザーのレンダリング。

概要

ソース コードが更新され、変更がリポジトリの push ブランチにmainされると、deploy.yml ワークフローが実行されます。 Bicep ファイルで定義されている Azure リソースをプロビジョニングし、アプリケーションをデプロイします。 リビジョンは、Azure Container Registry に自動的に登録されます。

Bicep 拡張機能のビジュアライザーに加えて、Azure portal のリソース グループ ページは、アプリケーションのプロビジョニングとデプロイ後の次の例のようになります。

Azure Portal: Orleans Azure Container Apps のショッピングカートサンプルアプリリソース。

こちらも参照ください