概要
AWS の CloudFrontと S3 で配信している部分のデータ転送量が大きく請求が膨らんでいることが分かりました。
そのため Cloudflare への移行を検討し、コスト削減を実施したいと思います。
しかし、CloudFront では複雑なビヘイビアとキャッシュ設定がされているため、Cloudflare で実現できるのかどうかを十分に検証していく必要がありました。
今回は Cloudflare の Free ~ Pro および Business プランの契約を前提としています。Enterprise プランでは CloudFront と同等の機能が使用できるため予算に余裕があればそちらを検討してみてください。
実現したいこと
今回は CloudFront と S3 で配信している部分の料金が高いので、 その部分だけ Cloudflare と S3 で配信してコスト削減を行いたいと思います。
しかし、サブドメインを利用せず、一つのドメインでサイトを運用するため CloudFront も Cloudflare を経由するしかありません。
リクエストの流れは以下となります。
- stg.example.com/* -> CloudFront
- stg.example.com/uploads/* -> S3
必要なことは
- Hostヘッダーのオーバライドができる
- ルーティング先のエンドポイント(オリジン)を複数管理できる
- サイトの管理ドメインは一つとし、パスによってエンドポイント(オリジン)を変更できる( static.example.com などの別のサブドメインを用意できるのであれば DNS だけで対応可能です。 )
となります。つまり、CloudFront のオリジンとビヘイビアの仕組みを Cloudflare で実現してみます。
Cloudflare に CloudFront の設定を移して完全に移行できたらいいのですが、エンタープライズ契約でなければ、キャッシュキーにヘッダーやCookie を入れたり、細かなTTLの設定ができません。
ホストヘッダーのオーバーライドもできず、複数のオリジン設定もできませんでした。
また、ページルールの転送URLを使用して、S3に向けた別ドメインに転送することも考えたのですが、バケット名とドメイン名の一致が必要だったりと理想の状態にもっていくことはできませんでした。
https://developers.cloudflare.com/rules/origin-rules/
Cloudflare Load Balancing で実現できる
しかし、以下を利用して実現できます。
- Cloudflare DNS
- Cloudflare Cache Rules
- Cloudflare Worker
- Cloudflare Load Balancing
- Amazon S3
それぞれ、トラフィックシーケンスに沿って説明します。
Cloudflare DNS
特に設定は不要です。Cloudflare の利用開始に必要ですが、ロードバランサーを設定した時点で、そちらの設定が使用されるようになります。
Cloudflare Cache Rules
Cache Rules に関しては、Cloudflare でキャッシュしたくない(bypass)オブジェクトとキャッシュしたいオブジェクトでルールを分け、
その他は、すべてキャッシュせず bypass する設定を行いました。キャッシュキーを細かく制御したい場合はエンタープライズ版を契約する必要があります。
Cloudflare Worker
S3 にリクエストを流すには Authorizationヘッダを空にする必要がありました。
理由としては、検証環境ではBasic認証がかかっておりリクエストヘッダに Authorizationヘッダが入ってしまい Unsupported Authorization Type で400エラーになるからです。
構成ルールやオリジンルールでヘッダの上書き等は可能なのですが、エンタープライズでなければヘッダの修正はできないようです。
そのため今回は以下のようなコードを Cloudflare Worker で実行させ、Worker を経由させることでヘッダーの修正を行います。
また、キャッシュキーにCookieやヘッダな値を入れるなどの細かな変更などもエンタープライズでしかできないのですが、Worker で実装すれば可能です。
ただし、運用面を考えるとあまり Worker で難しいことはしないほうがいいかもしれません。
Worker の実行にかかる料金も気になるところですが、キャッシュヒットしてしまえば実行されることはないので問題ないと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) async function handleRequest(request) { // リクエストヘッダーを取得 const headers = new Headers(request.headers) // Authorization ヘッダーが存在する場合、その中身を空にする if (headers.has('Authorization')) { headers.set('Authorization', '') } // 新しいリクエストオプションを作成 const requestOptions = { method: request.method, headers: headers, body: request.body, redirect: request.redirect } // 新しいリクエストを作成 const modifiedRequest = new Request(request.url, requestOptions) // オリジンサーバーにリクエストを送信 const response = await fetch(modifiedRequest) return response } |
作成した Worker を使用するように最後にルートの設定を行ってください。
Cloudflare Load Balancing
Cloudflare Load Balancing を使用するには追加で月5ドル必要となります。しかし、CloudFrontにかかる料金を考えればメリットが大きいと思います。
追加でエンドポイントを増やしたい場合は別途追加料金が必要となりますが、今回はCloudFrontへ流すエンドポイントと、S3に流すエンドポイントの2つが登録できればいいので5ドルで足ります。
そして、今回のポイントとしてカスタムルールを設定します。特定のパスの時に、デフォルトのエンドポイントではなく、別のエンドポイントに流す設定ができます。
エンドポイントのプール作成の注意ですが、Host ヘッダを変更する必要があります。 Host ヘッダを変更しない場合は、アクセスした際にバケットが存在しないとなり、404エラーになってしまいます。
そうならないためにはエンドポイントの Hostヘッダーを S3エンドポイントのドメインと合わせる必要があるので以下のキャプチャのように設定してください。
これでロードバランサーの設定は完了です。
Amazon S3
リクエストを流す先の S3バケットはプライベートな設定(パブリックアクセスをすべてブロック)にしています。
そのため Cloudflare を経由したリクエストは許可するように、Cloudflare の IPをバケットポリシーで許可するようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
{ "Sid": "AllowCloudflareAccess", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::bucket-name/*", "Condition": { "IpAddress": { "aws:SourceIp": [ "173.245.48.0/20", "103.21.244.0/22", "103.22.200.0/22", "103.31.4.0/22", "141.101.64.0/18", "108.162.192.0/18", "190.93.240.0/20", "188.114.96.0/20", "197.234.240.0/22", "198.41.128.0/17", "162.158.0.0/15", "104.16.0.0/12", "172.64.0.0/13", "131.0.72.0/22" ] } } }, |
Cloudflare の IP は https://www.cloudflare.com/ja-jp/ips/ を参照して最新の情報を入手してください。
これで全工程は完了となります。
最後に
Cloudflare から CloudFront と S3 にリクエストを流すということをやってみましたが、本当は Cloudflare に完全移行できればそれが良いです。
しかし、Cloudflare ではまだエンタープライズ契約でなければ利用できない設定も多いため、このような構成になりました。料金を比較してベストな構成を実現していただければと思います。
個人的に Cloudflare は機能開発も盛んでここ数年で最も勢いのあるCDNだと思っています。
コンテンツ配信だけではなく、ネットワーク(Web)・セキュリティ、ゼロトラストやエッジコンピューティングがとても優秀ですし、かなり注力しているようです。
Cloudflare One: https://blog.cloudflare.com/ja-jp/introducing-cloudflare-one/
私個人の費用的にエンタープライズは契約できないのですが、できる限り Cloudflare を触って検証した結果をブログにしていきたいと思います。
(いつかエンタープライズでも検証してちゃんと比較したい….)
Cloudflareとは: https://www.cloudflare.com/ja-jp/learning/what-is-cloudflare/