はじめに
新卒3年目のらぴおです。入社当初からエンジニアとして広告事業を営むZucksでアドネットワークの開発、運用に携わっています。
Zucksでは、2022年夏頃から円安の影響でサーバ費が上昇しコスト削減の温度感が高まっていました。
そこで、 僕が携わるアドネットワークにおいては、少ない作業量で大きい見直し効果が期待できそうなAWS S3のコスト最適化に取り組む ことになりました。
S3全体で月々のコストが $ 13,000 を超えており、特に広告配信関連のログデータが大部分を占めていました。
今回は、僕が実施したコスト削減調査と実施プロセス、その成果を共有します。
S3のコスト削減は、以下のアプローチで行います。
- オブジェクト数を減らす
- 最適なストレージ階層に移行し保存する
これらの取り組みにより、月々のストレージコストを $ 13,000 から $ 5,000 に削減 することができました。
コスト削減の対象となるAWS S3バケット
今回は、 特にS3容量の大部分を占めていた広告配信関連のログデータを対象とした最適化 に取り組みました。
前提として、Zucksが管理しているS3には多数のバケットが存在するため、まずは どのバケットに対して削減対応を行うことが効果的なのかを調査 しました。
そもそもコスト原因が分からなかったため、コスト原因調査から始めました。
AWS CostExplorerを用いた結果、バケットの容量に対する課金が支配的であることが判明しました。
より詳細な対象調査・選定のために、以下の作業を行いました。
- どのバケットが容量を占めているかの把握
- S3のStorage Lensが役立ちました
- タグが不足しているリソースにタグを付与
- タグが付与されていることで, Cost Explorerで細かく見れるようになる
- バケットごとの詳細なコストチェック
- 改善後のコスト変化のチェック
- タグが付与されていることで, Cost Explorerで細かく見れるようになる
- 移行コスト試算のためのスクリプト作成
- いくつかコスト試算のための既存ツールがありますが、ストレージ階層や流量、保存期間などまで含めていい感じに出せるのが見当たらなかった
- 移行先のストレージを決定するためのスクリプトを自作し、コスト見積もりを実行
- 正直なところ、AWS側でライフサイクルルールから想定コストとかを出してくれる機能とか追加してほしい気持ちもありますが...
最適化の対象としたバケットは、主に以下の3つです。
- 広告配信ログ
- LoadBalancer のリクエストログ
- CloudFrontのログ
これらのバケットは、合計でアカウント全体のオブジェクト 容量の 9割以上 を占めていました。また共通点として、全てStandard階層に保存されていること、保存された後は参照される機会が稀 という特徴もあります。
1. 配信系の通知
1つ目は、配信に関わる通知を保存しているバケット(以下、広告配信ログバケット) です。例として以下の情報が保存されています。
- 広告リクエスト
- インプレッション
- クリック
- コンバージョン
- アプリイベント
- 広告表示のエラー通知、etc…
広告配信ログはサーバからfluentdによってS3上に保存された後、非同期でBigQueryに送られます。
配信に関する分析や調査はBigQuery上で行われるため、このバケットに保存されたデータは普段の運用で参照される機会は稀 でした。
2. LoadBalancer のリクエストログ
2つ目は、配信サーバにひもづくLoadBalancer(以下、LB)へのリクエストログを保存するバケット(以下LBログバケット) です。複数のLBがそれぞれ別々のバケットにログを保存しています。
3. CloudFrontのログ
3つ目は、広告アセット(画像や動画)を配信する際に使用するCloudFrontのログを保存するバケット(以下CloudFrontログバケット) です。こちらもLBログ同様、複数のCloudFrontがそれぞれ別々のバケットに保存してます。
実施したコスト削減対策
コスト削減には以下の3つの対策を実施しました。
3.1 オブジェクト保存期間の変更
広告配信ログに関しては 保存期間を元々540日分から365日分 に変更しました。
調べるとBigQuery側には1年分保存しておく運用だったため、1年分のデータは調査や再取り込み等が可能なように保存すればよく、それ以上の保存は必要ないと判断 しました。
LB ログバケットと CloudFront ログバケットはもともと保存期間が異なりましたが、 どちらも保存期間を 1 ヶ月と短縮し統一しました。これらのログは 実際の運用でほぼ参照されないため、問題発生時の調査を考慮し1 ヶ月分のログがあれば十分と判断しました。
上記の条件をバケットのライフサイクルルールとして設定しました。
また保存期間の判断の際に以下の点も考慮し、確認しつつ進めていました。
- 過去の調査対応でどの程度過去分まで遡って調査したのかを確認
- GitHub Issueに調査時の作業が記録されているのが役立った
- Zucksでは、作業内容をGitHub Issuesに分報のように残している
- 事前にS3アクセスログを有効にしておくとより調査が行いやすかったかもしれない
- GitHub Issueに調査時の作業が記録されているのが役立った
- エンジニアメンバーに対して方針の確認
- 監査基準への抵触がないことを確認
3.2 ストレージ階層の移行
次にストレージ階層の最適化を行いました。
AWS S3では、複数のストレージ階層があり、ストレージやIOにかかる料金、可用性や取り出し時間等が異なります
事前の予想と反して、ストレージ階層の最適化については、バケットの中身をまるっと低アクセス階層ストレージに移動すればコストが下がるとは限らないことがわかりました。 オブジェクトの容量、保存期間、移行先階層によっては、移行コストの方が高くついてしまうことがあるためです。
シミュレーションの結果、以下のように移行する方針となりました。
- 広告配信ログバケット
- 1ヶ月経過した 1MB 以上のオブジェクトを Glacier Instant Retrieval(以下、Glacier IR) に移行
- LB ログ, CloudFrontログバケット
- 1日経過した 2MB 以上のオブジェクトを Glacier IRに移行
移行先をGlacier IRにした判断理由は以下です。
- 保管ログに対するアクセス頻度が数ヶ月に一回程度であること
- コストメリットを十分に受けることができること
- AWS Athenaでのクエリが可能なこと
- 稀にHTTPリクエストの詳細を調査することがあり、手間なくAthenaで分析を行えるのは便利だと判断
他のストレージ階層の選択肢について
Glacier IRの他に、Glacier Flexible ArchiveやGlacier Deep Archiveなども検討しましたが、オブジェクトの取り出しに時間がかかるのが懸念事項としてありました。
今後、「より低アクセス階層で問題なさそう」と判断ができれば、後から移行することも可能です。今回は、Glacier IRでの様子見のステップを踏むことにしました。
オブジェクトサイズによる移行対象の選別
移行対象とするオブジェクトをサイズで指定すると、コストメリットを受けられるものだけに限定できます。具体的には、事前にライフサイクルの運用案を2つ考えました。
- 命名規則からサイズの大きな傾向のオブジェクトを絞る
- サイズ指定
結論からいうと、今回は後者のサイズ指定を選択しました。
命名規則からGlacier IRに入れるオブジェクト対象に移行する案は、結果的に考慮することが増えるため廃案になりました。命名規則を利用する場合、運用変更や命名ルールの変更、ログファイルのサイズ傾向変化があった場合に追従できなくなる懸念があります。追従できず気づけなかった場合、想定外の課金が発生してしまいます。
これに対し、サイズ指定を行う場合はただオブジェクトサイズのみを気にすればよく、今後の運用変更に対しても強い設計と判断しました。
3.3 細かいオブジェクトの束ね作業
これは、まだ実現できていない構想中のアイディアです。
S3 Standardから低アクセス階層ストレージに移行する場合、オブジェクトサイズが小さいと、コストメリットを享受できない 場合があります。短期間だけ記録する小さなオブジェクトをGlacier IR移行対象として扱うとコスト的にメリットがさほどありません。
より移行のコストメリットを享受するには、移行対象にするオブジェクトのサイズを大きくすることが効果的 です。ログの場合、複数のファイルを1つのオブジェクトとして結合する方法で、1オブジェクトあたりのサイズを大きくすることができます。
広告配信ログバケットではStandardバケット上に小さなオブジェクトが大量にある状態です。具体的には1MB以下のオブジェクトが容量の50%、オブジェクト数の90%程度を占めています。
このため、上記の方法を利用しGlacier IRに転送できるとよりコストメリットを享受できると予想しています。
現在、定期的にオブジェクトを束ねるバッチの実装作業中であり、更なるコスト削減に向けて頑張っています。
似たような事例として以下があります。
3.4 改善策を通して
S3のコスト削減は、基本的に以下の方針になります。
- オブジェクト数を減らす
- 最適なストレージ階層に移行し保存する
もちろんバケットの状態や運用などによって 最適な施策は異なってくるので、様々なパターンでコストを細かくシミュレーションすることが大切 だと感じました。
また、施策のパターンを検討するにあたり、コストやバケットの状態を細かく見える化することも有効でした。
あとコスト削減は成果が目に見えるので楽しいですね。一方で、コスト削減そのものが目的ではなく、 事業を滞りなく前に進めるためのコスト削減である ことは忘れてはいけません
コスト削減の結果と今後の展望
これらの取り組みにより、月々のコストが $13,000 から $5,000 まで削減することができました。 今後は、作業中のものを含めて $3,000 /月くらいまで削減するのが一旦の目標です。また、チームのコスト削減大臣としてAWS全般のコストについても見直しに取り組んでいく予定です。