S3のバージョニングを有効にして誤って上書きや削除してしまったオブジェクトを復旧できるようにする
awsS3のバージョニングは S3 の Bucket に設定できる項目で、 有効にすると全ての PUT したデータがバージョンIDと共に残るようになり、DELETE した際も実際に削除はせず Delete marker が最新のバージョンとして書き込まれるようになる。 最新バージョンが削除マーカーのオブジェクトを GET するとオブジェクトがないときと同様に Not found になるが、Delete marker のバージョンを削除するとそのオブジェクトを再度取得できるようになる。
次のようにバージョンを指定して削除すると Delete marker は付かない。
$ export BUCKET=<bucket> PREFIX=<prefix> RESTORE_TIME="2023-03-14T15:00+00:00"
# permanently delete existing objects
$ aws s3api list-object-versions --bucket ${BUCKET} --prefix ${PREFIX} --output json --query 'Versions[?IsLatest==`true` && LastModified>`'"${RESTORE_TIME}"'].[Key, VersionId]' | jq -r '.[] | "--key '\''" + .[0] + "'\'' --version-id " + .[1]' | xargs -L1 aws s3api delete-object --bucket ${BUCKET}
# permanently delete delete markers
$ aws s3api list-object-versions --bucket <bucket> --prefix ${PREFIX} --output json --query 'DeleteMarkers[?IsLatest==`true` && LastModified>`'"${RESTORE_TIME}"'`].[Key, VersionId]' | jq -r '.[] | "--key '\''" + .[0] + "'\'' --version-id " + .[1]' | xargs -L1 aws s3api delete-object --bucket ${BUCKET}
過去のバージョンも通常のオブジェクト同様に課金対象となるため、普段から頻繁に上書きや削除を行っている場合は有効にすることでコストが上がってしまうが、 逆に言えばそれほど更新はしない場合はバックアップ分のコストを払うことなくいざというときには復旧させることができる。 ある程度時間が経った古いバージョンを削除する lifecycle rule を作成しておけば削除されたオブジェクトが永遠に残ることを避けられる。