どこにでもいる30代SEの学習ブログ

主にプログラミング関連の学習内容。読んだ本の感想や株式投資についても書いてます。

【AWS】CLIからバージョニングされたS3バケットを削除する方法

S3バケットは空にしてからでないと削除できません。それはバージョニングされたバケットでも同様です。

問題は、バージョニングされたオブジェクトを削除しても、実は消えていないことです。DeleteMarkerが追加されるだけで、オブジェクトが完全に消えるわけではありません。完全に削除するためには、DeleteMarkerとバージョンも削除する必要があります。

マネージメントコンソールであれば削除するのは難しくありません。しかし、AWS CLIから少々面倒なので手順をまとめました。

[1] オブジェクトの削除

[1-1] バケットとファイルの作成

試しにバージョニングされたバケットを作成し、test.txtをアップロードします。

$ aws s3 ls s3://{バケット名}
2021-04-17 13:19:12          4 test.txt

バージョンを確認します。

$ aws s3api list-object-versions --bucket {バケット名}
{
    "Versions": [
        {
            "LastModified": "2021-04-17T13:19:12.000Z", 
            "VersionId": "Goie_timWFWXJTwHv9swGAyjbIrDI6cQ", 
            "ETag": "\"033bd94b1168d7e4f0d644c3c95e35bf\"", 
            "StorageClass": "STANDARD", 
            "Key": "test.txt", 
            "Owner": {
                "DisplayName": "{所有者の表示名}", 
                "ID": "{所有者のID}"
            }, 
            "IsLatest": true, 
            "Size": 4
        }
    ]
}

[1-2] オブジェクトの削除

aws s3 rmでオブジェクトを削除します。

$ aws s3 rm s3://{バケット名}/ --recursive
delete: s3://{バケット名}/test.txt

aws s3 lsで確認すると削除されたように見えます。

$ aws s3 ls s3://{バケット名}

しかし、バケットを削除しようとするとエラーが発生します。

$ aws s3 rb s3://{バケット名} --force
remove_bucket failed: s3://{バケット名} An error occurred (BucketNotEmpty) when calling the DeleteBucket operation: The bucket you tried to delete is not empty. You must delete all versions in the bucket.

[1-3] バージョンの確認

バージョンを確認すると、完全には削除されていないことが分かります。DeleteMarkersが追加されています。

$ aws s3api list-object-versions --bucket {バケット名}
{
    "DeleteMarkers": [
        {
            "Owner": {
                "DisplayName": "{所有者の表示名}", 
                "ID": "{所有者のID}"
            }, 
            "IsLatest": true, 
            "VersionId": "mfYZIOM57MlB_8BkvG7YcNuKWJz0geHS", 
            "Key": "test.txt", 
            "LastModified": "2021-04-17T13:35:10.000Z"
        }
    ], 
    "Versions": [
        {
            "LastModified": "2021-04-17T13:19:12.000Z", 
            "VersionId": "Goie_timWFWXJTwHv9swGAyjbIrDI6cQ", 
            "ETag": "\"033bd94b1168d7e4f0d644c3c95e35bf\"", 
            "StorageClass": "STANDARD", 
            "Key": "test.txt", 
            "Owner": {
                "DisplayName": "{所有者の表示名}", 
                "ID": "{所有者のID}"
            }, 
            "IsLatest": false, 
            "Size": 4
        }
    ]
}

"DeleteMarkers", "Versions"を削除する必要があります。

[2] 完全な削除

以下のシェルスクリプトを作成・実行して削除します。コマンドは下記記事を参考にさせていただきました。

バージョニングが有効なS3バケットをAWS CLIで空にする手順(オブジェクト1000個以下) - のぴぴのメモ

#!/bin/bash

BUCKET_NAME={バケット名}

# バケット内の全オブジェクト削除
aws s3 rm s3://${BUCKET_NAME}/ --recursive

# DeleteMarkersの削除
aws s3api list-object-versions --bucket ${BUCKET_NAME} \
        | jq -r -c '.["DeleteMarkers"][] | [.Key,.VersionId]' \
        | while read line
do
        key=`echo $line | jq -r .[0]`
        versionid=`echo $line | jq -r .[1]`
        aws s3api delete-object --bucket ${BUCKET_NAME} \
               --key ${key} --version-id ${versionid}
done

# Versionsの削除
aws s3api list-object-versions --bucket ${BUCKET_NAME} \
        | jq -r -c '.["Versions"][] | [.Key,.VersionId]' \
        | while read line
do
        key=`echo $line | jq -r .[0]`
        versionid=`echo $line | jq -r .[1]`
        aws s3api delete-object --bucket ${BUCKET_NAME} \
               --key ${key} --version-id ${versionid}
done

実行すると、以下のような結果が返ってきます。

$ sh delete_s3_object.sh 
{
    "VersionId": "mfYZIOM57MlB_8BkvG7YcNuKWJz0geHS", 
    "DeleteMarker": true
}
{
    "VersionId": "Goie_timWFWXJTwHv9swGAyjbIrDI6cQ"
}

バージョンを再度確認すると、今度は削除されています。

$ aws s3api list-object-versions --bucket {バケット名}

バケット削除を実行すると今度は削除に成功します。

$ aws s3 rb s3://{バケット名} --force
remove_bucket: {バケット名}

出典