RDS Blue/Green Deployment完全解説：ダウンタイムゼロへの挑戦

# 1. そもそもBlue/Green Deploymentとは
`Blue/Green Deployment`は<font color="red">新しい概念でも Aurora 専用の手法でもありません</font>。
これは、<font color="red">アプリケーションの新バージョンをリリースする際に広く使用される一般的なデプロイメント戦略</font>です。
最近はインフラエンジニアにとってはもはや<font color="red">当たり前</font>になってきました。

**アプリケーションレイヤーでのBlue/Green Deploymentに関する特徴**
- 2つの同様の環境を用意
    - Blue環境: 現行の本番環境
    - Green環境: 新バージョンをデプロイする環境
- Green環境に新バージョンをデプロイし、テストを実施
    - デフォルトはトラフィックが直ちに徐々にBlueからGreenに切り替える設定ですが、待機時間(待機期間でテストを実施)を設定することも可能
- トラフィックを徐々にBlueからGreenに切り替え　
- 問題があればBlue環境に素早くロールバック可能
- 完全に切り替わって、特に問題が発生しない場合は、Blue環境を削除

**主なメリット:**
- ダウンタイムの最小化
- リスクの軽減
- 素早いロールバック

AWSでアプリケーションレイヤーで`Blue/Green Deployment`を実施する場合、<font color="red">主に`ECS`と`CodeDeploy`を組み合わせて使用する方法が一般的</font>です。

https://tech.dentsusoken.com/entry/2022/01/11/CodeDeploy_%E3%81%AB%E3%82%88%E3%82%8BECS_%E3%81%A7%E3%81%AEBlue/Green%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%AE%E8%A9%B1

https://zenn.dev/umatoma/articles/920b40bbc222da

# 2. 従来のデータベースBlue/Green Deployment
- データベースではBlue/Green Deploymentはそもそも可能なのか？
Blue/Green Deploymentは同時に新旧バージョンを稼働させるため、基本的にはステートレスなアプリケーション・サーバーでしか利用できず、データベースでは実現不可能だという固定観念を持つエンジニアは少なくありません。しかし実際には、RDS Blue/Green Deploymentがリリースされる以前から、データベースにおいて擬似的にBlue/Green Deploymentを実現するための手法がいくつか存在していました。

## 2.1 手動バイナリログレプリケーション
1. 本番環境(Blue)と同じ構成の新環境(Green)を<font color="red">手動</font>作成
2. バイナリログレプリケーションを手動で設定し、継続的なデータ同期を確立(<font color="red">MySQLにそれなりに詳しくないエンジニアでないかぎりではちょっとハードル高そう</font>)
3. Green環境で必要な変更を実施
4. テストを行いながら、レプリケーションを継続
5. 準備が整ったら、短時間のダウンタイムを取ってレプリケーションを停止し、<font color="red">手動</font>でアプリケーションの接続先を切り替え

バイナリログレプリケーションを手動で設定する方法：

https://dev.classmethod.jp/articles/enable-aurora-binary-logs/

## 2.2 RDSのread replicaを利用
RDSのread replicaを利用したBlue/Green Deploymentの具体的な手順:
1. 本番環境(Blue)のRDSインスタンスのread replicaを<font color="red">手動</font>作成する
2. read replicaのread_onlyパラメータを0に設定し、書き込み可能にする
   - パラメータグループを新規作成し、 <font color="red">`read_only`を0に設定</font>
   - read replicaにこのパラメータグループを適用し再起動
3. read replica(Green環境)で必要な変更を実施
   - スキーマ変更
   - バージョンアップグレード
   - パラメータ変更など
4. Green環境でテストを実施
5. 切り替え準備
   - アプリケーションを一時停止
   - Blue環境への書き込みを停止
6. レプリケーションの遅延がなくなるまで待機
7. read replicaをプロモートして独立したインスタンスにする
8. <font color="red">手動</font>アプリケーションの接続先をGreen環境に変更
9. アプリケーションを再開
10. 動作確認後、旧Blue環境を削除

