バージョニング有効なS3バケットが100TBを超えていたので旧バージョンオブジェクトの扱いやコスト削減メソッドについて調べてみた

バージョニング有効なS3バケットの総容量が100TBを超えてしまい、想定していた18TBを遥かに超えた状態となったので原因を調べていました。S3における論理削除は大きなコストに直接つながるので注意が必要です。
2021.05.24

業務で使っているバージョニング有効なS3バケットの総容量が120TBを超えてしまい、利用費が非常に嵩んでしまったこともあり掃除をしていました。チリも積もればとはいいますが、月々に積まれていくサイズが15TB近くあったのは流石にチリとは呼べないなーと感じています。

オブジェクト作成時にタグを付与して、ライフサイクルルールにてタグ付きオブジェクトを削除する形にしていました。以下の通り、割とよくある設定かと思います。

  1. タグ付きオブジェクトのうち、作成から一定期間経過したものを古いバージョンに移行させる
  2. タグ付きオブジェクトのうち、古いバージョンのオブジェクトを一定期間後に削除する

ところが、暫く様子をみていたところ、CloudWatch経由にて総容量が意図した形には減っていないことに気が付きました。タグ付与ルートから漏れていたオブジェクトもありましたが、私自身がオブジェクトのライフサイクルに伴う挙動を正確に理解しきれていなかったことも原因です。ただ、意外とありがちな事と聞き、具体的な注意点もあわせて書いてみました。

バージョニングが有効な状態にて古いバージョンへ移行することで起こること

まず、前提知識として。

Amazon S3 は、最新のオブジェクトバージョンを削除するのではなく、削除マーカーを追加してそれを最新バージョンにします。これにより、最新バージョンは以前のバージョンとして保持されます。

古いバージョン送りとなったオブジェクトのバージョンを確認してみるとDeleteMarkersがついています。IsLatestの値をみると分かりますが、DeleteMarkerが最新のステータスになります。

% aws s3api list-object-versions --bucket xxxxxxxxxxxxxxxxx --prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.csv.gz
{
    "Versions": [
        {
            "ETag": "\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"",
            "Size": 151959720,
            "StorageClass": "STANDARD",
            "Key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.csv.gz",
            "VersionId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "IsLatest": false,
            "LastModified": "2020-08-22T09:31:14+00:00",
            "Owner": {
                "DisplayName": "xxxxxxxxxxxxx",
                "ID": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            }
        }
    ],
    "DeleteMarkers": [
        {
            "Owner": {
                "DisplayName": "xxxxxxxxxxxxx",
                "ID": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            },
            "Key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.csv.gz",
            "VersionId": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
            "IsLatest": true,
            "LastModified": "2021-05-13T00:00:00+00:00"
        }
    ]
}

これが意味することとして、aws s3apiやawscliによるaws s3を実行した場合、version-idを指定しない限りはオブジェクトが存在していてもレスポンス上では存在しない扱いとなります。

途中でバージョニングを有効にした場合のオブジェクトのライフサイクルで考えるべきこと

バージョニングが有効ではない場合、バージョン管理がなされていないため削除操作はそのまま反映されます。問題は、途中でバージョニングを有効にしたケースです。DeleteMarkerのつくオブジェクトに対するライフサイクルルールを設定しない限りは、単に不可視状態となっただけでバケット総サイズは減りません。

取るべき対応としては、以下の内容にてライフサイクルルールを追加することです。完全に削除する日数については環境に応じて調整しましょう。

なお、今回問題となったバケットは最初からバージョニング有効でした。

現バージョンと前バージョンのデータ量を確認したい場合

Storage Lensからダッシュボードを作成します。ダッシュボードの名前を指定後、特に設定を変更せずに作成でも問題ありません。

次に、「傾向とディストリビューション」にて「旧バージョンのバイト数」と「現行バージョンのバイト数」で比較してみましょう。

旧バージョンのファイルサイズが増加する一方の場合は、ライフサイクルルールの追加あるいは見直しをすべきです。

あとがき

S3バケットでバージョニングを有効にする場合は、DeleteMarkerの挙動について把握しておくことでコスト節約に繋がります。

S3バケットサイズが100TBになると、S3標準の場合にて最初の50TBまでが 0.023USD/GB、次の50TBが 0.022USD/GB となるため

$0.023 * 50000 = $1150
$0.022 * 50000 = $1100
$1150 + $1100 = $2250

となります。これはバージョニングが有効で且つ削除されていない古いバージョンのオブジェクトサイズも含まれます。ファイル個別サイズの都合で 0.023USD の料金が50TBにかからないケースもありますが、0.001USDの違いであって大きなコストが発生することには変わりありません。

消したつもりが積み重なって多額の利用費に繋がってしまわないよう、バージョニングが有効な場合は古いバージョンのオブジェクトについても確認しておきましょう。