Amazon S3のコスト削減のためにやったこと

背景

S3のコストが月を追う毎に高くなっていました。 調べたところ、とあるバケットディレクトリに保管している数十TBのデータが支配的だったため削減に取り組みました。ここではその中でやったことをメモとして残しておきます。

一言サマリー

CloudTrailを利用してS3のデータイベントを保管しておくのが重要

コスト削減のためのステップ

以下の流れで進めました。

  1. 削減するべき対象を特定する
  2. 対象へのアクセスを特定する
  3. ストレージクラスの移行や削除を検討する

1. 削減するべき対象を特定する

まずはS3のコストが嵩んでいる理由を特定するため、請求書を眺めたり容量の大きいバケットディレクトリを特定したりしました。とは言っても、なんとなくあたりがついていたため、特定は容易でした。

やったことは以下です。

  1. AWSの請求書をみて、ストレージの保管コストが高いことを知る
  2. バケットメトリクスをみて、バケットサイズ・オブジェクトの合計数を特定する
  3. サイズの大きいバケットを特定したら、さらにディレクトリごとにサイズを取得する
    1. コンソール画面上からもディレクトリごとのオブジェクト数や合計サイズは取得できますが、aws s3 ls s3://<bucket-name>/<path-to-target> --human --recursive --sum とかのほうが便利に思います

S3 インベントリを使えばこのあたりのデータを取るのはもっと楽にできそうですが、僕はCLIと後述のCloudTrailで十分だったため利用しませんでした。   zenn.dev

ここまでで、特定のディレクトリにストレージクラスがStandardのデータがTB単位で増え続けていることがわかりました。

2. 対象へのアクセスを特定する

次に対象のディレクトリを掃除するためにアクセス元を特定しようと試みました。どのオブジェクトに誰がアクセスしているのかを網羅的に洗い出せれば、アクセス元単位で用途を洗い出してストレージクラスの移行や削除を検討できます。

アクセスを特定するには、CloudTrailでS3のデータイベントを取得するのが最も良いと思います。アクセス元・アクセス先オブジェクトの双方が確認できるためです。もちろん取得するだけではなく、分析できる必要がありますが、ボタン1つでAthenaにテーブルが作成できるため分析も非常に簡単です*1

僕はよく調べないまま、CloudTrailのデータを見るのは大変そう....と考え、ストレージクラスの分析を導入し、その結果の解釈に苦戦し、Glacier Deep Archive(以下Gracier DA)移行のコスト見積もりなども行いました。結果的にかなりの時間を無駄に費やしてしまいました。

一応、ストレージクラス分析について記載します(Gracier DA移行についても後述します)。

ストレージクラス分析はAWSが自動的にオブジェクトに対するアクセスパターンをレポーティングしてくれる機能です。配置からの経過時間とアクセス量を測定することで、推奨されるストレージクラスの移行を提案してくれます。

docs.aws.amazon.com

僕はこの機能を使って、例えば「360日が経過したオブジェクトにはもうアクセスがないから削除していい」などの事実を収集したいと考えました*2。しかし結果的には長期間が経過したオブジェクトにも少し(数MBとか)アクセスがあるというレポート結果になり、どうしたものかと頭を悩ませることとなりました *3

ストレージクラス分析を利用することでアクセス量がわかっても、個別のオブジェクトに対するアクセス元の特定まではできません。むしろ想定しないアクセスに対して「これなに...?」となりました。
最終的には特定のオブジェクトにAthena経由でアクセスしていることを同僚が思い出してくれました。そのため結果オーライではあるのですが、それもCloudTrailログを見れば分かったことであり、特定できないがゆえにコスト削減そのものを放置してしまったため、無駄な時間を使ってしまったなぁと反省しています。

3. ストレージクラスの移行や削除を検討する

CloudTrailログを見ることで最終的には削除に踏み切りましたが、ログを見るまではGlacier Deep Archiveへの移行を検討しました。Glacierであればコストも安く済むだろうし、仮にアクセスがあっても復元できるため安牌と考えたからです*4

しかし実際に見積もるにはいくつか考える必要があります。

