【Azure】Web App for ContainerのBlue/GreenデプロイをAzure Pipelinesで実装してみた

## 概要

本記事では、Azure Pipelinesを用いてWeb App for ContainerでのBlue/Greenデプロイを実装した方法について記載します。

Azureでコンテナアプリケーションを公開する際は、Web App for ContainerやAzure Kubernetes Serviceなどのサービスを利用する方法があります。
これらのサービスを利用する場合、コンテナアプリケーションのバージョンアップ方法についても検討する必要がありますが、Web App for Containerにはリリース時のダウンタイムをきわめて短くできる仕組みがあります。この仕組みとAzure Pipelinesを組み合わせることでCD（Continuous Deployment）を実現できます。

### Blue/Greenデプロイとは

理想的なCI/CDには、リリースのコストを小さくして開発のサイクルを素早く回していくことが求められます。
リリースのコストとはアプリケーションのデプロイにかかる手間やその際に生じるダウンタイムのことであり、このダウンタイムを限りなく短くするために用いられる主な手法の1つがBlue/Greenデプロイになります。

大まかなBlue/Greenデプロイの操作としては、運用中の本番環境とは異なる本番環境と同等の環境を用意し、その環境に事前にアプリケーションをデプロイしてからエンドポイントのアクセス先を切り替えるということを行います。
これにより、外部からは瞬時にリリースが行われたかのように見せることができます。

Blue/Greenデプロイに関する詳細な情報については、さまざまなサイトで記述されているのでご確認ください