ただし、この方法には以下の注意点があります:

- レプリケーションの整合性が損なわれる可能性がある
- プロモート後は元のマスターとの同期が失われる
- <font color="red">AWSの公式なBlue/Green Deployment機能ではないため、サポート対象外となる可能性がある</font>
一応AWS documentでは以下の内容が書かれているが、実際にRDS read replicaを利用してonline DDLサポートしていないDDLを実施するユースケースってなかなか少ないようですね。
というこごで技術的には可能ですが、多くのリスクを伴い、一般的には推奨されません。

https://aws.amazon.com/jp/about-aws/whats-new/2012/10/11/amazon-rds-mysql-rr-promotion/

```
Perform DDL operations: DDL operations such as creating/re-building indexes etc. 
could take a long time and impose significant performance penalty on your DB Instance. 
You can perform these operations on a Read Replica, and once the operations are 
complete and the updates are caught up with the Source DB Instance, 
you can promote the Read Replica, and point your applications to it.

```
- Auroraは共有ストレージアーキテクチャであり、スキーマ変更を直接行うことはできません。とうことでこの方法は、<font color="red">標準のMySQLレプリケーションには適用できる場合がありますが、Auroraには適用できません</font>

## 2.3 AWS DMSを使用した継続的レプリケーション
**詳細プロセス:**
1. <font color="red">手動</font>で新しいGreen環境のクラスターを作成
2. DMS(AWS Database Migration Service)を使用してBlueからGreenへの継続的なレプリケーションを設定
    - DMSレプリケーションインスタンスの作成:
        - 適切なインスタンスタイプとネットワーク設定でDMSレプリケーションインスタンスを作成
    -  ソースとターゲットのエンドポイント設定:
        - ソース（Blue環境）とターゲット（Green環境）のエンドポイントをDMSで設定
    - マイグレーションタスクの作成と実行:
        - フルロード＋CDCモードでマイグレーションタスクを作成
        - タスクを開始し、初期データロードと継続的な変更のレプリケーションを実行
3. Green環境で必要な変更（スキーマ変更、バージョンアップグレードなど）を実施
4. テストを行いながら、DMSによるデータ同期を継続
5. 切り替え:
    - <font color="red">手動</font>でアプリケーション側の接続先をBlue環境からGreen環境に変更
6. DMSタスクを停止
7. クリーンアップ:
    - 問題がないことを確認後、旧Blue環境とDMSリソースを削除

**特徴：**
- DMSは多くの手動設定と管理が必要で、DMSに慣れていない方にとってはハードルがかなり高い
- <font color="red">手動でアプリケーション側の接続先する必要があるから、切り替え時のダウンタイムが長くなりそう</font>
- カスタマイズの自由度が高い(例えば特定のデータベースや特定のテーブルだけ同期するなどもできる)
- <font color="red">異なるデータベースエンジン間の移行にも使用可能(MySQl⇒PostgreSQLなど)</font>

# 3. RDS Blue/Green Deployment
## 3.1 RDS Blue/Green Deploymentの仕組み
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments-overview.html

以前からデータベースにおいて擬似的にBlue/Green Deploymentを実現するための手法がいくつか存在していました。しかし、これらの手法は操作が複雑で、リスクも伴い、広く普及するには至っていませんでした。このような課題を解決し、マネージドサービスとして提供されているのがRDS Blue/Green Deploymentです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/fa6bd6cc-c4a3-825f-7db7-33762e440e86.png)


1. 数クリックだけで、現本番環境(Blue環境)のコピー(Green環境)を自動的に作成してくれる
    - Blue環境のバージョンアップ or CloneからGreen環境を作成
        - Green環境の作成時に、Blue環境で保留中のメンテナンス（バージョンアップやOSパッチ適用など）がある場合、それらは自動的にGreen環境に適用
    - 単なる特定時点のデータのコピーではなく、<font color="red">Blue環境とGreen環境の間では論理レプリケーションが自動的に設定</font>される。これにより、<font color="red">Blue環境に書き込まれるデータは、すべてリアルタイムでGreen環境に継続的に同期</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/02959d3b-ec11-c701-38ec-ec6a83142c2a.png)

