CloudFront構成でもECSブルーグリーンデプロイメントを使えるようにする。

# はじめに
以前までは`CloudFront`を使用している環境でECSブルーグリーンデプロイメントを行う場合、テスト用ポートへのアクセスが簡単には出来ないことから一手間加えたりする必要がありましたが、`CloudFront`の継続的デプロイ機能を応用することで`CloudFront`を使っている構成でもECSブルーグリーンデプロイメントのテスト用ポートに簡単にアクセスすることができたので紹介したいと思います。

# ECSブルーグリーンデプロイメントについて
ECSブルーグリーンデプロイメントは`AWS`のサービスとなる`ECS`や`EC2`、`ELB`、`CodeDeploy`等を組み合わせて安全にデプロイするための仕組みで、デプロイ時にサービス提供中のセットとは別に、サービスを更新したもう1セット分の`ECS`を準備し、テスト等行って問題なければ新しいセットに切り替える仕組みとなります。

![blue_green2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/bb2bdda9-3efe-3677-e256-8e035368b681.png)

構成としては中々複雑な構成ですが、構築する上でコードを書いたりする必要はないので、一度構築してしまえば安全にECSをデプロイすることが可能です。

# CloudFrontとECSブルーグリーンデプロイメントを両方使う場合の問題点
`CloudFront`はパスパターンごとに指定するオリジン（S3やELB等）に転送する役割となるため、アクセスするオリジンのポート番号が異なっていてもパスパターンが同じであれば指定することができません。

![CloudFront1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/ded28afe-e2a8-a690-70f1-bdf0e343e85f.png)

かと言ってテストトラフィック用の`CloudFront`を別で用意するとしても、テストトラフィック用の設定を行わなければならないので、設定も管理も面倒ですし、サービストラフィック用の`CloudFront`に割り当てているドメインは使い回すことは出来ないので、テスト用ドメインを別で取得したりする必要も出てきます。

![CloudFront2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/8c859aef-e2c5-2203-3156-78b94d2df93a.png)

テストトラフィックだけは`CloudFront`を挟まずに直接`ELB`にアクセスするようにするといった方法も取れますが、テストのために設定しているのに`CloudFront`のテストが出来ないというのも本末転倒となってしまいます。

![CloudFront3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/1250e7f3-528f-0bc6-9ce0-9c8b016c1190.png)

そのため、今まで`CloudFront`とECSブルーグリーンデプロイメント両方を使用したい場合、中々にハードルが高かったのではないかと思います。

# CloudFront継続的デプロイを利用したECSブルーグリーンデプロイの連携
2023年8月くらいに`CloudFront`の新しい機能となる継続的デプロイ機能がリリースされました。

- [CloudFront の継続的デプロイを使用して CDN 設定の変更を安全にテストする](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/continuous-deployment.html)

`CloudFront`の継続的デプロイ機能自体は`CloudFront`の設定を変更する際に別の`CloudFront`を用意して徐々に新しい`CloudFront`に切り替えたり、特定ヘッダが付与されている場合だけ新しい`CloudFront`にアクセスできるようにするといった、ECSブルーグリーンデプロイメントの方法と同じようなイメージとなる機能となります。

![継続的デプロイ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/9ef126f8-096a-2f65-b394-3cb7eb0a8962.png)

構成イメージとしてはテストトラフィック用に`CloudFront`を新しく作成するやり方と似ていますが、`CloudFront`継続的デプロイの利点としては、作成済みの`CloudFront`画面から簡単に新しい`CloudFront`（ステージング環境）を作成でき、また、元の`CloudFront`で使用しているドメインと同じドメインで新旧両方の`CloudFront`経由でアクセスできるのが利点となります。

新旧`CloudFront`への振り分け方法として、特定ヘッダが付与されている場合のみステージング側の`CloudFront`へアクセスできるようにすれば、ヘッダ付与のみで経由する`CloudFront`を変えることができるので、より実際のアクセスに近い方法でテストを行えるという点も利点になるかと思います。

## CloudFront継続的デプロイの注意点
継続的デプロイ機能は`HTTP/3`に対応していないようなので、`CloudFront`で`HTTP/3`を有効にしているサイトでは残念ながら使えません。

ステージング環境を作成する際にも`HTTP/3`のチェックは外しておく必要があるのでご注意ください。

