Azure Container Apps (ACA) でブルーグリーンデプロイする
こんにちは、@studio_meowtoon です。今回は、Azure Container Apps 環境でコンテナアプリをブルーグリーンデプロイする方法を紹介します。
目的
Windows 11 の Linux でクラウド開発します。
こちらから記事の一覧がご覧いただけます。
実現すること
Microsoft Azure Container Apps (ACA) にて、コンテナアプリのブルーグリーンデプロイを実践してみます。
この記事では、Docker Hub に公開するパブリックアクセス可能なカスタムコンテナイメージを使用しています。実際のシステム開発では、どのレジストリからコンテナイメージを取得するかは異なる場合がありますので、適宜ご確認ください。
技術トピック
ブルーグリーンデプロイとは?
こちらを展開してご覧いただけます。
ブルーグリーンデプロイメント
ブルーグリーンデプロイは、アプリケーションの新しいバージョンを本番環境にデプロイする際に、従来の運用方法とは異なり、新しいバージョンを本番環境に構築し、そこでアプリケーションをテストした後、従来の本番環境と切り替える方法です。
内容 |
---|
通常、ブルーの本番環境とグリーンの新しい本番環境を用意します。最初はブルーがアクティブな本番環境として稼働し、グリーンはアクティブではありません。 |
新しいバージョンのアプリケーションをグリーン環境にデプロイしてテストし、問題がなければトラフィックをグリーン環境に切り替えます。 |
これにより、ダウンタイムを最小限に抑え、システムの信頼性を高めることができます。 |
開発環境
- Windows 11 Home 22H2 を使用しています。
WSL の Ubuntu を操作していきますので macOS の方も参考にして頂けます。
WSL (Microsoft Store アプリ版) ※ こちらの関連記事からインストール方法をご確認いただけます
> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47
Ubuntu ※ こちらの関連記事からインストール方法をご確認いただけます
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.1 LTS
Release: 22.04
Java JDK ※ こちらの関連記事からインストール方法をご確認いただけます
$ java -version
openjdk version "11.0.18" 2023-01-17
OpenJDK Runtime Environment (build 11.0.18+10-post-Ubuntu-0ubuntu122.04)
OpenJDK 64-Bit Server VM (build 11.0.18+10-post-Ubuntu-0ubuntu122.04, mixed mode, sharing)
Maven ※ こちらの関連記事からインストール方法をご確認いただけます
$ mvn -version
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 11.0.18, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Docker ※ こちらの関連記事からインストール方法をご確認いただけます
$ docker --version
Docker version 23.0.1, build a5ee5b1
Azure CLI ※ こちらの関連記事からインストール方法をご確認いただけます
$ az --version
azure-cli 2.45.0
core 2.45.0
telemetry 1.0.8
この記事では基本的に Ubuntu のターミナルで操作を行います。Vim を使用してコピペする方法を初めて学ぶ人のために、以下の記事で手順を紹介しています。ぜひ挑戦してみてください。
ブルーグリーンデプロイする仕様
※ この記事での仕様となります。
識別するタグ | 内容 | エンドポイント | JSON レスポンス |
---|---|---|---|
v1 | 現用のサービス | /api/data | {"message":"Hello Blue!"} |
v2 | 更新するサービス | /api/data | {"message":"Hello Green!"} |
カスタムコンテナイメージ形式のアプリ
No | コンテナイメージ | 内容 |
---|---|---|
1 | app-hello-spring-boot:v1 | 現用のアプリケーション |
2 | app-hello-spring-boot:v2 | 更新するアプリケーション |
ブルーグリーンデプロイする手順
v1 アプリのコンテナイメージの作成
こちらを展開して手順をご覧いただけます。
Java アプリ作成
こちらの関連記事で手順がご確認いただけます。
https://qiita.com/studio_meowtoon/items/9c07e20b4124d8c5f972
プロジェクトフォルダに移動します。
※ ~/tmp/hello-spring-boot をプロジェクトフォルダとします。
$ cd ~/tmp/hello-spring-boot
v1 アプリのソースコードを作成します。
$ vim src/main/java/com/example/springboot/controller/HelloController.java
ファイルの内容
package com.example.springboot.controller;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/data")
public Map<String, String> getData() {
Map<String, String> map = Map.of("message", "Hello Blue!");
return map;
}
}
v1 アプリをビルドします。
$ mvn clean package
コンテナイメージ作成
こちらの関連記事で手順がご確認いただけます。
https://qiita.com/studio_meowtoon/items/9c07e20b4124d8c5f972
Docker デーモンを起動します。
$ sudo service docker start
* Starting Docker: docker [ OK ]
v1 アプリをコンテナイメージにビルドします。
$ docker build --no-cache -t app-hello-spring-boot:v1 .
v1 アプリのコンテナイメージを確認します。
$ docker images | grep app-hello-spring-boot
app-hello-spring-boot v1 c61d32929a90 58 seconds ago 390MB
コンテナイメージを Docker Hub にプッシュ
こちらの関連記事で手順がご確認いただけます。
https://qiita.com/studio_meowtoon/items/cbcfe1433885bae514db
Docker Hub にログインします。
$ docker login
Login Succeeded
v1 アプリのコンテナイメージにタグを付けます。
※ $USER の部分はご自身のコンテナリポジトリに読み替えて下さい。
$ docker tag app-hello-spring-boot:v1 $USER/app-hello-spring-boot:v1
Docker Hub に v1 アプリのコンテナイメージをプュシュします。
$ docker push $USER/app-hello-spring-boot:v1
ローカルでコンテナを起動させアプリの動作を確認します。
※ $USER の部分はご自身のコンテナリポジトリに読み替えて下さい。
$ docker run --rm --name app-local -p 8080:8080 $USER/app-hello-spring-boot:v1
$ curl http://localhost:8080/api/data/
{"message":"Hello Blue!"}
コンテナイメージをビルドし、Docker Hub にプッシュする際、キャッシュが不適切に使用され、ソースコードの変更が反映されないことがあります。この問題を解決するために、事前に Docker Hub にプッシュしたコンテナイメージをローカルで起動し、正しい動作を確認することをお勧めします。
ここまでの作業で v1 アプリのカスタムコンテナイメージが Docker Hub に公開できました。
v1 アプリを Azure Container Apps にデプロイ
ログイン
Azure CLI で Azure にログインします。
$ az login
こちらの関連記事で手順がご確認いただけます。
リソースグループ
リソースグループを作成します。
$ az group create \
--name rg-hello \
--location japaneast
コンテナ アプリ環境
こちらの関連記事で手順がご確認いただけます。
コンテナ アプリ環境を作成します。
※ Kubernetes 基盤の環境がベースとなっているので少し時間がかかります。
$ az containerapp env create \
--resource-group rg-hello \
--name cae-hello \
--location japaneast
コンテナ アプリ
v1 コンテナ アプリの作成とデプロイを行います。
※ $USER の部分はご自身のコンテナリポジトリに読み替えて下さい。
$ az containerapp create \
--resource-group rg-hello \
--environment cae-hello \
--name ca-hello-spring-boot \
--image $USER/app-hello-spring-boot:v1 \
--target-port 8080 \
--ingress 'external' \
--min-replicas 1 \
--revisions-mode multiple \
--revision-suffix v1
説明を開きます。
このコマンドは、Azure Container App インスタンスを作成するためのコマンドです。以下が各オプションが実行する内容です。
コマンド | 内容 |
---|---|
az containerapp create | Container Apps を作成する為のコマンドです。 |
オプション | 値 | 内容 |
---|---|---|
--resource-group | rg-hello | デプロイするリソースが属するリソースグループの名前を指定します。 |
--environment | cae-hello | Container Apps 環境の名前を指定します。 |
--name | ca-hello-spring-boot | Container Apps の名前を指定します。 |
--image | $USER/app-hello-spring-boot:v1 | 実行するコンテナイメージの名前を指定します。ここでは、前述の手順で Docker Hub にプッシュしたイメージ名を使用しています。 |
--target-port | 8080 | コンテナが公開するポートを指定します。ここでは、Spring Boot アプリケーションがポート 8080 で公開されているため、8080 を指定しています。 |
--ingress | 'external' | コンテナを外部からアクセスできるようにするためのイングレス設定を指定します。ここでは、外部からのアクセスを許可する 'external' を指定しています。 |
--min-replicas | 1 | 最小レプリカ数を指定します。ここでは、最小レプリカ数を 1 に設定しています。 |
--revisions-mode | multiple | リビジョンのモードを指定します。ここでは複数のリビジョンをサポートする multiple を指定しています。 |
--revision-suffix | v1 | 新しいリビジョンを作成するために、Container Apps の名前の末尾に付ける接尾辞を指定します。ここでは v1 を指定しています。 |
コンテナ アプリが作成されました。
https://ca-hello-spring-boot.jollyisland-XXXXXXX.japaneast.awesomecontainerapps.io/
別ターミナルから curl コマンドでアプリケーション URL を確認します。
$ curl https://ca-hello-spring-boot.jollyisland-XXXXXXX.japaneast.awesomecontainerapps.io/api/data
{"message":"Hello Blue!"}
ここまでの作業で v1 アプリのカスタムコンテナイメージが Azure Container Apps で起動できました。
Azure Portal の確認
[コンテナ アプリ] → [リビジョン管理] を確認します。
以下のように、コンテナアプリにリビジョンが付加されています。
ca-hello-spring-boot--v1
また、v1 アプリのリビジョン URL も確認することができます。
https://ca-hello-spring-boot--v1.jollyisland-XXXXXXX.japaneast.awesomecontainerapps.io/
v2 アプリのコンテナイメージの作成
こちらを展開して手順をご覧いただけます。
Java アプリ作成
v2 アプリのソースコードを作成します。
$ vim src/main/java/com/example/springboot/controller/HelloController.java
ファイルの内容
package com.example.springboot.controller;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/data")
public Map<String, String> getData() {
Map<String, String> map = Map.of("message", "Hello Green!");
return map;
}
}
v2 アプリをビルドします。
$ mvn clean package
コンテナイメージ作成
v2 アプリをコンテナイメージにビルドします。
$ docker build --no-cache -t app-hello-spring-boot:v2 .
v2 アプリのコンテナイメージを確認します。
$ docker images | grep app-hello-spring-boot
app-hello-spring-boot v1 c61d32929a90 58 seconds ago 390MB
app-hello-spring-boot v2 9d54d1056fb2 9 seconds ago 390MB
コンテナイメージを Docker Hub にプッシュ
v2 アプリのコンテナイメージにタグを付けます。
※ $USER の部分はご自身のコンテナリポジトリに読み替えて下さい。
$ docker tag app-hello-spring-boot:v2 $USER/app-hello-spring-boot:v2
Docker Hub に v2 アプリのコンテナイメージをプュシュします。
$ docker push $USER/app-hello-spring-boot:v2
ローカルでコンテナを起動させアプリの動作を確認します。
※ $USER の部分はご自身のコンテナリポジトリに読み替えて下さい。
$ docker run --rm --name app-local -p 8080:8080 $USER/app-hello-spring-boot:v2
$ curl http://localhost:8080/api/data/
{"message":"Hello Green!"}
ここまでの作業で v2 アプリのカスタムコンテナイメージが Docker Hub に公開できました。
v2 アプリを Azure Container Apps にデプロイ
コンテナ アプリ
コンテナ アプリのトラフィック分割を構成します。
※ 現状のリビジョンを 100% にします。
コンテナ アプリのトラフィック分割の構成を設定しない場合、更新するリビジョンのコンテナ アプリのトラフィックが 100% として設定されます。ご注意ください。
$ az containerapp ingress traffic set \
--resource-group rg-hello \
--name ca-hello-spring-boot \
--revision-weight ca-hello-spring-boot--v1=100
説明を開きます。
このコマンドは、Azure Container Apps のリビジョンごとにトラフィックのウェイトを設定するために使用されます。
コマンド | 内容 |
---|---|
az containerapp ingress traffic set | Container Apps のリビジョンごとにトラフィックのウェイトを設定する為のコマンドです。 |
オプション | 値 | 内容 |
---|---|---|
--resource-group | rg-hello | デプロイするリソースが属するリソースグループの名前を指定します。 |
--name | ca-hello-spring-boot | Container Apps の名前を指定します。 |
--revision-weight | ca-hello-spring-boot--v1=100 | ca-hello-spring-boot--v1 というリビジョンのトラフィックウェイトを 100 に設定しています。 |
※ 以下のようなレスポンスが返ります。
[
{
"latestRevision": true,
"weight": 0
},
{
"revisionName": "ca-hello-spring-boot--v1",
"weight": 100
}
]
v2 コンテナ アプリのデプロイを行います。
※ $USER の部分はご自身のコンテナリポジトリに読み替えて下さい。
$ az containerapp update \
--resource-group rg-hello \
--name ca-hello-spring-boot \
--image $USER/app-hello-spring-boot:v2 \
--revision-suffix v2
コンテナ アプリが更新されました。
別ターミナルから curl コマンドでアプリケーション URL を確認します。
$ curl https://ca-hello-spring-boot.jollyisland-XXXXXXX.japaneast.awesomecontainerapps.io/api/data
{"message":"Hello Blue!"}
コンテナ アプリのアプリケーション URLをリクエストすると、更新前の v1 アプリの出力が表示されます。
Azure Portal の確認
[コンテナ アプリ] → [リビジョン管理] を確認します。
以下のように、コンテナ アプリに新しいリビジョンが追加されています。
ca-hello-spring-boot--v2
新しいリビジョンはトラフィックが 0% になっています。この状態ではコンテナ アプリのアプリケーション URLは最新のリビジョンである v2 アプリに向いていません。
また、v2 アプリのリビジョン URL を確認することができます。
https://ca-hello-spring-boot--v2.jollyisland-XXXXXXX.japaneast.awesomecontainerapps.io/
別ターミナルから curl コマンドでリビジョン URL を確認します。
v2 アプリの出力が表示されます。
$ curl https://ca-hello-spring-boot--v2.jollyisland-XXXXXXX.japaneast.awesomecontainerapps.io/api/data
{"message":"Hello Green!"}
アプリを更新するために、v2 アプリを本番環境にデプロイすることができました。また、実際にリリースする前にリビジョン URL を利用して新しいリビジョンの動作確認を行うことができます。これは、ブルーグリーンデプロイの目的の1つです。
新しいリビジョンへの切り替え
v1 アプリから、v2 アプリに切り替えます。
※ v1 リビジョンから、v2 リビジョンへリビジョンを切り替えます。
$ az containerapp ingress traffic set \
--resource-group rg-hello \
--name ca-hello-spring-boot \
--revision-weight ca-hello-spring-boot--v1=0 ca-hello-spring-boot--v2=100
※ 以下のようなレスポンスが返ります。
[
{
"latestRevision": true,
"weight": 0
},
{
"revisionName": "ca-hello-spring-boot--v1",
"weight": 0
},
{
"revisionName": "ca-hello-spring-boot--v2",
"weight": 100
}
]
リビジョンが切り替わりました。
別ターミナルから curl コマンドでアプリケーション URL を確認します。
$ curl https://ca-hello-spring-boot.jollyisland-XXXXXXX.japaneast.awesomecontainerapps.io/api/data
{"message":"Hello Green!"}
コンテナ アプリのアプリケーション URLをリクエストして、更新後の v2 アプリの出力が表示されました。本番環境へのデプロイ作業が完了しました。※ この記事での本番環境となります。
Azure Portal の確認
[コンテナ アプリ] → [リビジョン管理] を確認します。
v2 リビジョン側のトラフィックが 100% になっていることを確認できます。
トラブル発生時の切り戻し
サービスを最新バージョンにデプロイした後にトラブルが発生した場合、以前に正常に動作していたリビジョンに戻す必要があります。これは、ブルーグリーンデプロイの目的の1つです。
v2 アプリから、v1 アプリに切り戻します。
※ リビジョンを切り替えます。
$ az containerapp ingress traffic set \
--resource-group rg-hello \
--name ca-hello-spring-boot \
--revision-weight ca-hello-spring-boot--v1=100 ca-hello-spring-boot--v2=0
別ターミナルから curl コマンドでアプリケーション URL を確認します。
$ curl https://ca-hello-spring-boot.jollyisland-XXXXXXX.japaneast.awesomecontainerapps.io/api/data
{"message":"Hello Blue!"}
コンテナ アプリのアプリケーション URLをリクエストして、更新前の v1 アプリの出力が表示されました。
Azure Portal の確認
[コンテナ アプリ] → [リビジョン管理] を確認します。
再度 v1 リビジョン側のトラフィックが 100% に設定され、切り戻せたことを確認できます。
デプロイ後の注意点
コンテナ アプリのリビジョンがアクティブ状態だと、利用に応じて課金されます。新しいリビジョンが正常に動作し、安定した状態になった後に、元々の古いリビジョンのアクティブ状態を解除することができます。これにより、必要以上に課金されることを防ぐことができます。
$ az containerapp revision deactivate \
--resource-group rg-hello \
--name ca-hello-spring-boot \
--revision ca-hello-spring-boot--v1
説明を開きます。
このコマンドは、Azure Container Apps のリビジョンを非アクティブ化するために使用されます。
コマンド | 内容 |
---|---|
az containerapp revision deactivate | Container Apps のリビジョンを非アクティブ化する為のコマンドです。 |
オプション | 値 | 内容 |
---|---|---|
--resource-group | rg-hello | デプロイするリソースが属するリソースグループの名前を指定します。 |
--name | ca-hello-spring-boot | Container Apps の名前を指定します。 |
--revision | ca-hello-spring-boot--v1 | ca-hello-spring-boot--v1 というリビジョンを非アクティブに設定しています。 |
Azure Portal の確認
[コンテナ アプリ] → [リビジョン管理] を確認します。
v1 リビジョンが非アクティブに設定されたことを確認できました。
まとめ
Azure Container Apps 環境で、ブルーグリーンデプロイを実践することができました。
Maven、Docker、Azure CLI を使って、Spring Boot アプリの開発からコンテナイメージの作成、Azure 環境へのデプロイまで、すべてをターミナルから行うことができます。このように、クラウドでのシステム開発に必要なスキルや理解を深めることができます。初めての人でも簡単に手順を追うことができるので、ぜひ挑戦してみてください。
どうでしたか? 検証目的の Azure Container Apps 環境で、コンテナアプリのブルーグリーンデプロイを手軽に体験することができます。ぜひお試しください。今後も Azure の開発環境などを紹介していきますので、ぜひお楽しみにしてください。
推奨コンテンツ