テクノロジーグループの冨田です。
北欧、暮らしの道具店とクラシコムのコーポレートサイトにCloudFrontを導入しました。
以前から画像についてはCloudFrontやimgixを利用し配信していました。
今回はサイト自体を配信するようにしました。
背景
2022年8月に東証グロース市場へ上場しました。
という動機からCloudFrontを導入しました。
やったこと
Cognitoによる認証
クラシコムの検証環境(ステージング環境)はALBでCognitoによる認証をかけており、社員のみアクセス可能にしていました。
今回ALBの前段にCloudFrontを導入しましたが、そのままの構成でCloudFrontを前段に置いてしまうと社員以外もキャッシュされた内容がCloudFrontで閲覧可能になってしまいます。
検証環境(ステージング環境)と本番環境でなるべくインフラの構成を合わせておきたいのでLambda@Edgeでcognito-at-edgeをデプロイし、Cognitoでの認証をかけました。
Lambda@Edgeの制約で下記の点ではまってしまいました。
ALBへのリクエストの制限
CloudFrontを用意したため、ALBに直接アクセスされてしまうと用意した意味がありません。
CloudFrontからALBへのアクセスはリクエストにカスタムHTTPヘッダを付与し、カスタムヘッダが付与されているものだけに応答するようにしてあります。
2022年2月からCloudFront マネージドプレフィックスリストが用意されたため、ALBのセキュリティグループで、CloudFrontからのインバウンドHTTPSアクセスのみを許可するようにしました。
また、万が一に備えてステージング環境においてはALBでもCognitoによる認証は引き続きかけています。
はまったこと
クライアントのIPアドレス、スキーマの取り扱い
ECS Fargate上でNGINXとphp-fpm、Laravelを利用しています。
NGINXのアクセスログでクライアントIPアドレスやリクエストスキーマを記録しています。
また、Laravel上でもクライアントIPアドレスやリクエストスキーマを利用しています。
クライアントのIPアドレスはNGINXで `real_ip_header X-Forwarded-For;` リクエストヘッダ、 `set_real_ip_from 192.168.1.0/24;` で信頼できるアドレス、 `real_ip_recursive on;` で信頼されない最後のアドレスを取得するようにしていました。
CloudFrontのIPアドレスはJSON形式で公開されていますが不定期に変更されるため、`set_real_ip_from`を自動的に更新するのは少し面倒です。
クラシコムではインフラのアドバイザーとしてカヤックの藤原さんにアドバイス、レビューをしていただいています。
`CloudFront-Viewer-Address`や`CloudFront-Forwarded-Proto` リクエストヘッダを利用すれば良いとアドバイスをいただきました。
`CloudFront-Viewer-Address`はIPアドレスとポート番号が含まれているため、IPアドレスのみを利用したい場合には分割する必要があります。
NGINXのLua moduleを利用し分割しました。
【nginx】CloudFront, ALBどちらからのリクエストでも適切なremote_addrを取得する【php-fpm】 - Qiita
NGINXのオフィシャルのDockerイメージそのままではLua moduleは利用できないため、オフィシャルのドキュメントをもとにビルドしました。
運用は無事回っているもののデプロイ時にLua moduleのビルド時間がのびてしまいました。
今後の課題としてはビルド方法の見直しを行うか、OpenRestyのイメージを利用するか、CloudFront Functions側に任せようかなと思います。
カナリアリリースやメンテナンス
カナリアリリースやメンテナンス時にALBのリスナールール 送信元IPアドレス に 作業者のIPアドレスを設定して動作確認をしていました。
CloudFrontを経由することになり送信元IPアドレスがCloudFrontになってしまいました。
ALBのリスナールール の HTTPヘッダで ヘッダ名は `CloudFront-Viewer-Address` を指定し、比較文字列には 作業者のIPアドレスを指定しました、ポート番号はワイルドカード文字列を利用しました。
設定の例
203.0.113.1:*
並行運用
日中に旧ALBからCloudFrontへDNSの切り替えを行い、DNSのキャッシュが切れるまで並行運用を行いました。
DNSを変更して3分後には大半のトラフィックはCloudFront経由に切り替わったのですが、CATV系のプロバイダやBotは1週間経過しても旧ALBへのアクセスが続きました。
ALBも運用中にIPアドレスが変わることもあるということで旧ALBは退役させました。
ALB切替時のリクエスト数の変化
まとめ
CloudFrontの導入で7/12のテレビ東京系列のWBS(ワールドビジネスサテライト)でとりあげられたタイミングや、8/5の上場当日も無事乗り切ることができほっとしました。
一点悔やまれるのはALB側のWAFにレートリミットを設定してしまい、一部のリクエストをブロックしてしまいました。
今後も改善を重ね「サイトに快適・安全にアクセスできて当たり前」な状態にしていきたいと思っています。
クラシコムは上場しましたが、エンジニア7名体制でほぼ内製&運用しております。
まだまだシステムには改善の余地があるので外部SaaSなどの選定なども経験しやすいかなと思います。
また、バックエンドやネイティブアプリ中心に開発していた私ですがアドバイザーにレビューしていただけるので心強いです。
レコメンドやサイト内検索のチューニングやフロントエンドの最適化などなど やりたいことはいっぱいあるのでクラシコム、北欧、暮らしの道具店に興味を持った方はお気軽にご連絡ください。