ROMANCE DAWN for the new world

Microsoft Azure を中心とした技術情報を書いています。

Azure Container Apps で Blue-Green Deployments を試してみた

先日の Microsoft Ignite で発表された Azure Container Apps で、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 / Pod の構成要素を理解しておけば OK です。

f:id:TonyTonyKun:20211110144308p:plain
Microsoft Docs から引用

Container Apps Environment を作成する

Bicep を使って、App Service Plan にあたる 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-preview' = {
  name: appInsightsName
  location: location
  kind: 'web'
  properties: { 
    ApplicationId: appInsightsName
    Application_Type: 'web'
    Flow_Type: 'Redfield'
    Request_Source: 'CustomDeployment'
  }
}

resource environment 'Microsoft.Web/kubeEnvironments@2021-02-01' = {
  name: environmentName
  location: location
  properties: {
    type: 'managed'
    internalLoadBalancerEnabled: false
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logAnalyticsWorkspace.properties.customerId
        sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
      }
    }
    containerAppsConfiguration: {
      daprAIInstrumentationKey: appInsights.properties.InstrumentationKey
    }
  }
}

output location string = location
output environmentId string = environment.id

main.bicep では、Resource Group 名にプレフィックスをつけて Environment 名を定義します。

param environmentName string = 'env-${resourceGroup().name}'

module environment 'environment.bicep' = {
  name: 'container-app-environment'
  params: {
    environmentName: environmentName
  }
}

Azure CLI を使って、デプロイします。

$ az group create -n <ResourceGroup Name> -l canadacentral
$ az deployment group create -f ./deploy/main.bicep -g <ResourceGroup Name>

作られたリソースは、こんな感じです。

f:id:TonyTonyKun:20211110142722p:plain

Container Apps をデプロイする

Azure CLI を使って、Container Apps をデプロイします。
まだ Preview 中なので、拡張モジュールをインストールする必要があります。

$ az extension add --source https://workerappscliextension.blob.core.windows.net/azure-cli-extension/containerapp-0.2.0-py2.py3-none-any.whl
$ az provider register --namespace Microsoft.Web

あらかじめ ASP.NET Core Web アプリケーションの Docker Image を作っておいたので、Container Apps にデプロイします。
オプションの revisions-mode に multiple を指定する部分がポイントです。ちなみに In-place upgrade を行う場合は、single を指定します。

$ az containerapp create -n dapr-frontend -g <ResourceGroup Name> \
     -e <Environment Name> -i thara0402/dapr-frontend:0.1.0 \
     --ingress external --target-port 80 \
     --revisions-mode multiple --scale-rules ./deploy/httpscaler.json \
     --max-replicas 10 --min-replicas 1

httpscaler.json には、HTTP リクエスト数によるスケーリングルールを定義しました。

[{
    "name": "http-scaling-rule",
     "type": "http",
    "metadata": {
        "concurrentRequests": "10"
    }
}]

デプロイすると、dapr-frontend--h2qwxun という Revision が作成されました。

f:id:TonyTonyKun:20211110143014p:plain

dapr-frontend.blackcliff-bbde75ab.canadacentral.azurecontainerapps.io という FQDN が自動生成されました。
ASP.NET Core Web アプリケーションがブラウザで表示されることを確認できます。

f:id:TonyTonyKun:20211110143030p:plain

Blue-Green Deployments を行う

新しいバージョンをデプロイします。Staging へのデプロイを想定し、トラフィック制御では先ほど作成された Revision( dapr-frontend--h2qwxun)に「100」、latestに「0」を指定します。

$ az containerapp update -n dapr-frontend -g <ResourceGroup Name> \
     -i thara0402/dapr-frontend:0.2.0 \
     --traffic-weight dapr-frontend--h2qwxun=100,latest=0

デプロイすると、dapr-frontend--ugfijqv という Revision が追加されました。

f:id:TonyTonyKun:20211110143103p:plain

トラフィック制御が「0」の新しい Revision には、ユーザーに公開される FQDN とは異なる FQDN が割り当てられるので、リリース前のテストができます。
dapr-frontend--ugfijqv.blackcliff-bbde75ab.canadacentral.azurecontainerapps.io という Revision が含まれた FQDN が自動生成されました。

f:id:TonyTonyKun:20211110143137p:plain

リリース前のテストが完了したので、Swap します。

$ az containerapp update -n dapr-frontend -g <ResourceGroup Name> \
     --traffic-weight dapr-frontend--h2qwxun=0,latest=100

トラフィック制御で、「100」と「0」の指定が入れ替わったことを確認できます。

f:id:TonyTonyKun:20211110143206p:plain

ユーザーに公開される FQDN にアクセスすると、V2 に更新された ASP.NET Core Web アプリケーションが表示されます。

f:id:TonyTonyKun:20211110143239p:plain

最後に、旧バージョンの Revision をシャットダウンします。アクティブのままだと、課金対象となってしまいます。

$ az containerapp revision deactivate --app dapr-frontend -g <ResourceGroup Name> \
     --name dapr-frontend--h2qwxun

新バージョンの Revision のみになったことを確認できます。

f:id:TonyTonyKun:20211110145109p:plain

まとめ

Azure Container Apps で Blue-Green Deployments を試してみました。トラフィック制御の比率を変えることで AB テストやカナリアリリースもできます。GA までにはもう少し簡単にできるようになるといいですね。
Envoy によるトラフィック制御以外にも、KEDA によるスケーリングや Dapr によるサイドカーなどの面白い機能があるので、引き続き試していきたいと思います。