AWS の Amazon CloudFront で継続的デプロイ(CD)をしてみる

クラウドエンジニアの小寺です。
CI/CD にハマっている私ですが、今回は有名な Code シリーズではなく、Amazon CloudFront の「継続的デプロイ(=CD)」についてお話し、実際に試してみたいと思います。
目次
Amazon CloudFront の継続的デプロイ機能とは
Amazon CloudFront は AWS が提供する CDN サービスで、本ブログでも何度か取り上げられたことがあるかと思います。クライアント PC からの HTTP リクエストを受け付け、TLS を終端してオリジン(Amazon EC2 や Amazon S3 など多数設定可能)にトラフィックを送信します。
そんな Amazon CloudFront ですが、実は継続的デプロイ機能も備わっており、昨今の CI/CD ブームの中でも構成要素として検討いただけるかと思います。
主な要素としては「ブルーグリーンデプロイ」と「カナリアリリース」になりますが、それぞれの言葉の定義を確認したいと思います。
【ブルーグリーンデプロイ】
ブルーグリーンデプロイとは、安全なデプロイと瞬時のフェールバックを実現するデプロイ方式で、簡単に言ってしまうと現状の稼働している本番環境(ブルー)とは別にステージング環境(グリーン)を作成し、アプリケーションのデプロイを行うというものです。切替時に本番環境が残っているので、切替時に問題があったとしてもすぐに切り替えられることが利点です。
【カナリアリリース】
ある特定のユーザについては新アプリケーションを利用してもらい、しばらく様子を見てから全ユーザにリリースするという手法になります。特定のユーザの指定方法として、Amazon CloudFront ではパーセンテージを決めて本番環境またはステージング環境にトラフィックを流す方法と、特定の HTTP ヘッダーが設定されたユーザのトラフィックだけステージング環境に流すという方法の二通りがあります。
ではまずは通常の通信について図を見ながら解説していきましょう。
Amazon CloudFront と Amazon S3 でウェブサイトを提供している構成です。ユーザーがウェブサイト(bluegreeens3.sub.naretok.xyz)へブラウザからアクセスすると CloudFront へ到達し、そこからオリジンとなる S3 へトラフィックが流れます(blue/index.html)。

次は継続的デプロイが発動した時の図です。
予め次期本番用のフォルダ(green)を S3 にアップロードし、CloudFront のステージング Distribution のオリジン設定などを調整しておきます。継続的デプロイを CloudFront にて実行するとステージング Distribution への経路ができ上がります。ステージング Distribution に誘導するユーザのルール設定は二通りあり、パーセンテージで本番・ステージングにトラフィックを分ける方法と、特定の HTTP ヘッダーを持つリクエストをステージングに流す方法があります。
この状態で、本番とステージング環境を両方保持してデプロイを行うブルーグリーンデプロイと、通信をルールによって振り分けるカナリアリリースができています!

あとは十分にテストした後に切り替えを行うだけです。
ステージング Distribution がそのまま本番に昇格するのではなく、ステージング Distribution の設定をそのまま本番 Distribution へ上書きするのがミソです。キャッシュを有効にしている場合はキャッシュクリアが必要です。
後片付けとして S3 内の旧本番フォルダ(blue)を削除などする必要がありますが、いつまで保持し、いつ削除するかのメンテナンスは別途考えなければいけません。やり方としては、S3 内のバケットは固定(blue と green)とし、CodePipeline + CodeCommit + CodeBuild で S3 にファイルをデプロイ(CodeBuild で aws s3 sync 実行)する仕組みを作っておくことが考えられますが、次回で試した結果を共有できればと思います。

AWS 設定のキモを解説
既にリソースは作成済みですが、何点か設定の肝となる部分を実際の画面キャプチャを見ながら解説していきます。
S3 オリジンは OAI を有効にする
これは必須ではないのですが、S3 はできるだけ公開したくないのでこのようにしています。

CloudFront でルートドキュメント及びオリジンパスの設定を行う
今回は S3 へのアクセスを CloudFront からのみに限定(OAI)したかったので、ルートドキュメントに“index.html”を設定しました。
(HTML のファイル名は実ファイルに合わせて変更してください)

また、S3 内のディレクトリ構造からリクエストをそのまま流すとファイルが存在しないエラーが発生するので、オリジンパスに追加(/blue)しています。

この時点でウェブサイトが見れます。

設定は以上です。
実際に CloudFront で継続的デプロイをやってみた
それではやってみましょう。
まずはステージング Distribution がないので作成します。今回は初回なので作成しますが、切替後もステージング Distribution は残りますので、次回からは作成不要です。
Create staging distribution をクリック。

そのまま次へをクリック。

ステージング Distribution 用に設定を変更。
今回はオリジンのオリジンパスを /green に変更して次へをクリック。
(変更前)

(変更後)

トラフィックの振り分け方法を指定。
パーセンテージを選択した場合はスティッキーセッションも有効化可能です。
今回は HTTP ヘッダーの振り分けを指定して次へをクリック。
※ Enable を有効化するとステージング Distribution へのトラフィック振り分けが有効になるので、適宜無効化してください。

最後に Create staging distribution をクリック。

ステージングができ上がります。

Amazon S3 へ green 環境をアップロード。

この時点で HTTP ヘッダーを設定したクライアントから green 環境が見れますので、Chrome 拡張機能の ModHeader でヘッダー設定します。

見れる!・・・と思ったのですが見れませんでした。
これは OAI が関係しており、ステージング Distribution 用に追加が必要でした。

S3 のバケットポリシーにステージング Distribution のリソース ARN を追記します。

見れました。

内容は OK なのでステージング Distribution の設定を本番 Distribution へ反映すべく、Promote します。

ポップアップが出ても気にせず Promote をクリック。

本番ステージングのオリジンパス設定が /green に変更されています。

HTTP ヘッダーを無効化してドメインアクセスすると、キャッシュが残っているためまだページが変わりません。

キャッシュ削除します。

削除が進行中でもページがバージョン2に変わっていました。

なお、2回目以降はステージング Distribution の設定を変更後、Enable ボタンを押すだけで継続的デプロイが発動します。

AWS Amazon CloudFront の継続的デプロイ機能(まとめ)
今回は CloudFront における継続的デプロイ(CD)をお届けいたしました。この機能が出てきたことにより、今までの Amazon Route 53 による不安定な切替(DNSキャッシュ要因)をせずに済むようになり、手順も非常に簡潔でわかりやすいため、取り入れやすくなりました。
今回は Amazon S3 を対象にしましたが、オリジンが Amazon EC2 (ALB) でも可能です。動的コンテンツを Amazon EC2 に配置し、Amazon S3 に静的コンテンツを配置して CloudFront のオリジンに両方を設定することで、一貫性のある切替ができるかと思います。
ご興味がございましたら、弊社までお気軽に お問い合わせ ください。
それでは、皆様も良い CI/CD ライフを!

元記事発行日: 2024年04月22日、最終更新日: 2024年04月18日