:::note info
2024/03/10 追記
CloudFront継続的デプロイ機能を使っていると変更できない機能について以下にまとめたので、設定変更する場合、以下も参考にしてください。
- [CloudFront継続的デプロイでは変更できない機能について](https://qiita.com/sakai00kou/items/93a584022697fb7a628b)
:::

# CloudFront継続的デプロイの設定
今回は`CloudFront`やECSブルーグリーンデプロイメントの構成は以下構成で作成出来ているものとして進めます。

ややこしいので元々の`CloudFront`ディストリビューションは本番環境、継続的デプロイ機能で作成する`CloudFront`ディストリビューションはステージング環境として進めます。

![blue_green.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/e57dc4d7-57a6-52b9-1294-4c56e71a58b7.png)

## ステージング環境の設定
本番環境の`CloudFront`の設定より、「**Create staging distribution**」を選択し、ステージング環境を作成します。

また、今回は、本番環境にアクセスしているのか、ステージング環境にアクセスしているのか分かりやすくするため、「**デフォルトルートオブジェクト**」設定で、本番用は「**production.html**」、ステージング用は「**staging.html**」の画面が表示されるように設定します。

![Monosnap_20231004_150158.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/d7874048-aa43-ae3a-b8c1-4b8fad2ad4e9.png)

ステージング環境の設定は本番環境の設定がデフォルトで入るため、変更したい設定のみ変更します。

今回はECSブルーグリーンデプロイのテスト用ポートにアクセスしたいので、オリジンの設定を変更し、オリジンのHTTPSポートを`4430`に変更します。

:::note info
ウェルノウンポートの指定はできないため、ELB側のテストポートをウェルノウンポートで指定している場合は変更すること。

- [ディストリビューションを作成または更新する場合に指定する値](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html)
:::

![Monosnap_20231004_151606.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/fc223309-d44b-f1ff-c92f-6ee83452d05d.png)

## 振り分け方法の設定
本番環境の`CloudFront`へアクセスするか、ステージング環境の`CloudFront`へアクセスするかの設定として、アクセスの割合で振り分ける「**Weight-based**」の設定と、特定ヘッダが付与されている場合のみステージング環境に振り分ける「**Header-based**」の設定の２つがあります。

今回は特定ヘッダが付与されている場合に先程ステージング設定で行った`4430`ポートへのアクセスを行いたいため、以下のようなヘッダ設定を行います。

|項目|設定|
|:--|:--|
|Type|Header-based|
|Header|aws-cf-cd-bgtest|
|Value|staging|

![Monosnap_20231004_151658.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/794917f0-17c0-88e8-8cf7-697826904c62.png)

なお、ヘッダ名には`aws-cf-cd-`を含める必要があるため、注意すること。

## ステージングアクセス用拡張機能のインストール
ステージング環境にアクセスするためには特定ヘッダを付与しないとアクセスできませんので、`Google Chrome`の拡張機能となる「**ModHeader - Modify HTTP headers**」をインストールして特定ヘッダを付与したアクセスを行えるようにします。
※ヘッダを付与できれば何でも良いので、別の手段を用いても問題ありません。

`Google Chrome`の「**Chromeウェブストア**」から「**ModHeader - Modify HTTP headers**」を検索し、インストールしてください。

## 特定ヘッダの付与
「**ModHeader - Modify HTTP headers**」をインストールしたら、ModHeaderのアイコンをクリックし、先程`CloudFront`で設定したヘッダ名とValue値を指定します。

![Monosnap_20231004_152959.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/f2654ab4-95c6-ab39-768e-99d293c57dfa.png)

また、ヘッダ名の左にあるチェックボックスのチェック有無でヘッダをつけてアクセスするかどうかを指定できるので、以下よりアクセス確認を行ってみます。

# CloudFront経由での本番＆ステージング環境アクセス
特定ヘッダなしでアクセスした場合。

![Monosnap_20231004_200502.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/f85eef37-269d-4f5b-16f8-5a7852f408ef.png)

特定ヘッダを付与してアクセスした場合。

![Monosnap_20231004_200929.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/15c95f71-88c9-db3c-e856-76382d2cb5d9.png)

特定ヘッダの有無でアクセス先が変わるため、アクセスする際のURLは本番でもステージングでも同じURLでアクセスすることができます。

# ステージング環境の管理
ステージング環境作成後、本番用`CloudFront`の設定画面を見ると、以下のようにステージング環境が作成されていることが確認出来ます。

![Monosnap_20231004_202313.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/2862deb3-ace2-f58b-8940-5c14e8243da2.png)

`CloudFront`のステージング環境については特に「**Promote**」で昇格させずにそのまま放置していたとしても、勝手に消されたりすることは無い（AWSサポート確認済み）ので、そのまま放置しても問題ありません。

放置が気になる方は、「**Disable**」で無効化しておいたり、無効化後、「**Delete**」することでステージング環境を削除することが出来ます。

なお、本番用`CloudFront`の設定を変更したとしてもステージング環境に設定が同期されたりはしないので、放置や無効化してテスト時のみステージング環境を利用する場合は本番用`CloudFront`の設定が変更されていないか注意してください。

# おわりに
`CloudFront`継続的デプロイ機能の本来の使用用途とは異なると思いますが、今回のような設定を行うことで`CloudFront`を挟んでいても、`ECS`ブルーグリーンデプロイメントを簡単に利用できるようになったのは大きいかと思います。

`CloudFront`とECSブルーグリーンデプロイメント両方を使用するようなシステムはたくさんあるかと思いますので、同じように悩んでいる方は参考にしてみてください。