2. Green環境で気軽に以下のような各種変更のテストできる
    - **データベースエンジンのバージョン アップグレード**:メジャーまたはマイナーバージョンのアップグレードを行う際に、事前にGreen環境でテストできる
    - **パラメータグループの変更**:データベースパラメータの変更をGreen環境で試し、本番環境に影響を与えないようにすることが可能
    - **新機能のテスト**: 新しいアプリケーション機能やデータベース設定変更を本番環境へ適用する前に、Green環境で検証できる

3. 環境の切り替えを実施(切り替えは<font color="red">通常1分以内で完了</font>)
    - webコンソールから<font color="red">ボタンを数クリックするだけで簡単に環境切り替えできる</font>
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/a5463815-925f-334b-a78d-7321a6a9d6bb.png)
    - 切り替え後の状態：もともとのデータベースエンドポイントが自動的にGreen環境に向けられ、<font color="red">アプリケーションの変更も一切不要</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/4ca06e09-ffd1-b767-3fd5-da6d82a78ecc.png)

4. 切り替え後もBlue環境は保持されます。しかし、Blue環境には切り替え時点のデータしか残っておらず、ユーザーからのトラフィックを停止しない限り、<font color="red">Blue環境とGreen環境の間にデータの差分が発生</font>します。そのため、<font color="red">切り替え後に簡単にBlue環境に戻すことはできません</font>。Blue環境が不要となった場合は、手動で削除しても構いません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/e5bd166f-d69d-c08a-1666-c3d43dffa856.png)


**主な利点**:
- データベースの変更リスクを軽減
- ダウンタイムの最小化
- テストと検証が容易
- 素早いロールバック可能

**通常のオンラインDDLでは対応が難しいが、RDS Blue/Green Deploymentを使用することでBlue環境で実行可能なDDLのリスト**：
- ALTER TABLE文を使用したカラムのデータ型変更
    - 例: INT型からBIGINT型への変更
- ALTER TABLE文を使用したカラムの追加
    - 例: 新しいカラムをテーブルに追加する
- インデックスの作成 (CREATE INDEX)
    - 例: 大規模なテーブルに新しいインデックスを追加する
- インデックスの削除 (DROP INDEX)
    - 例: 不要になったインデックスを削除する
- テーブルのパーティション化
    - 例: 既存の大規模テーブルをパーティション化する
- カラムのデフォルト値の変更
    - 例: ALTER TABLE文を使用してカラムのデフォルト値を変更する
- NULL制約の追加または削除
    - 例: ALTER TABLE文を使用してカラムにNOT NULL制約を追加する

これらのDDL操作は、通常のオンラインDDLでは本番環境に大きな影響を与える可能性がありますが、RDS Blue/Green Deploymentを使用することで、Blue環境で安全に実行し、テストした後に本番環境（Green環境）に適用することができます。


## 3.2 注意点
- Blue環境でバイナリログを有効にする必要があります。バイナリログのフォーマットはROWが推奨されますが、以下のことが注意したほうがよい。
    - ログの肥大化によるディスク容量の増加
    - I/O速度(パフォーマンスへの影響):通常5%未満
- クラスタの再起動が必要：
    クラスターパラメータグループの変更が適用されていないと、グリーン環境を作成できない。変更後はクラスタの再起動が必要です。
- 書き込み操作の制限: デフォルトでは、グリーン環境のDBクラスターは書き込み操作を許可しません

- 一時的に2つの環境を維持する必要があるため、コストが倍増する期間がある。

## 3.3 制限
- 利用できるエンジン
    - RDS for MySQL
    - RDS for PostgreSQL
    - RDS for MariaDB
    - Aurora MySQL：　Blue環境でbinlogを有効にする必要がある
    - Aurora PostgreSQL

