ROMANCE DAWN for the new world

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

キャンプ黄金崎に行ってきました

梅雨入り間近ではありましたが、ゆるキャン△の聖地であるキャンプ黄金崎に行ってきました。
前回は、本栖湖の畔にある浩庵キャンプ場に行きました。
gooner.hateblo.jp

沼津港

黄金崎の近くには大きなスーパーがないので、キャンプの食材を買い出しするため、沼津に立ち寄りました。


沼津港では、新鮮な地魚を使った食事を楽しめますが、キャンプ飯に備えて軽めの朝食として、生しらす丼を食べました。


買い出しは、フードストアあおきの沼津店に行きました。キャンプ向けの食材が充実しているという感じではないので、普通に肉や野菜、お酒などを買いました。

黄金崎公園

沼津から1時間ちょっとで、黄金崎公園に到着しました。キャンプ場のチェックインは 13 時からで少し早く着いたので、馬ロックに行きました。

見事に馬でしたね。そして、海も綺麗でした。




キャンプ黄金崎

キャンプ黄金崎は、テントサイトの事前予約が必要です。海側と山側のサイトがありますが、今回は海側のテントサイトAを予約しました。
前回は富士山の見えるキャンプ場でしたが、海の見える景色もいいですね。

2~3人用のテントを2つ張りたかったので A-2 と A-3 のサイトを予約しましたが、A-3 だけでも大丈夫な広さでした。
地面は固めでペグを打つのに苦戦したので、ペグハンマーが欲しくなった。

ゆるキャン△にも出てきた見覚えのある風景です。駐車場は少し離れていますが、他キャンパーが少なかったのでテントサイトの横に車を停めさせてくれました。


キャンプ飯の写真は、結局1枚しか撮らなかったですが、肉、椎茸、ハマグリ、アスパラなどを焼きました。パイナップルは美味しかった。フライパンでアヒージョも作りました。
伊豆キャン△だし干物とかも焼きたかったけど、メタル賽銭箱なのでサイズ的に厳しそうなので断念。

日が暮れるとこんな感じ。なでしこと恵那が夜眠れなくて会話していた場所ですね。ゆるキャン△のなかでも、あのシーンはけっこう好きです。

この日は夜中から雨の予報だったので、デイキャンプに変更して空いていた2~3人用のコテージに宿泊しました。強い雨と風を凌ぐことができて良かったです。


禅の湯

天気が良ければ、堂ヶ島のトンボロや海の見える露天風呂のある温泉とかに行きたかったですが、翌日も雨だったのでとある目的のため河津方面に向かいました。

河津に向かう途中で立ち寄り温泉の禅の湯に行きました。露天風呂や岩盤浴などもあって、くつろげる温泉でした。
改装のため休業中だったことを知らずに訪れたにもかかわらず、私たちのために開けてくれて、ありがとうございました。また河津に来たら、必ず立ち寄ります。

zen-no-yu.com

わさび園 かどや

とある目的というは、河津にある「わさび園 かどや」でわさび丼を食べることです。孤独のグルメに2回も登場したお店です。
tabelog.com

わさび丼を注文すると、わさびとおろし板を渡されるので自分ですります。

おろしたわさびをごはんの真ん中にのせ、まわりの鰹節に醤油をかけて、少しずつわさびを崩しながら食べます。わさびの風味が消えてしまうので、わさびに直接醤油をかけてはいけません。

こんなにシンプルな組み合わせなのに、めちゃくちゃ旨い。混み合うので追加注文ができなかったので、次回は最初から2杯注文したい。

Azure Container Apps の Revision Label を使って Staging の URL を固定する

Azure Container Apps の Revision は、Web Apps の Deployment Slot とは異なり、新しい Docker Image をデプロイするたびに Revision が追加されます。
Revision Label を使うことで、Staging の URL を固定できるかどうか試してみました。
docs.microsoft.com

Container Apps をデプロイする

前回の記事と同様の手順で、Bicep で Container Apps をデプロイします。
gooner.hateblo.jp

Staging へのデプロイを想定し、新しいバージョンをデプロイしました。dapr-frontend--v2 という Revision が追加されました。

新しい Revision には、Container Apps とは別の Revison URL が割り当てられるので、リリース前のテストができます。

この Revision 毎に割り当てられる URL を固定させるため、Revison Label に staging をセットします。

Revision URL とは別に、Label URL が割り当てられます。


Revision を Swap する

Revision の traffic パーセンテージを Swap します。

$ az containerapp ingress traffic set -n dapr-frontend -g <ResourceGroup Name> \
     --revision-weight dapr-frontend--v1=0 latest=100

Swap が完了したら、Revison Label を dapr-frontend--v2 から dapr-frontend--v1 に付け替えます。

最後に、旧バージョンの Revision をシャットダウンします。

$ az containerapp revision deactivate -n dapr-frontend -g <ResourceGroup Name> --revision dapr-frontend--v1

あとは、この繰り返しで。

まとめ

Azure Container Apps の Revision Label を使って Staging の URL を固定してみました。
ひと手間かかりますが、Web Apps の Deployment Slot に近い運用を実現できそうです。

本当は、Azure CLI で Revision Label を追加削除したかったのですが、挙動が怪しかったので Azure Portal を使いました。
具体的には、traffic パーセンテージが 0% の Revison に対して、Revison Label を追加できません。

$ az containerapp revision label add -n dapr-frontend -g <ResourceGroup Name> --label staging --revision dapr-frontend--v2
Please specify a revision name with an associated traffic weight.

GitHub の Issues に報告したところ、次のリリースで修正されるようです。
github.com

// 追記:2022/06/15
Azure CLI の Ver.0.3.6 で修正が完了しました。--no-prompt オプションを指定することで、Revision Label を削除追加せずとも、強制的に付け替えできます。

// Revision Label(staging) を新バージョンにセット
az containerapp revision label add -n dapr-frontend -g <ResourceGroup Name> --label staging --revision dapr-frontend--v2

// スワップ
az containerapp ingress traffic set -n dapr-frontend -g <ResourceGroup Name> --revision-weight dapr-frontend--v1=0 latest=100

// Revision Label(staging) を付け替え
az containerapp revision label add -n dapr-frontend -g <ResourceGroup Name> --label staging --revision dapr-frontend--v1 --no-prompt

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

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 です。

Microsoft Docs から引用

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