CloudFrontでコストを30%以上削減するために、やるべきこと ～AWS100本ノック～ 9/100

# はじめに

Webアプリケーションなどのフロントエンドでよく使われるCloudFrontですが、コスト削減を見込める方法を調べたのでこの記事で紹介します。

そもそも、なぜこの記事を書こうと思ったかですが、AWSのコスト削減の仕事を振られたのがきっかけです。
対象のAWSアカウントでは他にはECSやRDSを利用しているので、おそらくこれらが一番お金かかっているだろうなーと思い、`Billing and Cost Management`で請求額を試しに見てみました。

すると、CloudFrontに`471$`と一番お金がかかっていることがわかりました。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/d509ae2b-bd18-fb7d-f83c-d1974e9b190e.png)

# CloudFrontって何にお金がかかるのか

そもそもCloudFrontって、何に課金されるのかってことなんですが主に以下になります。
- インターネットへのリージョンレベルのデータ転送(OUT) ←今回ほとんどこれにお金がかかっていました
- オリジン(S3など)へのリージョンレベルのデータ転送(OUT)
- HTTP/HTTPSのリクエスト数
- その他(CloudFront関数の呼び出し回数、Lambda@Edgeの呼び出し回数など)

:::note info
なお、他のAWSサービスと同様CloudFrontにも無料枠があります。
CloudFrontでは2024/10現在で以下が常時無料枠になります。
小規模のWebアプリケーションなら無料利用枠で賄えるかもしれません :thinking: 
- 1か月あたり、1TBのインターネットへのデータ転送
- 1か月あたり、1000万件のHTTP/HTTPSリクエスト
- 1か月あたり、200万件のCloudFront関数呼び出し
- 1か月あたり、200万回のCloudFront KeyValueStoreの読み取り
- 無料のSSL証明書
:::


# キャッシュ設定を確認してみた

CloudFrontを使うことによってデータをキャッシュし、オリジンへのリクエストを減らせるわけですが、データ転送量が多いことからキャッシュ設定周りが怪しいのかなーと思いました。
なので、`キャッシュ統計`を確認してみました。

すると`ミスが94%`、`ヒットが0%`とまったくキャッシュを使えてないことがわかりました :cry: 

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/fdfa2832-5b08-7599-0dd8-bd6bc8946ef0.png)


実際の設定を確認すると、TTL設定が全て0秒(=キャッシュしない)になっていたため、都度オリジンにデータを取りにいっていたようです。
さらに、圧縮も無効になっていたため、その分データ転送量が多くなってしまっていたようです。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/2b1180b2-0608-135f-1965-b75a1d4c6e05.png)

:::note info
個人的に全く知らなかった`Brotli`ですがGoogleが開発した圧縮アルゴリズムで、gzipより20%くらい圧縮率が良いらしいです :smile: 
:::

# キャッシュ設定を修正してみた

ということで、`TTL設定`と`圧縮サポート`を以下のように修正しました。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/c19b14db-05ec-0813-81de-e8892bfe16a3.png)

これでデフォルトでは1日はキャッシュし、また圧縮したファイルを配信できるようになりました :smile: 
TTLの挙動については[公式サイト](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/Expiration.html#ExpirationDownloadDist)に記載がありますが、[こちらの記事](https://christina04.hatenablog.com/entry/cloudfront-ttl-flowchart)にフロー形式でまとめてくれています。
オリジンからのレスポンスに`Cache-Control`や`Expires`ヘッダーがあるかによってTTLの挙動は変わるようです。

さらに、圧縮を設定したことによってサイズが`1,000～10,000,000バイト`のオブジェクトを圧縮してくれます。
どの圧縮形式にするかは、ビューワー(ブラウザなど)のリクエストヘッダーの`Accept-Encoding`に依存しますが、Chromeなどの代表的なブラウザであればどちらもサポートしていますので、どちらも有効にしておけば良さそうです。

:::note info
自前でキャッシュポリシーを作成することもできますが、ユースケースに応じたマネージドキャッシュポリシーをAWSが用意してくれているのでまずはこれを利用するのでも良さそうです。
※キャッシュ最適化であれば、`CachingOptimized`という名前で用意されています
:::

## GzipとBrotliどちらも設定する場合の挙動

GzipとBrotliとちらも有効にしていて、ビューワー(ブラウザなど)がどちらもサポートしている場合は[公式](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/ServingCompressedFiles.html)に記載がある通りCloudFrontは`Brotliを優先`します。
※`br`がBrotliです

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/5252a5b6-02a9-0b77-9ee1-37246002fe43.png)

## キャッシュヒットするか確認

TTL設定後のキャッシュ統計を見ると、`ヒットが86%`になっていてちゃんとキャッシュが出来ていることが確認出来ました。

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/e88fa75d-268d-a16a-e660-709211b0e729.png)


# CloudFront Security Savings Bundle

EC2などと同様にCloudFrontにもリザーブドプランのようなものがあります(最近知った)
1年間、月間の使用料金をコミットメントすることによって`最大30%`請求額を節約することが出来ます。

## 購入してみる

左メニューの`購入`をクリックすることで、過去の請求額から自動的に推定してくれた推奨コミットメントが表示されます。
毎月`330$`のコミットメントをすることで、`471$`分利用することが出来ます。
※見てわかる通り、AWS WAFの料金もカバーされるようです
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/9a4947dc-2460-498a-6c79-7831bae92d50.png)

この画面で、購入コミットメントを入力します。
毎月の料金が一定であれば`毎月のコミットメント支払い`は前の画面で表示された金額を入力すればいいと思います。
また、1年以上使うのであれば、自動更新を有効にしておけば、毎年購入作業を行う必要はなくなります。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/82d0947f-0bd0-f6ff-2114-a5c4d2244933.png)


最後に確認画面が出るので、`購入`をクリックし、完了です！
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/fa1913d8-4ab6-8575-d6dd-5e2b7e92d755.png)

:::note warn
月毎のコミットメントになるため、利用量が少ない場合にはコミットメントは繰り越されませんので、注意が必要です。
なので、利用量が予想できる、かつ、本番環境以外では購入は見送るべきかもしれません
:::

# おわりに
今回はCloudFrontのコスト削減方法について説明しました。
思いがけず、CloudFrontの料金が高くなってしまった人、高くならないようにしたい人の参考になれば幸いです:bow: