Azure Container Apps に Orleans をデプロイする
このチュートリアルでは、Azure Container Apps にサンプルの Orleans ショッピング カート アプリケーションをデプロイする方法について説明します。 このチュートリアルでは、「Azure App Service に Orleans をデプロイする」で紹介している、サンプルの Orleans ショッピング カート アプリの機能を拡張します。 サンプル アプリでは、Azure Active Directory (AAD) の企業-消費者間 (B2C) 認証を追加し、Azure Container Apps にデプロイします。
GitHub Actions、.NET と Azure CLI、Azure Bicep を使用してデプロイする方法について学習します。 さらに、Container Apps の HTTP イングレスを構成する方法について学習します。
このチュートリアルでは、以下の内容を学習します。
- Azure Container Apps に Orleans アプリケーションをデプロイする
- GitHub Actions と Azure Bicep を使ってデプロイを自動化する
- HTTP イングレスを構成する
前提条件
- GitHub アカウント
- Orleans の概要について読む
- .NET 6 SDK
- Azure CLI
- .NET 統合開発環境 (IDE)
- Visual Studio または Visual Studio Code を自由にお使いください
アプリをローカルで実行する
アプリをローカルで実行するには、Azure サンプル: Azure Container Apps の Orleans ショッピング カートのリポジトリをフォークし、ローカル コンピューターにクローンします。 クローンしたら、お好みの 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+C キーを押してください。
AAD B2C
認証の概念については、このチュートリアルでは説明していませんが、Azure Active Directory B2C テナントを作成する方法を学習してから、Web アプリを登録してそれを使用することができます。 このショッピング カートのサンプル アプリの場合、結果としてデプロイされた Container Apps の URL を B2C テナントに登録する必要があります。 詳細については、「ASP.NET Core Blazor 認証と承認」を参照してください。
重要
Container Apps がデプロイされた後、B2C テナントにアプリの URL を登録する必要があります。 ほとんどの運用環境のシナリオでは、アプリの URL を 1 回登録するだけで済みます。変更することはできません。
Azure Container Apps 環境内でアプリがどのように分離されているかを視覚化するために、次の図を参照してください。
前の図では、アプリへのすべての受信トラフィックは、セキュリティで保護された HTTP イングレスを介してファネルされます。 Azure Container Apps 環境にはアプリ インスタンスが含まれており、そのアプリ インスタンスには、Blazor Server と Orleans アプリ機能を公開する ASP.NET Core ホストが含まれています。
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 のワークフローで使用できます。 アプリのデプロイを自動化するために、Azure Bicep と組み合わせて GitHub Actions を使う方法を見ていきます。
Bicep は、宣言型の構文を使用して Azure リソースをデプロイするドメイン固有言語 (DSL) です。 詳細については、「Bicep とは」を参照してください。 「サービス プリンシパルの作成」の手順で得た出力を使用し、JSON 形式の資格情報を使って AZURE_CREDENTIALS
という名前の GitHub シークレットを作成する必要があります。
GitHub リポジトリ内で、[Settings](設定)>[Secrets](シークレット)>[Create a new secret](新しいシークレットの作成) の順に選択します。
AZURE_CREDENTIALS
という名前を入力し、前の手順の JSON 資格情報を [Value](値) フィールドに貼り付けます。
詳細については、GitHub: 「Encrypted Secrets (暗号化されたシークレット)」を参照してください。
Azure デプロイの準備をする
アプリは、デプロイ用にパッケージ化する必要があります。
Orleans.ShoppingCart.Silos
プロジェクトで、Publish
ステップの後に実行される Target
要素を定義します。 これにより、発行ディレクトリが silo.zip ファイルに圧縮されます。
<Target Name="ZipPublishOutput" AfterTargets="Publish">
<Delete Files="$(ProjectDir)\..\silo.zip" />
<ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ProjectDir)\..\silo.zip" />
</Target>
Azure Container Apps に .NET アプリをデプロイする方法は多数あります。 このチュートリアルでは、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 からログアウトします。
ワークフローは、"メイン" ブランチへのプッシュによってトリガーされます。 詳細については、「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 リソースの詳細な宣言情報が含まれています。 この手順は、デプロイのためにすべてのリソースを "プロビジョニング" すると考えることもできます。
重要
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 ファイルに含まれるのは、単なる 1 つの resource
ではありません。 主に module
定義の委任で構成される main.bicep ファイルを考えてみましょう。
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: 既存のリソース」を参照してください。 -
environment.bicep 定義ファイルに委任する
module env
を定義します。 -
storage.bicep 定義ファイルに委任する
module storageModule
を定義します。 - サイロ モジュールによって使用される複数の共有
envVars
を宣言します。 -
container-app.bicep 定義ファイルに委任する
module siloModule
を定義します。 - ACA URL を出力します (これは、既存の AAD B2C アプリ登録のリダイレクト URI を更新するために使用される可能性があります)。
main.bicep は他のいくつかの Bicep ファイルに委任されます。 最初は 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
リソースは、WorkspaceResourceId
プロパティを使用して logs
リソースにリンクされます。 この bicep で定義されている出力は 3 つあり、後で Container Apps module
によって使用されます。 次に、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 ファイルは、次のように視覚化されます。
まとめ
ソース コードを更新し、変更をリポジトリの main
ブランチに push
すると、deploy.yml ワークフローが実行されます。 Bicep ファイルで定義されている Azure リソースをプロビジョニングし、アプリケーションをデプロイします。 リビジョンは、Azure Container Registry に自動的に登録されます。
Bicep 拡張機能のビジュアライザーに加えて、アプリケーションをプロビジョニングしてデプロイした後の Azure portal のリソース グループ ページは次の例のようになります。
関連項目
.NET