バージョニングされたS3バケットのオブジェクトを削除してみる

2020.02.07

こんにちは。さかいです。

バージョニングが有効となっているS3バケットのオブジェクトを削除する場合、バージョニングを利用していない場合と動きが異なるので、確認するため実際に試してみました。

オブジェクトのバージョニングとは

バージョニングとは、同じバケット内でオブジェクトの複数のバリアントを保持する手段です。バージョニングを使用して、Amazon S3 バケットに格納されたあらゆるオブジェクトのあらゆるバージョンを、格納、取得、復元することができます。バージョニングを使用すれば、意図しないユーザーアクションからもアプリケーション障害からも、簡単に復旧できます。

こちらより引用

メリットとしては、間違って削除してしまった…アプリケーションがバグってて必要なファイルまで削除してしまった…間違って上書きしてしまった…という意図していない操作からオブジェクトを復旧することができます。

オブジェクト上書き時の動き

同一のキーのオブジェクトを保存する場合、新しいバージョンが作成され、そのオブジェクトが最新バージョンとなります。(上書きされません。) これまで、最新バージョンだったオブジェクトは以前のバージョンとして保持されます。

こちらより引用

オブジェクト削除時の動き

オブジェクトを削除した場合、削除マーカーが挿入され、その削除マーカーが最新バージョンとなります。削除マーカーが最新バージョンの場合は、オブジェクトが削除されたという扱いになります。(マネジメントコンソール上もバージョンを表示しないとオブジェクトは表示されません) また、これまで最新バージョンだったオブジェクトは以前のバージョンとして保持されます。

こちらより引用

バージョニングを有効にするには

バケット作成時にバージョニングを有効にする

同じバケット内でオブジェクトのすべてのバージョンを保持します。にチェックを入れて作成する。

作成済みバケットのバージョニングを有効にする

バケットのプロパティにあるバージョニングを表示し、バージョニングの有効化を選択し保存する。なお、バージョニングを有効にする前にバケットに格納されているオブジェクトは変更されません。反対にバージョニングを停止した場合も、既存のオブジェクトは変更されません。

バージョニングされているオブジェクトを削除してみる

実際にバージョニングされているオブジェクトをプログラム(AWS SDK)で削除してみます。プログラムの実行環境は、Lambda(Node.js 12.x)を利用します。

Lambdaで削除する

以下の通りLambda関数を作成し実行します。

const AWS = require("aws-sdk");

exports.handler = async (event) => {
    const params = {
      Bucket: [バケット名],
      Key: [オブジェクトのキー]
    };
    const s3 = new AWS.S3();
    return s3.deleteObject(params).promise();
};

実際に削除したファイルを確認すると、削除マーカーが最新バージョンとなっていることがわかります。

Lambdaで削除マーカーを作成せずに削除する

今度は削除時に削除マーカーを作成しないで削除してみます。この場合は、オブジェクトのキーとバージョンIDを指定することで、削除マーカーを作成しないで削除することができます。

const AWS = require("aws-sdk");

exports.handler = async (event) => {
    const params = {
      Bucket: [バケット名],
      Key: [オブジェクトのキー],
      VersionId: [バージョンID]
    };
    const s3 = new AWS.S3();
    return s3.deleteObject(params).promise();
};

実際に削除したファイルを確認すると、オブジェクトが削除されています。(バージョンを表示してもオブジェクトはありません) ですが、バージョンIDを指定して削除してしまうと、削除から復旧することができなくなりますので注意が必要です。

Lambda + ライフサイクル設定を利用して削除する

バージョニングのメリットを受けつつ、削除する方法の1つとして、削除して以前のバージョンとなったオブジェクトをライフサイクル設定で一定期間経過後、削除するように設定してみます。

ライフサイクル設定

一定期間経過後、以前のバージョンが削除されるようにライフサイクルルールを作成します。

以前のバージョンが1日経過後、自動的に削除されるように設定してみました。また、期限切れのオブジェクト削除マーカーをクリーンアップするオプションを有効にしています。これは、以前のバージョンがすべて削除され、削除マーカーのみが残ってしまった場合に、クリーンアップ(削除)してくれるオプションです。
ライフサイクルの実行のタイミングと日数のカウントについてはこちらをご確認ください。今回のように1日後と指定しても、ぴったり24時間後削除されるわけではありませんので、注意が必要です。

ライフサイクル実行前と実行後

ライフサイクル実行前

  • version_test1.txt
    • 削除されて、以前のバージョンが残っている状態
  • version_test2.txt
    • 上書きされて、以前のバージョンが残っている状態
  • version_test3.txt
    • 上書き後、削除されて、以前のバージョンが2オブジェクト残っている状態
  • version_test4.txt
    • オブジェクトが新規作成された状態

ライフサイクル実行後

  • version_test1.txt
    • 以前のバージョンが削除され、削除マーカーのみが残っている
  • version_test2.txt
    • 以前のバージョンが削除された
  • version_test3.txt
    • 以前のバージョンがすべて削除され、削除マーカーのみが残っている
  • version_test4.txt
    • 変更なし

ライフサイクルの実行で以前のバージョンが削除されることを確認できました。削除マーカーのみとなったオブジェクトは、期限切れのオブジェクト削除マーカーをクリーンアップするオプションを有効にしましたので、一定時間経過後(試した環境だとおおよそ1日後)、削除されていることを確認できました。

さいごに

バージョニングを有効にすると意図しないミスからの復旧などのメリットがありますが、以前のバージョンがずっと残ったままだとコストもかかります。バージョニングのメリットを受けつつ、最低限のコストになるよう、適切に設定する必要があると感じました。今回は、有効期限が切れた場合、削除されるよう設定しましたが、一定期間後、ストレージクラスの変更もできますので、オブジェクトの特性に応じて設定することができるかと思います。