1. ライフサイクル移行コスト
2. ライフサイクルが移行するタイミングでのメタデータの追加
3. 一部のストレージクラスは、格納後一定期間他のクラスへの移行や削除ができない

要するに、無思考でGlacierに移行してもコストが削減できるとは限りません。
多くの場合「1. ライフサイクル移行コスト」が最も心配になると思います。ライフサイクルの移行を一度にTB単位で実行するとそれだけで結構な費用が発生するためです。特に移行先がGlacier DAの場合のコストは他と比較しても高いです。

Glacier DAの場合、記事作成時点で0.065USD / 1000リクエス

そのため、移行した結果本当に費用が安くなるのかは慎重に検討せざるを得ません。 わかりやすい事例が以下のnoteです。

note.com

このnoteは、ライフサイクル移行によってコストメリットが得られるはずが期待通りにはならなかったという事例です。この原因は「2. ライフサイクルが移行するタイミングでのメタデータの追加」 にあります。

*** S3 Glacier Flexible Retrieval および S3 Glacier Deep Archive ストレージクラスに保存されるオブジェクトごとに、AWSアーカイブされたオブジェクトごとに 40 KB の追加メタデータを請求します。このうち、8 KB は S3 標準料金で請求され、32 KB は S3 Glacier Flexible Retrieval または S3 Deep Archive 料金で請求されます。

参考: 料金 - Amazon S3 |AWS

この注釈に僕は気がついていなかったため、NAVITIMEさんのnoteには助けられました。 移行対象が

  • 一つ一つのオブジェクトサイズが非常に小さく
  • 数が非常に多い

という特徴を持っている場合、メタデータ(40KB)の追加が結果的にコスト削減を阻害する可能性がある点に気を付けましょう。 なお現在は128KB未満のオブジェクトはそもそも移行されないようにデフォルトの挙動が変更されているため、このような不幸はもう発生しないはずです。

参考:Amazon S3 ライフサイクルを使用したオブジェクトの移行 - Amazon Simple Storage Service

また「3. 一部のストレージクラスは、格納後一定期間他のクラスへの移行や削除ができない」点も考慮しましょう。Glacier DAに移行した場合でも、100 TBあれば 200 USDが毎月発生し、それは180日間削除できません*5。削除すると180日分が一括で請求されるというのも地味に怖いですね。もちろんStandardに比較して10分の1以下で済むことは事実です。しかし仮にアクセスがある場合そのコストは高くつきます。

要するに、Glacierへの移行であれば安心してコスト削減できるとも簡単には言えず、しっかりと見積もりが必要でした*6

まとめ

結果的にはCloudTrailログをもとにライフサイクルルールで削除設定をいれることで、バッサリ削除することができました*7
そして、

  • CloudTrailによるアクセス元の分析は簡単にでき、効果的であること
  • 監査や法の要件として長期間保存しなければならないケースを除き、なるべく削除する方針で検討すること
  • 時間が経ってから消すのはハードルも高いので、初期の設計段階でライフサイクルを設定しておくのが大切であること

ということを学びました。

以上です。

*1:ただしボタン1つで作成するテーブルにはパーティションがないため、実用的ではありません。パーティション射影を使用して Athena で CloudTrail ログ用テーブルを作成する を参考にパーティションを活用するのがよいと思います。

*2:一時的に保管しておくためのディレクトリだったので削除する前提で調査していました

*3:ちゃんと確認していませんが、バケットサイズを確認するときにaws s3 ls等のCLIを利用していたのが原因ではないかと後から気が付きました。アホですね...

*4:ちなみにAthena経由で参照していたものはGoogle BigQueryに移行しました。

*5:参考:最小ストレージ期間

*6:だったらIntelligent Tieringやストレージクラス分析の推奨をそのまま適用するのが簡単という話もあるのですが、一度Intelligent Tieringや推奨設定にしてしまうと心理的にそれ以上の削減余地を検討しにくいですし、インフラのコストは積み重ねであるため、これを期に可能な限り整理するのが事業にとってプラスだという気持ちがありました。

*7:ちなみにライフサイクルルールを設定すると次のUTC0時(日本時間で9時)に初回が実行されます。例えば30日で削除する設定をいれると、このタイミングで30日が経過しているオブジェクトが一気に削除されます。参考