cloudfront continuous deploymentでSPAのデプロイパイプラインを構築する
こんにちは、TOKIUMのembedded SREの對馬です。
現在構築中のサービスで、はじめてcloudfront continuous deploymentを使いました。
構築してみた結果、便利である反面、IaCとの兼ね合いが難しいなどの考慮すべき点もあり、一長一短、備忘として記事にします。
continuous deploymentの概要
なぜcontinuous deploymentを選んだか
現在構築中のサービスは、以下の図に近い構成をとっています。
ECS アーキテクチャデザインパターン
APIはECS上で動作し、frontendはS3バケットに配置する構成です。
この構成でfrontendに対してカナリアリリースなどを目指す場合、ユーザーからみてS3バケットより手前にあるリソースで、トラフィックを制御する必要があります。
そうなると、AWS WAFか、(図中にないですが)Route 53か、CloudFrontあたりから選ぶことになります。
まずもって、AWS WAFにはリクエスト振り分け機能が存在しないため、候補から外れます。
Route 53も、CloudFrontとの兼ね合いがよろしくないため候補から外れます。
加重ルーティング・IPベース問わず、Route 53のルーティングポリシーを使って複数個のCloudFront Distributionにリクエスト分散させることができません。
そうなると、CloudFront一択となります。
CloudFrontを利用したデプロイ方法にもいくつか種類はあるようですが、今回はcontinuous deploymentを使うことにしました。
(本当は他のデプロイ方法とも比較検討したかったんですが、時間が足りませんでした。)
概要
continuous deploymentは、本番ディストリビューションとは別にステージングディストリビューションを設けることで、本番適用前にテスト・検証ができる機能です。
stagingディストリビューションで事前にテストをして、OKだったらステージングの内容を本番に反映する、というフローを作れます。
本番とステージングのルーティング方法としては、以下2つが存在します。
- ヘッダーベース:特定のヘッダーが付与されているリクエストのみ、ステージングにルーティングする
- ウェイトベース:すべてのリクエストのうち一定割合はステージングにルーティングする。(0〜15%で指定可能)
仕組みがわかりやすくていいですね。
構築した内容
最終的に構築したインフラは、下記になります。
カナリアリリースを実現したかったため、ルーティングはウェイトベースを選ぶことにしました。
また、デプロイ中の異変に気づけるよう、CloudWatchアラームで、stagingの5XXエラーを監視するようにしています。
デプロイは以下の流れで行われます。
- S3に新バージョンのfrontend資材をアップロード
- stagingのオリジンパスを、新バージョン向けに更新
- stagingの更新が完了したら、deployment policyを有効化し、10%のトラフィックが流れるようにする。
- 一定時間この状態で監視を続ける。
4.a. ステージングで5XXエラーが頻発したら、CloudWatchアラームが発火しデプロイを中止し、deployment policyも無効化する。 - 特に問題がなければ、stagingのバージョンをそのまま本番に反映。continuous deploymentを無効化し、デプロイ完了!
continuous deploymentの注意点
terraform applyが一回じゃすまなくなる
わりかしいい感じのcontinuous deploymentですが、CloudFrontのリソース作成とcontinuous deploymentのポリシー紐付けが同時にできない点は注意が必要です。
どうやらAWS側の仕様でディストリビューションの作成とデプロイメントポリシーの紐づけを同時にできない様で、このため
- 各種リソースの作成
- プライマリディストリビューションとデプロイメントポリシーの紐づけ
を分けて行う必要があります。
この仕様により、一発でインフラを構築できないのがちょっと面倒。
弊社では、クラスメソッドさんの記事と同様に、紐付けを変数化して紐付けなしでapply -> 紐付けしてapplyという形にしています。
構築時の一回だけではあるものの、面倒だなーと思ってしまいます。
結構シェルを書かなきゃいけない
直感的でわかりやすいcontinuous deploymentですが、デプロイを自動化しようとすると、結構な量のシェルを書かないといけなくなります。
弊社のパイプラインでは、以下5つのシェルが必要になりました。
- ステージング更新シェル
- 本番反映シェル
- deployment policy有効化/無効化シェル
- deployment policy id取得シェル
- deployment policy 設定更新シェル
deployment policyの制御が結構煩雑で、こういうふうになってしまいました。
まとめ
こんな感じでよさげなcontinuous deploymentですが、本番リリースがまだなので評価しがたい部分もあります。
本番運用で使ってみた感想は、気が向いたら別途記事にしようかと思います。
Discussion