ArgoRolloutsによるBlue/Greenデプロイの動作検証メモ

# 1. はじめに
ArgoCDでBlue/Greenデプロイを実現するのはかなり面倒だなと感じていました。
なにかいい方法がないかを探したところArgo Rolloutsがどうやら便利そうとのことで、実際に自分のお遊び環境で動作検証てみました。
これはその検証内容と実施手順の備忘メモとなります。

# 2. kubernetes環境の準備
簡単にArgo Rolloutsの使い方を理解するためなので、minikubeを利用します。
いきなりArgo Rolloutを試すのではなく、まずはminikube上でアプリを動かします。

## 2.1 マニフェストファイルの準備
今回は自作のWebアプリのコンテナイメージを検証に利用します。

用意したDockerfileを`docker build`でビルドし、ローカルのレジストリにイメージを格納します。
格納したイメージはminikubeで利用できないため、`minikube image load`コマンドでイメージをminikubeに持ち込みます。
```bash
$ minikube image load blue-green-sample:latest
$ minikube image ls
  # 省略
docker.io/library/blue-green-sample:latest
```

次にDeploymentとServiceのマニフェストファイルを準備します。
ローカルイメージを利用する場合は、Deploymentの`ImagePullPokicy`を`IfNotPresent`にする必要があるので注意してください。

```yaml:deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blue-green-sample
  labels:
    app: blue-green-sample
spec:
  replicas: 2
  selector:
    matchLabels:
      app: blue-green-sample
  template:
    metadata:
      labels:
        app: blue-green-sample
    spec:
      containers:
        - name: blue-green-sample
          image: blue-green-sample:latest
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
```
```yaml:service.yaml
apiVersion: v1
kind: Service
metadata:
  name: blue-green-sample-service
spec:
  selector:
    app: blue-green-sample
  type: NodePort
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
```

## 2.2 アプリ動作確認
minikubeでDeploymentとServiceをデプロイします。

```bash
# deploymentの作成
$ kubectl apply -n sample -f ./k8s/deployment.yaml
$ kubectl get pod -n sample
NAME                                 READY   STATUS    RESTARTS   AGE
blue-green-sample-679d6b6dd4-564tb   1/1     Running   0          22s
blue-green-sample-679d6b6dd4-bxlph   1/1     Running   0          12s

# serviceの作成
$ kubectl apply -n sample -f ./k8s/service.yaml
service/blue-green-sample-service created
$ kubectl get service -n sample
NAME                        TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
blue-green-sample-service   NodePort   10.97.200.105   <none>        8080:30641/TCP   2m49s

# Serviceのポートフォワード設定
$ kubectl port-forward -n sample service/blue-green-sample-service 8080:8080
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
```

デプロイ後、そのままではServiceにリクエストを送信できないのでポートフォワーディングを実行します。
フォワーディングが有効になっている状態でリクエストを送信するとレスポンスが返って来きたので、動作確認はOKです。

```bash
$ curl -s http://localhost:8080/sample/version
{"appVersion":"green"}
```