- [ブルーグリーン・デプロイメントとは](https://www.redhat.com/ja/topics/devops/what-is-blue-green-deployment)
- [3分でわかる ブルーグリーンデプロイメント](https://xtech.nikkei.com/atcl/nxt/keyword/18/00002/070800077/#:~:text=%E3%83%96%E3%83%AB%E3%83%BC%E3%82%B0%E3%83%AA%E3%83%BC%E3%83%B3%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%83%A1%E3%83%B3%E3%83%88%E3%81%A8%E3%81%AF,%E3%81%93%E3%81%AE%E9%81%8B%E7%94%A8%E3%82%92%E6%8E%A1%E7%94%A8%E3%81%99%E3%82%8B%E3%80%82)
- [Blue-Green Deploymentにおける注意点](https://dev.classmethod.jp/articles/operation-blue-green-deployment/)

### Web App for ContainerでのBlue/Greenデプロイの実現

Web App for Containerにはスロットという概念があります。このスロットにコンテナイメージをデプロイすることでアプリケーションをリリースします。このスロットを2つ用意して中身を入れ替えることでBlue/Greenデプロイを実現することができます。スロットの中身を入れ替えることをスワップといいます。

以下はAzureポータル上で見える挙動の抽象的なイメージ図となります。

![slot_swap.drawio_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1826890/74d51949-520f-166b-b022-7ceb6978c3b6.png)

この方法を採用することで、ほぼダウンタイムゼロのアプリケーションのリリースが可能となります。また、切り替え後の古い環境も残るため、新しいアプリケーションのリリース後に古いアプリケーションにロールバックすることも可能です。

スロットのスワップを使ったBlue/GreenデプロイをAzure Pipelinesで自動化することでCI/CDに組み込むことができます。本記事では、広く一般的に採用されているBlue/Greenデプロイを用いたAzure Pipelinesの実装方法について紹介します。

## 前提

Azure PipelinesでBlue/Greenデプロイを実装するには、以下の項目が前提事項となります。

- Azure DevOpsが使用できること
- [Azure Resource Managerサービス接続](https://docs.microsoft.com/ja-jp/azure/devops/pipelines/library/connect-to-azure?view=azure-devops)が作成されていること
- デプロイ対象のコンテナイメージがパブリックのリポジトリまたはAzure Container Registryに格納されていること
- デプロイ対象のWeb App for Containerおよび運用Slotを含む2つ以上のSlotが作成されていること

## Azure PipelinesでのBlue/Greenデプロイの実装

Azure PipelinesでのBlue/Greenデプロイの具体的な実装方法について記載します。

まず、Web App for Containerの運用スロットとは別に作成したステージングスロットに、対象のコンテナイメージをデプロイします。その後、運用スロットをステージングスロットをスワップすることでBlue/Greenデプロイを実現します。

ここではAzure Pipelinesに以下の2つのステージを定義しています。

| ステージ名 | 説明                                                         |
| ---------- | ------------------------------------------------------------ |
| Deploy     | 任意のコンテナイメージからステージングスロットへデプロイする |
| Swap       | ステージングスロットと運用スロットをスワップする             |

本記事では、パイプラインのトリガー設定等についての説明は割愛します。
要件に応じて、[パイプラインをトリガーするイベント](https://docs.microsoft.com/ja-jp/azure/devops/pipelines/build/triggers?view=azure-devops)を指定してください。

```yaml:azure-pipelines.yml
stages:
  - stage: Deploy
    displayName: 'Deploy App to Slot'
    jobs:
      - job:
        steps:
        - task: AzureWebAppContainer@1
          inputs:
            azureSubscription: 'example-service-connection'
            appName: 'example-webapp'
            imageName: 'exmpale/example:latest'
            deployToSlotOrASE: true
            resourceGroupName: 'example-resource-group'
            slotName: 'staging'
            appSettings: '-KEY VALUE'
  - stage: Swap
    displayName: 'Slot Swap'
    jobs:
      - job:
        steps:
        - task: AzureAppServiceManage@0
          inputs:
            azureSubscription: 'example-service-connection'
            WebAppName: 'example-webapp'
            ResourceGroupName: 'example-resource-group'
            SourceSlot: 'staging'
            SwapWithProduction: true

```

### パラメータの説明

`azureSubscription`
事前に作成したAzure Resource Managerサービス接続の`Connection Name`を指定してください。

`appName`, `WebAppName`
事前に作成したWeb App for Containerの名前を指定してください。

`imageName`
デプロイ対象のコンテナイメージおよびタグを指定してください。

`deployToSlotOrASE`
既存のデプロイスロットにデプロイする場合は、`true`に指定する必要があります。
ステージングスロットを事前に作成している想定なので、ここでは`true`で指定してください。

`resourceGroupName`
Web App for Containerを作成しているリソースグループ名を指定してください。

`slotName`, `SourceSlot`
事前に作成しているステージングスロットの名前を指定してください。

`appSettings`
デプロイ対象のコンテナアプリケーションに設定する環境変数を`-key value`の構文で指定します。

`SwapWithProduction`
ステージングスロットを運用スロットとスワップする場合は、このパラメータを`true`で指定します。
運用スロット以外のスロットとスワップする場合（`SwapWithProduction`を`false`で指定する場合）は`TargetSlot`でスワップ先のスロット名を指定する必要があります。

各パラメータの詳細については、以下の公式ドキュメントをご参照ください。

- [Azure Web App for Container task](https://docs.microsoft.com/ja-jp/azure/devops/pipelines/tasks/deploy/azure-rm-web-app-containers?view=azure-devops)
- [Azure App Service Manage task](https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/azure-app-service-manage?view=azure-devops)

### 補足

パイプライン定義ファイルが作成できたら、Azure DevOpsからパイプラインを作成する必要があります。パイプラインの作成方法については、[最初のパイプラインの作成](https://docs.microsoft.com/ja-jp/azure/devops/pipelines/create-first-pipeline?view=azure-devops&tabs=java%2Ctfs-2018-2%2Cbrowser)を参考にしてください。

## まとめ

今回はAzure Pipelinesを使ってBlue/Greenデプロイを実装する機会があったのでまとめてみました。
Blue/Geenデプロイに限らずデプロイ方法にはそれぞれメリット/デメリットがあるので、CICDを実装する際には他の方法も含めて検討するのがよいでしょう。