Azure Spring Apps (ASA) でブルーグリーンデプロイする

# Azure Spring Apps (ASA) でブルーグリーンデプロイする

こんにちは、@studio_meowtoon です。今回は、Azure Spring Apps 環境で JAR ファイル形式のアプリをブルーグリーンデプロイする方法を紹介します。
![spring-boot_on_azure-spring-apps.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/122bce21-b77b-90a6-54d8-4a8deaef68fd.png)

## 目的

Windows 11 の Linux でクラウド開発します。

こちらから記事の一覧がご覧いただけます。

https://qiita.com/studio_meowtoon/items/6119ab05d8b13527efd8 

## 実現すること

[Microsoft Azure Spring Apps (ASA)](https://learn.microsoft.com/ja-jp/azure/spring-apps/overview) にて、JAR ファイル形式のアプリのブルーグリーンデプロイを実践してみます。

## 技術トピック

### ブルーグリーンデプロイとは？  

<details>
<summary>こちらを展開してご覧いただけます。</summary>

### [ブルーグリーンデプロイメント](https://martinfowler.com/bliki/BlueGreenDeployment.html)

:::note info
ブルーグリーンデプロイは、アプリケーションの新しいバージョンを本番環境にデプロイする際に、従来の運用方法とは異なり、新しいバージョンを本番環境に構築し、そこでアプリケーションをテストした後、従来の本番環境と切り替える方法です。

|内容|
|:--|
通常、ブルーの本番環境とグリーンの新しい本番環境を用意します。最初はブルーがアクティブな本番環境として稼働し、グリーンはアクティブではありません。|
|新しいバージョンのアプリケーションをグリーン環境にデプロイしてテストし、問題がなければトラフィックをグリーン環境に切り替えます。|
|これにより、ダウンタイムを最小限に抑え、システムの信頼性を高めることができます。|

:::

</details>

## 開発環境

+ Windows 11 Home 22H2 を使用しています。  

:::note info
[WSL](https://learn.microsoft.com/ja-jp/windows/wsl/about) の Ubuntu を操作していきますので macOS の方も参考にして頂けます。  
:::

<details>

WSL (Microsoft Store アプリ版) [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/2aaa6579cb8e4fa1d874)

```sh
> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47
```

Ubuntu [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/2aaa6579cb8e4fa1d874)

```sh
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04
```

Java JDK [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/4d11e94a2389758759cd)

```sh
$ 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 [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/f4cdc4039158153365fb)

```sh
$ 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
```

</details>

:::note warn
この記事では基本的に **Ubuntu のターミナルで操作**を行います。**Vim を使用してコピペする方法**を初めて学ぶ人のために、以下の記事で手順を紹介しています。ぜひ挑戦してみてください。
:::

https://qiita.com/studio_meowtoon/items/7771ad48676926e41463

## ブルーグリーンデプロイする仕様
※ この記事での仕様となります。

|識別するタグ|内容|エンドポイント|JSON レスポンス|
|:--|:--|:--|:--|
|v1|現用のサービス|/api/data|{"message":"Hello **Blue**!"}|
|v2|更新するサービス|/api/data|{"message":"Hello **Green**!"}|

**JAR ファイル形式のアプリ**

|No|ファイル|内容|
|:--|:--|:--|
|1|app.jar|現用のアプリケーション|
|2|app.jar|更新するアプリケーション|

## ブルーグリーンデプロイする手順

### v1 アプリの JAR ファイル作成

<details>
<summary>こちらを展開して手順をご覧いただけます。</summary>

#### Java アプリ作成

こちらの関連記事で手順がご確認いただけます。 

https://qiita.com/studio_meowtoon/items/37ac0082a3228e4de570

プロジェクトフォルダに移動します。  
※ ~/tmp/hello-spring-boot をプロジェクトフォルダとします。    

```sh
$ cd ~/tmp/hello-spring-boot
```

v1 アプリのソースコードを作成します。

```sh
$ vim src/main/java/com/example/springboot/controller/HelloController.java
```

ファイルの内容

```java: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 アプリをビルドします。

```sh
$ mvn clean package
```

</details>

:::note info
ここまでの作業で **v1 アプリとして、JAR ファイル**が作成できました。
:::

### v1 アプリを Azure Spring Apps にデプロイ

#### ログイン

Azure CLI で Azure にログインします。  

```sh
$ az login
```

こちらの関連記事で手順がご確認いただけます。 

https://qiita.com/studio_meowtoon/items/9721041f9e6e3e987cf0

#### リソースグループ

リソースグループを作成します。

```sh:Microsoft.Resources/resourceGroups
$ az group create \
    --name rg-hello \
    --location japaneast
```

#### Spring Apps サービスインインスタンス

こちらの関連記事で手順がご確認いただけます。 

https://qiita.com/studio_meowtoon/items/7a5c2cbb4d1267e110ba

Spring Apps サービスインスタンスを作成します。
※ Kubernetes 基盤の環境がベースとなっているので少し時間がかかります。  

:::note alert
--sku **Standard** からブルーグリーンデプロイに対応しています。 
:::

```sh:Microsoft.AppPlatform/Spring
$ az spring create \
    --resource-group rg-hello \
    --name aps-hello \
    --location japaneast \
    --sku Standard
```

#### Spring Apps アプリ

v1 Spring Apps アプリの作成を行います。 

```sh:Microsoft.AppPlatform/Spring/apps
$ az spring app create \
    --resource-group rg-hello \
    --service aps-hello \
    --name sap-hello-spring-boot \
    --deployment-name sap-hello-spring-boot--v1 \
    --runtime-version Java_11 \
    --assign-endpoint true
```

<details>
<summary>説明を開きます。</summary>

:::note info
このコマンドは、Spring Apps アプリを作成しています。

|コマンド|内容|
|:--|:--|
|az spring app create|Spring Apps アプリを作成するためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--resource-group|rg-hello|Spring Apps アプリを作成するリソースグループの名前を指定します。|
|--service|aps-hello|Spring Apps アプリを作成する、Spring Apps サービスインスタンスの名前を指定します。|
|--name|sap-hello-spring-boot|Spring Apps アプリの名前を指定します。|
|--deployment-name|sap-hello-spring-boot--v1|Spring Apps アプリのデプロイの名前を指定します。|
|--runtime-version|Java_11|Spring Apps アプリを Java 11 ランタイムで実行するように設定します。|
|--assign-endpoint|true|true の場合は直接アクセス用のエンドポイント URL を割り当てます。|
:::

</details>

v1 Spring Apps アプリをデプロイします。

```sh:Microsoft.AppPlatform/Spring/apps/deployments
$ az spring app deploy \
    --resource-group rg-hello \
    --service aps-hello \
    --name sap-hello-spring-boot \
    --deployment sap-hello-spring-boot--v1 \
    --artifact-path target/app.jar
```

<details>
<summary>説明を開きます。</summary>

:::note info
このコマンドは、Spring Apps アプリをデプロイしています。

|コマンド|内容|
|:--|:--|
|az spring app deploy|Spring Apps アプリをデプロイするためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--resource-group|rg-hello|Spring Apps アプリを作成するリソースグループの名前を指定します。|
|--service|aps-hello|Spring Apps アプリを作成する、Spring Apps サービスインスタンスの名前を指定します。|
|--name|sap-hello-spring-boot|Spring Apps アプリの名前を指定します。|
|--deployment|sap-hello-spring-boot--v1|Spring Apps アプリのデプロイの名前を指定します。|
|--artifact-path|target/app.jar|Spring Apps アプリにデプロイするコードの場所を指定します。|
:::

</details>

デプロイ成功後、以下のURLでアクセス可能です。

```sh
https://<service-name>-<app-name>.azuremicroservices.io
```

別ターミナルから curl コマンドで**URL** を確認します。

```sh
$ curl https://aps-hello-sap-hello-spring-boot.awesomemicroservices.io/api/data
{"message":"Hello Blue!"}
```

#### Azure Portal の確認

[アプリ] → [デプロイ] を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/408aa06a-e079-14bc-47c9-688e57228dc6.png)
v1 アプリが、**実稼働**と設定されていることが確認できます。

:::note info
ここまでの作業で **v1 アプリ**の Azure Spring Apps への**デプロイが完了**しました。
:::

### v2 アプリの JAR ファイル作成

<details>
<summary>こちらを展開して手順をご覧いただけます。</summary>

#### Java アプリ作成

v2 アプリのソースコードを作成します。

```sh
$ vim src/main/java/com/example/springboot/controller/HelloController.java
```

ファイルの内容

```java: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 アプリをビルドします。

```sh
$ mvn clean package
```

</details>

:::note info
ここまでの作業で **v2 アプリとして、JAR ファイル**が作成できました。
:::

### v2 アプリを Azure Spring Apps にデプロイ

#### Spring Apps アプリ

v2 Spring Apps アプリのステージング環境のデプロイを作成します。

```sh
$ az spring app deployment create \
    --resource-group rg-hello \
    --service aps-hello \
    --app sap-hello-spring-boot \
    --name sap-hello-spring-boot--v2 \
    --runtime-version Java_11 \
    --artifact-path target/app.jar
```

<details>
<summary>説明を開きます。</summary>

:::note info
このコマンドは、Spring Apps アプリのステージング環境のデプロイを作成しています。

|コマンド|内容|
|:--|:--|
|az spring app deployment create|Spring Apps アプリのステージング環境のデプロイを作成するためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--resource-group|rg-hello|Spring Apps アプリを作成するリソースグループの名前を指定します。|
|--service|aps-hello|Spring Apps アプリを作成する、Spring Apps サービスインスタンスの名前を指定します。|
|--app|sap-hello-spring-boot|Spring Apps アプリの名前を指定します。|
|--name|sap-hello-spring-boot--v1|Spring Apps アプリのデプロイの名前を指定します。|
|--runtime-version|Java_11|Spring Apps アプリを Java 11 ランタイムで実行するように設定します。|
|--artifact-path|target/app.jar|Spring Apps アプリにデプロイするコードの場所を指定します。|
:::

</details>

別ターミナルから curl コマンドで**URL** を確認します。

```sh
$ curl https://aps-hello-sap-hello-spring-boot.awesomemicroservices.io/api/data
{"message":"Hello Blue!"}
```

:::note warn
アプリの**URL**をリクエストすると、更新前の **v1 アプリの出力が表示**されます。
:::

#### Azure Portal の確認

[アプリ] → [デプロイ] を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/90a11cef-6149-a18c-83ce-ff8a5539f29f.png)
v2 アプリは、**ステージング**と設定されていることが確認できます。

別ターミナルから curl コマンドで**テスト エンドポイント**を確認します。

```sh
$ curl https://primary:4Fk5UKl9Bch3GbFFzXoLtzSRPpURANQ5Z2oylLldyp9OQZ4FplVxcLPqRpOxnJ6L@aps-hello.test.awesomemicroservices.io/sap-hello-spring-boot/sap-hello-spring-boot--v2/api/data
{"message":"Hello Green!"}
```

:::note info
アプリを更新するために、v2 アプリを本番環境に**ステージング**としてデプロイすることができました。また、実際にリリースする前に**テスト エンドポイント** を利用して**動作確認**を行うことができます。これは、**ブルーグリーンデプロイの目的の1つ**です。
:::

### 新しいデプロイへの切り替え

ステージングを実環境に切り替えます。

```sh
$ az spring app set-deployment \
    --resource-group rg-hello \
    --service aps-hello \
    --name sap-hello-spring-boot \
    --deployment sap-hello-spring-boot--v2
```

<details>
<summary>説明を開きます。</summary>

:::note info
このコマンドは、Spring Apps アプリの運用環境のデプロイを設定しています。

|コマンド|内容|
|:--|:--|
|az spring app set-deployment|Spring Apps アプリの運用環境のデプロイを設定するためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--resource-group|rg-hello|Spring Apps アプリを作成するリソースグループの名前を指定します。|
|--service|aps-hello|Spring Apps アプリを作成する、Spring Apps サービスインスタンスの名前を指定します。|
|--name|sap-hello-spring-boot|Spring Apps アプリの名前を指定します。|
|--deployment|sap-hello-spring-boot--v2|Spring Apps アプリのデプロイの名前を指定します。|
:::

</details>

デプロイが切り替わりました。

別ターミナルから curl コマンドで**URL** を確認します。

```sh
$ curl https://aps-hello-sap-hello-spring-boot.awesomemicroservices.io/api/data
{"message":"Hello Green!"}
```

:::note info
アプリの**URL**をリクエストすると、更新後の **v2 アプリの出力が表示**されます。**本番環境へのデプロイ作業が完了**しました。※ この記事での本番環境となります。
:::

#### Azure Portal の確認

[アプリ] → [デプロイ] を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/9e832395-045d-fc53-4b65-65af297e1a30.png)
v2 アプリが**実稼働**と設定されていることが確認できます。

### トラブル発生時の切り戻し

:::note alert
サービスを最新バージョンにデプロイした後に**トラブルが発生**した場合、以前に**正常に動作**していた**デプロイに戻す**必要があります。これは、**ブルーグリーンデプロイの目的の1つ**です。
:::

v2 アプリから、v1 アプリに切り戻します。
※ デプロイを切り替えます。  

```sh
$ az spring app set-deployment \
    --resource-group rg-hello \
    --service aps-hello \
    --name sap-hello-spring-boot \
    --deployment sap-hello-spring-boot--v1
```

別ターミナルから curl コマンドで**URL** を確認します。

```sh
$ curl https://aps-hello-sap-hello-spring-boot.awesomemicroservices.io/api/data
{"message":"Hello Blue!"}
```

アプリの**URL**をリクエストして、更新前の **v1 アプリの出力が表示**されました。

#### Azure Portal の確認

[アプリ] → [デプロイ] を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/10bb991c-b0c8-2f75-9ead-80b778ca6b51.png)
再度 v1 デプロイが**実稼働**に設定され、**切り戻せた**ことを確認できます。

### デプロイ後の注意点

:::note alert
Spring Apps アプリは**2つのデプロイしか保持できません**。さらに最新のデプロイを反映させるためには古いデプロイを削除する必要があります。

**App sap-hello-spring-boot may have at most 2 deployments, currently 2**
:::

Spring Apps アプリの古いデプロイを削除します。 

```sh
$ az spring app deployment delete \
    --resource-group rg-hello \
    --service aps-hello \
    --app sap-hello-spring-boot \
    --name sap-hello-spring-boot--v1
```

<details>
<summary>説明を開きます。</summary>

:::note info
このコマンドは、Spring Apps アプリのデプロイを削除しています。

|コマンド|内容|
|:--|:--|
|az spring app deployment delete|Spring Apps アプリのデプロイを削除するためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--resource-group|rg-hello|Spring Apps アプリを作成するリソースグループの名前を指定します。|
|--service|aps-hello|Spring Apps アプリを作成する、Spring Apps サービスインスタンスの名前を指定します。|
|--app|sap-hello-spring-boot|Spring Apps アプリの名前を指定します。|
|--name|sap-hello-spring-boot--v1|Spring Apps アプリのデプロイの名前を指定します。|
:::

</details>

#### Azure Portal の確認

[アプリ] → [デプロイ] を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/ff41abf7-7534-d1bb-b78e-7ecafc76cf5c.png)
v1 デプロイが削除されたことを確認できました。

## まとめ

Azure Spring Apps 環境で、ブルーグリーンデプロイを実践することができました。

:::note warn
**Maven**、**Azure CLI** を使って、Spring Boot の JAR ファイル形式アプリの作成、Azure 環境へのデプロイまで、**すべてをターミナルから行うことができます**。このように、クラウドでのシステム開発に必要なスキルや理解を深めることができます。初めての人でも簡単に手順を追うことができるので、ぜひ挑戦してみてください。
:::

どうでしたか？ 検証目的の Azure Spring Apps 環境で、JAR ファイル形式アプリのブルーグリーンデプロイを手軽に体験することができます。ぜひお試しください。今後も Azure の開発環境などを紹介していきますので、ぜひお楽しみにしてください。

## 推奨コンテンツ

https://qiita.com/studio_meowtoon/items/12bd250b02f8e37e3031