Microsoft Build 2022 で Azure Container Apps が GA されました。東日本リージョンでも使えるようになりましたので、Blue-Green Deployments を試してみました。
Azure Container Apps とは
Azure Container Apps は、複数のコンテナアプリで構成されるシステム向けのサービスです。これまでは Web Apps for Containers か AKS の2択でしたが、新たに Container Apps が追加されたことになります。
docs.microsoft.com
Container Apps は Kubernetes を基盤に構成されています。下記のような Environment / Container App / Revision / Replica の構成要素を理解しておけば OK です。
Container Apps Environment を作成する
Azure Portal では App Service Plan にあたる Environment だけを作成できないため、Bicep を使って Environment を作成します。
environment.bicep では、Environment、LogAnalytics、Application Insights のリソースを定義します。
param environmentName string param logAnalyticsWorkspaceName string = 'logs-${environmentName}' param appInsightsName string = 'appins-${environmentName}' param location string = resourceGroup().location resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' = { name: logAnalyticsWorkspaceName location: location properties: any({ retentionInDays: 30 features: { searchVersion: 1 legacy: 0 enableLogAccessUsingOnlyResourcePermissions: true } sku: { name: 'PerGB2018' } }) } resource appInsights 'Microsoft.Insights/components@2020-02-02' = { name: appInsightsName location: location kind: 'web' properties: { Application_Type: 'web' WorkspaceResourceId:logAnalyticsWorkspace.id } } resource environment 'Microsoft.App/managedEnvironments@2022-03-01' = { name: environmentName location: location properties: { appLogsConfiguration: { destination: 'log-analytics' logAnalyticsConfiguration: { customerId: logAnalyticsWorkspace.properties.customerId sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey } } daprAIInstrumentationKey: appInsights.properties.InstrumentationKey zoneRedundant: false } } output location string = location output environmentId string = environment.id
main.bicep では、Resource Group 名にプレフィックスをつけて Environment 名を定義します。
param environmentName string = 'env-${resourceGroup().name}' param location string = resourceGroup().location module environment 'environment.bicep' = { name: 'container-app-environment' params: { environmentName: environmentName location: location } }
Azure CLI を使って、デプロイします。
$ az group create -n <ResourceGroup Name> -l japaneast $ az deployment group create -f ./deploy/env/main.bicep -g <ResourceGroup Name>
作られたリソースは、こんな感じです。
Container Apps をデプロイする
Container Apps についても、Azure Portal では細かい構成を指定できないので、Bicep を使って作成します。
あらかじめ ASP.NET Core Web アプリケーションの Docker Image を作っておいたので、apps.bicep でデプロイします。
param containerAppName string param location string = resourceGroup().location param environmentId string param containerImage string param revisionSuffix string param oldRevisionSuffix string param isExternalIngress bool @allowed([ 'multiple' 'single' ]) param revisionMode string = 'single' resource containerApp 'Microsoft.App/containerApps@2022-03-01' = { name: containerAppName location: location properties: { managedEnvironmentId: environmentId configuration: { activeRevisionsMode: revisionMode ingress: { external: isExternalIngress targetPort: 80 transport: 'auto' allowInsecure: false traffic: ((contains(revisionSuffix, oldRevisionSuffix)) ? [ { weight: 100 latestRevision: true } ] : [ { weight: 0 latestRevision: true } { weight: 100 revisionName: '${containerAppName}--${oldRevisionSuffix}' } ]) } dapr:{ enabled:false } } template: { revisionSuffix: revisionSuffix containers: [ { image: containerImage name: containerAppName resources: { cpu: '0.25' memory: '0.5Gi' } } ] scale: { minReplicas: 1 maxReplicas: 10 rules: [ { name: 'http-scaling-rule' http: { metadata: { concurrentRequests: '10' } } } ] } } } } output fqdn string = containerApp.properties.configuration.ingress.fqdn
main.bicep では、Blue-Green Deployments を行うため、revisions-mode に multiple
を指定します。
新旧 RevisionSuffix に v1
を指定することで、デプロイしたアプリケーションの traffic を 100%
にします。
param environmentName string = 'env-${resourceGroup().name}' param containerAppName string = 'dapr-frontend' param location string = resourceGroup().location param containerImage string = 'thara0402/dapr-frontend:0.1.0' param revisionSuffix string = 'v1' param oldRevisionSuffix string = 'v1' param isExternalIngress bool = true param revisionMode string = 'multiple' resource environment 'Microsoft.App/managedEnvironments@2022-03-01' existing = { name: environmentName } module apps 'apps.bicep' = { name: 'container-apps' params: { containerAppName: containerAppName location: location environmentId: environment.id containerImage: containerImage revisionSuffix: revisionSuffix oldRevisionSuffix: oldRevisionSuffix revisionMode: revisionMode isExternalIngress: isExternalIngress } }
Azure CLI を使って、デプロイします。
$ az deployment group create -f ./deploy/app/main.bicep -g <ResourceGroup Name>
デプロイすると、dapr-frontend--v1
という Revision が作成されました。
dapr-frontend.bravewave-d4e6d1bd.japaneast.azurecontainerapps.io
という FQDN が自動生成されました。
ASP.NET Core Web アプリケーションがブラウザで表示されることを確認できます。
Blue-Green Deployments を行う
Staging へのデプロイを想定し、新しいバージョンをデプロイします。
main.bicep では、containerImage のタグを 0.2.0
、revisionSuffix のバージョンを v2
に更新することで、先ほどデプロイした Revision( dapr-frontend--v1
)へのトラフィックを 100%
のまま、新しい Revision をデプロイします。
param containerImage string = 'thara0402/dapr-frontend:0.2.0' param revisionSuffix string = 'v2'
デプロイすると、dapr-frontend--v2
という Revision が追加されました。
traffic が「0」の新しい Revision には、ユーザーに公開される FQDN とは異なる FQDN が割り当てられるので、リリース前のテストができます。
dapr-frontend--v2.bravewave-d4e6d1bd.japaneast.azurecontainerapps.io/
という Revision が含まれた FQDN が自動生成されました。
リリース前のテストが完了したので、Azure CLI を使って Swap します。
拡張モジュールをインストールし、名前空間を登録します。Preview のときは Microsoft.Web 名前空間でしたが、Microsoft.App 名前空間に移行されています。
$ az extension add --name containerapp --upgrade $ az provider register --namespace Microsoft.App
$ az containerapp ingress traffic set -n dapr-frontend -g <ResourceGroup Name> \ --revision-weight dapr-frontend--v1=0 latest=100
traffic のパーセンテージが入れ替わったことを確認できます。
ユーザーに公開される FQDN にアクセスすると、V2 に更新された ASP.NET Core Web アプリケーションが表示されます。
最後に、旧バージョンの Revision をシャットダウンします。アクティブのままだと、課金対象となってしまいます。
$ az containerapp revision deactivate -n dapr-frontend -g <ResourceGroup Name> --revision dapr-frontend--v1
新バージョンの Revision のみになったことを確認できます。
まとめ
Azure Container Apps で Blue-Green Deployments を試してみました。トラフィック制御の比率を変えることで AB テストやカナリアリリースもできます。
Envoy によるトラフィック制御以外にも、KEDA によるスケーリングや Dapr によるサイドカーなどの面白い機能があるので、引き続き試していきたいと思います。
今回のソースコードは、こちらのリポジトリで公開しています。
github.com