https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments-overview.html

https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/blue-green-deployments.html


- 対応していないDDL

https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments-best-practices.html

`However, schema changes, such as renaming columns or renaming tables, break replication to the green deployment.`

https://dev.mysql.com/doc/refman/8.0/en/replication-features-differing-tables.html


RDS Blue/Green Deploymentは、論理レプリケーションを使用してBlue環境からGreen環境へのデータ同期を行います。Blue環境では破壊的な変更を実行する場合は、レプリケーションエラーになってしまいます。
- 列名の削除
- 列名の変更
- テーブルの削除
- テーブル名の変更

**具体的な例**：
green環境である列を削除したとします。blue環境では継続的に該当の列に新しいデータを入れています。レプリケーションでblue環境からgreen環境にデータを同期しようとすると、該当の列がないから、レプリケーションエラーが発生し、レプリケーションが止まってしまう。
対応方法：<font color="red">アプリケーション側であらかじめ該当のカラムに対してデータを入れないようにする修正をする必要がある</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/0a21499e-fd7c-d90a-0ae7-fee7588297bd.png)



## 3.4 4つの案の比較
| 特徴 | 手動binlog replication | RDS read replica利用 | AWS DMS | RDS Blue/Green Deployment |
|------|----------------------------------|----------------------|---------|---------------------------|
| replicationの責任 | ユーザー自身 | RDS | DMS | RDS |
| 複雑さ | 高 | 中 | 中 | 低 |
| 技術的専門知識の必要性 | 高 | 中 | 中 | 低 |
| コスト | 低<br>管理コスト高| 中 | 中 | 高<br>管理コスト低|
| ダウンタイム | 高 | 中 | 低 | 最小<br><font color="red">通常1分未満</font>|
| 異種DB間の移行 | 制限あり | 不可 | 可能 | 不可 |
| 自動化レベル | 低 | 中 | 中 | 高 |
| green環境の作成 | 手動 | 半自動 | 手動 | 自動 |
| ロールバックの容易さ | 難しい | 中程度 | 中程度 | 容易 |
| AWSサポート | なし(完全自己責任) | 部分的 | あり | 完全サポート |

この比較から、RDS Blue/Green Deploymentが最も使いやすく、リスクが低い方法であることがわかります。ただし、特定の要件や制約がある場合は、他の方法が適している可能性もあります。


:::note info
切り替え時間：
自分はテストしていないが、AWSさん公開している動画によると1分も経たずにに切り替えできた。

https://youtu.be/7CuyE2M8jBY?t=964

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/40c73c44-68e4-b730-7109-78a0ef43e149.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/4942fcab-1f79-ee89-fab8-2a772246c964.png)

テスト用のスクリプト：
https://github.com/euno7/rds-bgdeploy-demo/blob/main/main.go
:::


# 4. RDS Blue/Green Deployment対応できる課題のまとめ

1. **メジャー/マイナーバージョンアップ時のダウンタイム削減**：
メジャーまたはマイナーバージョンのアップグレードを行う際に、事前にGreen環境でテストできる

2. **スキーマ変更などのデータベース変更作業における長いダウンタイムの削減**
MySQLの新バージョンでは、以前はオフラインでしか実行できなかったDDL操作の多くがオンラインDDLとして実行可能になりました。これにより、ダウンタイムなし、あるいは極めて短いダウンタイムだけで多くのスキーマ変更が実施できるようになりました。しかし、カラムの削除やデータ型の変更など、依然としてオンラインDDLでサポートされていない操作も存在します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/a78b9560-df4e-1508-3f28-33d52980005a.png)

https://youtu.be/7CuyE2M8jBY?t=252


参考記事：

https://zenn.dev/hakushou41/articles/70b83066cd1741

https://qiita.com/bamtech1904/items/c6ba080556d4ca59de00


https://dev.classmethod.jp/articles/amazon-rds-blue-green-deployments-aurora-postgresql/


https://dev.classmethod.jp/articles/rds-bg-deploy/