# 3. Argo Rolloutsの検証
では本題のArgo Rolloutsの動作検証を進めていきます。
Argo Rolloutsではデプロイ戦略として[カナリア](https://argoproj.github.io/argo-rollouts/features/canary/)と[Blue/Green](https://argoproj.github.io/argo-rollouts/features/bluegreen/)が選択可能です。
今回はタイトルの通りBlue/Greenデプロイの検証が目的なのでデプロイ戦略はBlue/Greenを選択します。

## 3.1 Argo Rolloutsのインストール
まずは、Argo Rolloutsをインストールします。
[公式のドキュメント](https://argoproj.github.io/argo-rollouts/installation/)ではインストール方法は2通りあると記載されています。

1. [install.yaml](https://github.com/argoproj/argo-rollouts/blob/master/manifests/install.yaml) - Standard installation method
2. [namespace-install.yaml](https://github.com/argoproj/argo-rollouts/blob/master/manifests/namespace-install.yaml) - Installation of Argo Rollouts which requires only namespace level privileges.  

1.はスタンダードな方法でこのインストールを実行するとArgo RolloutsのContorllerが起動する`argo-rollouts`というnamespaceが作成されます。
一方で、2.は同じKubernetesクラスター上に複数のArgo Rollouts Controllerを起動する場合に利用するそうです。

今回は複数起動させる予定はないため、`install.yaml`でインストールします。
インストールコマンドは[公式のドキュメント](https://argoproj.github.io/argo-rollouts/installation/)に記載されているとおりです。

```bash
$ kubectl create namespace argo-rollouts
$ kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
```

次にプラグインもインストールします。
手順は[Kubectl Plugin Installation](https://argoproj.github.io/argo-rollouts/installation/#kubectl-plugin-installation)に記載されており、方法は`brew`か手動の2通りが選択可能です。
私の環境はUbuntuなので手動インストールを選択しました。
手順通りで問題ないですが、公式のコマンドはディストリビューションが`darwin`なので`linux`に書き換えます。

```bash
# プラグインのインストール
$ curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
$ chmod +x ./kubectl-argo-rollouts-linux-amd64
$ sudo mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts

# プラグインのインストール確認
$ kubectl argo rollouts version
kubectl-argo-rollouts: v1.4.0+e40c9fe
  BuildDate: 2023-01-09T20:20:38Z
  GitCommit: e40c9fe8a2f7fee9d8ee1c56b4c6c7b983fce135
  GitTreeState: clean
  GoVersion: go1.19.4
  Compiler: gc
  Platform: linux/amd64
```

`kubectl argo rollouts version`コマンドでバージョンが表示されればインストールは完了です。

## 3.2 マニフェストファイルの作成
Argo Rolloutsを利用する場合、マニフェストファイルの`kind`はDeploymentではなくRolloutになります。
また、Rolloutの構造はDeploymentとよく似ていますが、`strategy:`にデプロイ戦略の設定を追記します。

```yaml:rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-blue-green
spec:
  replicas: 2
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: rollout-blue-green
  template:
    metadata:
      labels:
        app: rollout-blue-green
    spec:
      containers:
        - name: rollout-blue-green-sample
          image: blue-green-sample:blue
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
  strategy:
    blueGreen:
      activeService: rollout-blue-green-svc-active
      previewService: rollout-blue-green-svc-preview
      autoPromotionEnabled: false
```


次にRolloutに対応するServiceを作成します。
Blue/Greenデプロイの場合、公開面とスタンバイ面の2つのServiceを作成する必要があります。
また、Serviceの名前(`metadata.name`)にRolloutの`activeService`と`previewService`に指定したService名を設定します。

```yaml:rollout-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: rollout-blue-green-svc-active
spec:
  selector:
    app: rollout-blue-green
  type: NodePort
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: rollout-blue-green-svc-preview
spec:
  selector:
    app: rollout-blue-green
  type: NodePort
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
```

## 3.3 Blue/Greenデプロイの実行
それではBlue/Greenデプロイの動作検証を進めていきたいと思います。
### 3.3.1 Blue面のデプロイ
作成したRolloutとServiceのマニフェストファイルを指定して`apply`を実行します。

```bash
# Rolloutの作成
$ kubectl apply -n sample -f rollout.yaml
rollout.argoproj.io/rollout-blue-green created

# Serviceの作成
$ kubectl apply -n sample -f rollout-service.yaml
service/rollout-blue-green-svc-active created
service/rollout-blue-green-svc-preview created

# Podの確認
$ kubectl get pod -n sample
NAME                                  READY   STATUS              RESTARTS   AGE
rollout-blue-green-5854f6d6dd-8qlsx   0/1     ContainerCreating   0          4s
rollout-blue-green-5854f6d6dd-vd7kr   0/1     ContainerCreating   0          4s

# Serviceの確認
$ kubectl get svc -n sample
NAME                             TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
rollout-blue-green-svc-active    NodePort   10.111.189.10   <none>        8080:31917/TCP   48s
rollout-blue-green-svc-preview   NodePort   10.101.18.128   <none>        8080:30764/TCP   47s

# Rolloutの確認
$ kubectl get rollout -n sample
NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
rollout-blue-green   2         2         2            2           74s

# Argo Rolloutsの状態確認
$ kubectl argo rollouts get rollout -n sample rollout-blue-green
Name:            rollout-blue-green
Namespace:       sample
Status:          ✔ Healthy
Strategy:        BlueGreen
Images:          blue-green-sample:blue (stable, active)
Replicas:
  Desired:       2
  Current:       2
  Updated:       2
  Ready:         2
  Available:     2

NAME                                            KIND        STATUS     AGE   INFO
⟳ rollout-blue-green                            Rollout     ✔ Healthy  2m9s
└──# revision:1
   └──⧉ rollout-blue-green-5854f6d6dd           ReplicaSet  ✔ Healthy  109s  stable,active
      ├──□ rollout-blue-green-5854f6d6dd-8qlsx  Pod         ✔ Running  107s  ready:1/1
      └──□ rollout-blue-green-5854f6d6dd-vd7kr  Pod         ✔ Running  107s  ready:1/1

# ポートフォワーディング
$ kubectl port-forward -n sample service/rollout-blue-green-svc-active 8080:8080
```

`rollout-blue-green-svc-active`のポートフォワーディングを実行します。
Serviceに対してリクエストを送信すると、Blue面からレスポンスが返ってきました。

```bash
$ curl -s http://localhost:8080/sample/version
{"appVersion":"blue"}
```

### 3.3.2 Green面のデプロイ
次にGreen面をデプロイするため、`rollout.yaml`のイメージのタグを修正します。
現在は`blue`面がデプロイされているので、タグ名を`green`に変更し保存します。

```yaml:rollout.yaml
# イメージのタグをgreenに更新
image: blue-green-sample:green
```

変更したマニフェストファイルの`apply`を実行します。

```bash
$ kubectl apply -n sample -f rollout.yaml
rollout.argoproj.io/rollout-blue-green configured
```

するとRolloutの状態が変化し`revision:2`が新しく立ち上がります。

```bash
$ kubectl argo rollouts get rollout -n sample rollout-blue-green --watch
# ==============================
# revision:2の作成
# ==============================
Name:            rollout-blue-green
Namespace:       sample
Status:          ◌ Progressing
Message:         more replicas need to be updated
Strategy:        BlueGreen
Images:          blue-green-sample:blue (stable, active)
Replicas:
  Desired:       2
  Current:       2
  Updated:       0
  Ready:         2
  Available:     2

NAME                                            KIND        STATUS         AGE   INFO
⟳ rollout-blue-green                            Rollout     ◌ Progressing  119m
├──# revision:2
│  └──⧉ rollout-blue-green-8d77c86f5            ReplicaSet  ◌ Progressing  2s    preview
└──# revision:1
   └──⧉ rollout-blue-green-5854f6d6dd           ReplicaSet  ✔ Healthy      119m  stable,active
      ├──□ rollout-blue-green-5854f6d6dd-8qlsx  Pod         ✔ Running      119m  ready:1/1
      └──□ rollout-blue-green-5854f6d6dd-vd7kr  Pod         ✔ Running      119m  ready:1/1

# ==============================
# revision:2のPod作成待ち
# ==============================
Name:            rollout-blue-green
Namespace:       sample
Status:          ◌ Progressing
Message:         more replicas need to be updated
Strategy:        BlueGreen
Images:          blue-green-sample:blue (stable, active)
Replicas:
  Desired:       2
  Current:       2
  Updated:       0
  Ready:         2
  Available:     2

NAME                                            KIND        STATUS         AGE   INFO
⟳ rollout-blue-green                            Rollout     ◌ Progressing  119m
├──# revision:2
│  └──⧉ rollout-blue-green-8d77c86f5            ReplicaSet  ◌ Progressing  2s    preview
│     ├──□ rollout-blue-green-8d77c86f5-2xn9n   Pod         ◌ Pending      0s    ready:0/1
│     └──□ rollout-blue-green-8d77c86f5-vlsqd   Pod         ◌ Pending      0s    ready:0/1
└──# revision:1
   └──⧉ rollout-blue-green-5854f6d6dd           ReplicaSet  ✔ Healthy      119m  stable,active
      ├──□ rollout-blue-green-5854f6d6dd-8qlsx  Pod         ✔ Running      119m  ready:1/1
      └──□ rollout-blue-green-5854f6d6dd-vd7kr  Pod         ✔ Running      119m  ready:1/1

# ==============================
# revision:2のPod作成開始
# ==============================
Name:            rollout-blue-green
Namespace:       sample
Status:          ◌ Progressing
Message:         active service cutover pending
Strategy:        BlueGreen
Images:          blue-green-sample:blue (stable, active)
                 blue-green-sample:green (preview)
Replicas:
  Desired:       2
  Current:       4
  Updated:       2
  Ready:         2
  Available:     2

NAME                                            KIND        STATUS               AGE   INFO
⟳ rollout-blue-green                            Rollout     ◌ Progressing        119m
├──# revision:2
│  └──⧉ rollout-blue-green-8d77c86f5            ReplicaSet  ◌ Progressing        6s    preview
│     ├──□ rollout-blue-green-8d77c86f5-2xn9n   Pod         ◌ ContainerCreating  4s    ready:0/1
│     └──□ rollout-blue-green-8d77c86f5-vlsqd   Pod         ◌ ContainerCreating  4s    ready:0/1
└──# revision:1
   └──⧉ rollout-blue-green-5854f6d6dd           ReplicaSet  ✔ Healthy            119m  stable,active
      ├──□ rollout-blue-green-5854f6d6dd-8qlsx  Pod         ✔ Running            119m  ready:1/1
      └──□ rollout-blue-green-5854f6d6dd-vd7kr  Pod         ✔ Running            119m  ready:1/1

# ==============================
# revision:2のPod作成完了
# ==============================
Name:            rollout-blue-green
Namespace:       sample
Status:          ॥ Paused
Message:         BlueGreenPause
Strategy:        BlueGreen
Images:          blue-green-sample:blue (stable, active)
                 blue-green-sample:green (preview)
Replicas:
  Desired:       2
  Current:       4
  Updated:       2
  Ready:         2
  Available:     2

NAME                                            KIND        STATUS     AGE   INFO
⟳ rollout-blue-green                            Rollout     ॥ Paused   120m
├──# revision:2
│  └──⧉ rollout-blue-green-8d77c86f5            ReplicaSet  ✔ Healthy  30s   preview
│     ├──□ rollout-blue-green-8d77c86f5-2xn9n   Pod         ✔ Running  28s   ready:1/1
│     └──□ rollout-blue-green-8d77c86f5-vlsqd   Pod         ✔ Running  28s   ready:1/1
└──# revision:1
   └──⧉ rollout-blue-green-5854f6d6dd           ReplicaSet  ✔ Healthy  119m  stable,active
      ├──□ rollout-blue-green-5854f6d6dd-8qlsx  Pod         ✔ Running  119m  ready:1/1
      └──□ rollout-blue-green-5854f6d6dd-vd7kr  Pod         ✔ Running  119m  ready:1/1
```

`revision:2`のPodが立ち上がったことが確認できますが、`rollout-blue-green`のSTATUSが`Paused`となっています。
この状態でリクエストをactiveサービスに送信すると、Blueのレスポンスが返ってきます。
このことから、まだBlue面とGreen面が切り替わっていないことがわかります。

```bash
$ curl -s http://localhost:8080/sample/version
{"appVersion":"blue"}
```

この状態をダッシュボードでも確認してみます。
ダッシュボードを起動する場合は、[]()でインストールしたプラグインの`dashbord`を実行します。

```bash
$ kubectl argo rollouts -n sample dashboard
INFO[0000] Argo Rollouts Dashboard is now available at http://localhost:3100/rollouts
```
ブラウザから`http://localhost:3100/rollouts`のURLにアクセスると下記のダッシュボードが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177076/9b00923a-2ca2-66d1-6b7e-f807f446dffd.png)


画面上の緑の✅はPodを表しており、それぞれのRevisionで2つのPodが起動しています。
また、Revision:1とRevision:2の両方が起動しており、Revision:1がActiveであることも確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177076/5a07ca1d-f655-ad9b-b610-815b735e8142.png)


### 3.3.3 面の切り替え
Blue面、Green面の両方がデプロイできたので面の切り替えを実行します。
切り替えの実行はコマンドまたはダッシュボードの画面から実行します。
下記は面切り替えのコマンド例です。

```bash
$ kubectl argo rollouts promote -n sample rollout-blue-green
```


```bash
$ kubectl argo rollouts get rollout -n sample rollout-blue-green --watch
# ==============================
# Green面がActiveに昇格
# ==============================
Name:            rollout-blue-green
Namespace:       sample
Status:          ✔ Healthy
Strategy:        BlueGreen
Images:          blue-green-sample:blue
                 blue-green-sample:green (stable, active)
Replicas:
  Desired:       2
  Current:       4
  Updated:       2
  Ready:         2
  Available:     2

NAME                                            KIND        STATUS     AGE   INFO
⟳ rollout-blue-green                            Rollout     ✔ Healthy  150m
├──# revision:2
│  └──⧉ rollout-blue-green-8d77c86f5            ReplicaSet  ✔ Healthy  30m   stable,active
│     ├──□ rollout-blue-green-8d77c86f5-2xn9n   Pod         ✔ Running  30m   ready:1/1
│     └──□ rollout-blue-green-8d77c86f5-vlsqd   Pod         ✔ Running  30m   ready:1/1
└──# revision:1
   └──⧉ rollout-blue-green-5854f6d6dd           ReplicaSet  ✔ Healthy  149m
      ├──□ rollout-blue-green-5854f6d6dd-8qlsx  Pod         ✔ Running  149m  ready:1/1
      └──□ rollout-blue-green-5854f6d6dd-vd7kr  Pod         ✔ Running  149m  ready:1/1

# ==============================
# revision:1の縮退開始
# ==============================
Name:            rollout-blue-green
Namespace:       sample
Status:          ✔ Healthy
Strategy:        BlueGreen
Images:          blue-green-sample:blue
                 blue-green-sample:green (stable, active)
Replicas:
  Desired:       2
  Current:       4
  Updated:       2
  Ready:         2
  Available:     2

NAME                                            KIND        STATUS         AGE   INFO
⟳ rollout-blue-green                            Rollout     ✔ Healthy      150m
├──# revision:2
│  └──⧉ rollout-blue-green-8d77c86f5            ReplicaSet  ✔ Healthy      30m   stable,active
│     ├──□ rollout-blue-green-8d77c86f5-2xn9n   Pod         ✔ Running      30m   ready:1/1
│     └──□ rollout-blue-green-8d77c86f5-vlsqd   Pod         ✔ Running      30m   ready:1/1
└──# revision:1
   └──⧉ rollout-blue-green-5854f6d6dd           ReplicaSet  • ScaledDown   150m
      ├──□ rollout-blue-green-5854f6d6dd-8qlsx  Pod         ◌ Terminating  150m  ready:1/1
      └──□ rollout-blue-green-5854f6d6dd-vd7kr  Pod         ◌ Terminating  150m  ready:1/1

# ==============================
# revision:1の縮退完了
# ==============================
Name:            rollout-blue-green
Namespace:       sample
Status:          ✔ Healthy
Strategy:        BlueGreen
Images:          blue-green-sample:green (stable, active)
Replicas:
  Desired:       2
  Current:       2
  Updated:       2
  Ready:         2
  Available:     2

NAME                                           KIND        STATUS        AGE   INFO
⟳ rollout-blue-green                           Rollout     ✔ Healthy     152m
├──# revision:2
│  └──⧉ rollout-blue-green-8d77c86f5           ReplicaSet  ✔ Healthy     32m   stable,active
│     ├──□ rollout-blue-green-8d77c86f5-2xn9n  Pod         ✔ Running     32m   ready:1/1
│     └──□ rollout-blue-green-8d77c86f5-vlsqd  Pod         ✔ Running     32m   ready:1/1
└──# revision:1
   └──⧉ rollout-blue-green-5854f6d6dd          ReplicaSet  • ScaledDown  152m
```

`promote`を実行すると`revision:2`がActiveになり、`revision:1`のPodは削除され縮退していることがわかります。
この状態で`rollout-blue-green-svc-active`のポートフォワーディングを実行し、Serviceに対してリクエストを送信するとGreen面からレスポンスが返ってきました。
面の切り替えは成功です。

```bash
$ curl -s http://localhost:8080/sample/version
{"appVersion":"green"}
```

ダッシュボードでもRevision:2がActiveになっていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177076/87441c3a-82c8-4fac-8806-0af4fa9103df.png)

## 3.4 ロールバックの実行
次にロールバック時にどういった挙動になるのかを確認してみます。
今回はコマンドではなくダッシュボードの画面から実行してみます。

ダッシュボードを開くと、Revisionsに2つのRevisionが表示されます。
ただし`Revision 1`は縮退しているため、Podは起動していません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177076/068411a1-8c9a-01ab-6f1a-d59f10ec263b.png)
この縮退しているRevisionのROLLBACKを押します。
押すとボタンの文字が「本当に実行する？(Sure?)」となるので、ボタンを押してROLLBACKを実行します。
ROLLBACKを実行すると新しいRevisionの`Revision 3`が立ち上り、Podが起動します。
コンテナイメージのタグは縮退したRevisionと同じく`green`です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177076/29e1559b-be9e-94ee-0dab-8e7ea9f02d10.png)
`Revision 3`のPod起動が完了しましたので画面上部のPROMOTEを実行します。
こちらも再確認が求められるので、そのまま実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177076/123a101b-b361-536c-dfa4-3e9ce6c36867.png)
PROMOTEを実行すると`Revision 3`がActiveに昇格し、`Revision 2`はPreviewに降格します。
そして降格の30秒後にPodの縮退を開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177076/d84b8496-f90a-2c74-67ad-88b1525a83b5.png)
縮退開始までの時間は`rollout.yaml`に設定する`scaleDownDelaySeconds`で変更可能です。
デフォルトでは30秒となっています。
設定可能なオプションは[公式ドキュメントのConfigurable Features](https://argoproj.github.io/argo-rollouts/features/bluegreen/#configurable-features)を参照してください。

# 4. マニフェストファイルのkustomize化
作成したマニフェストファイルをkustomize化してみます。
下記はディレクトリやファイルの構成です。

```
manifest
 ├ base
 │  ├ kustomization.yaml
 │  ├ rollout.yaml
 │  └ rollout-service.yaml
 └ overlays/dev
    ├ kustomization.yaml
    ├ patch.yaml
    └ config.env
```

`base`ディレクトリの各ファイルの内容は以下の通り。

```yaml:base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - rollout.yaml
  - rollout-service.yaml

# Version 2023-03-01-1677634140
openapi:
  path: https://github.com/argoproj/argo-schema-generator/raw/2023-03-01-1677634140/schema/argo_all_k8s_kustomize_schema.json

# Version v1.4.0
configurations:
  - https://raw.githubusercontent.com/argoproj/argo-rollouts/v1.4.0/docs/features/kustomize/rollout-transform.yaml
```

`openapi`と`configurations`にAPIのスキーマや、[Transformer Configurations](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/transformerconfigs/README.md)を設定する必要があります。
これらの設定がないとうまく`Rollout`が加工できません。
実際にこれらの設定をなくして`kustomize build`を実行すると、`configMap`がうまく`Rollout`に反映できませんでした。

また以前は[こちらのブログ](https://tech.isid.co.jp/entry/2022/09/05/kustomize%E3%81%A7Custom_Resource%E3%82%92%E6%89%B1%E3%81%86)に記載されているとおり、標準リソースとArgo RolloutsのOpenAPIスキーマを統合した独自のスキーマ定義を作成し、設定する必要がありました。
ですが、最新のArgoRolloutsのドキュメントによると[argo-schema-generator](https://github.com/argoproj/argo-schema-generator)で生成されたスキーマ定義を利用すれば独自に加工したスキーマ定義は不要とのことです。

詳細は[公式ドキュメント](https://argoproj.github.io/argo-rollouts/features/kustomize/)を参照してください。

```yaml:base/rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-blue-green
spec:
  replicas: 2
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: rollout-blue-green
  template:
    metadata:
      labels:
        app: rollout-blue-green
    spec:
      containers:
        - name: rollout-blue-green-sample
          image: rollout-blue-green-sample-image
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 9090
          env:
            - name: TEST_ENV_01
              value: "environment message01"
          envFrom:
            - configMapRef:
                name: blue-green-sample-config
  strategy:
    blueGreen:
      activeService: rollout-blue-green-svc-active
      previewService: rollout-blue-green-svc-preview
      autoPromotionEnabled: false
```

`base/rollout-service.yaml`は[3.2 マニフェストファイルの作成](https://qiita.com/yuuman/items/77742a2597866fa32a0b#32-%E3%83%9E%E3%83%8B%E3%83%95%E3%82%A7%E3%82%B9%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%BD%9C%E6%88%90)と同じなので割愛します。

`overlays/dev`ディレクトリの各ファイルの内容は以下の通り。

```yaml:overlays/dev/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

images:
  - name: rollout-blue-green-sample-image
    newName: blue-green-sample
    newTag: latest

patches:
  - target:
      kind: Rollout
    path: patch.yaml

configMapGenerator:
  - name: blue-green-sample-config
    envs:
      - config.env
```

```yaml:overlays/dev/patch.yaml
- op: replace
  path: /spec/template/spec/containers/0/ports/0/containerPort
  value: 8080
- op: add
  path:  /spec/template/spec/containers/0/env/-
  value:
    name: TEST_ENV_02
    value: "environment message02"
```
```env:config.env
ENV_VALUE01=ENV-VALUE
```

この構成で`kustomize build`を実行すると下記の通りにマニフェストファイルが作成されます。
環境変数や`configMap`、コンテナイメージやポート番号がうまく上書き、追記されていることが確認できます。

```yaml
apiVersion: v1
data:
  ENV_VALUE01: ENV-VALUE
kind: ConfigMap
metadata:
  name: blue-green-sample-config-gcfb6g9844
---
apiVersion: v1
kind: Service
metadata:
  name: rollout-blue-green-svc-active
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: rollout-blue-green
  type: NodePort
---
apiVersion: v1
kind: Service
metadata:
  name: rollout-blue-green-svc-preview
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: rollout-blue-green
  type: NodePort
---
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-blue-green
spec:
  replicas: 2
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: rollout-blue-green
  strategy:
    blueGreen:
      activeService: rollout-blue-green-svc-active
      autoPromotionEnabled: false
      previewService: rollout-blue-green-svc-preview
  template:
    metadata:
      labels:
        app: rollout-blue-green
    spec:
      containers:
      - env:
        - name: TEST_ENV_01
          value: environment message01
        - name: TEST_ENV_02
          value: environment message02
        envFrom:
        - configMapRef:
            name: blue-green-sample-config-gcfb6g9844
        image: blue-green-sample:latest
        imagePullPolicy: IfNotPresent
        name: rollout-blue-green-sample
        ports:
        - containerPort: 8080
```

# 5. さいごに
今回の検証作業でArgo RolloutsでのBlue/Greenデプロイがどうやって動くのかを確認しましたが、結構使えそうだということがわかりました。
またマニフェストファイルのkustomize化も問題ないことが確認できたました。

調べてみるとArgoCDのプラグインで`rollout-extension`があるらしく、ArgoCDのダッシュボードにArgo Rolloutsのダッシュボードを表示することができるそうです。
これを使うとさらに使い勝手がよくなりそうですね。

https://blog.manabusakai.com/2021/11/argo-cd-extensions/