デフォルトでは、1つのAWSアカウント内に100バケットしか作成できません。しかもこれはすべてのリージョンの合計なので、数十人規模のプロジェクトのサンドボックスアカウントなどではあっという間に上限に達してしまいます。
上限緩和で最大1000バケットまで引き上げられますが、それよりも誰も使っていない「ゾンビバケット」を整理するのが先です。ゾンビバケットは、余計なコスト発生の原因だけでなく、セキュリティ上の問題になることもあります。
生成AIでS3の空バケットを一覧化するPythonスクリプトを作成してもらいました(ただし、使用するAPIやパラメータなどはこちらからの指定)。MaxKey=1を指定することで、オブジェクトを最大でも1つしか取得しないように設定し、効率化を図っています。
import boto3
from botocore.exceptions import ClientError
def list_empty_buckets():
# Create an S3 client
s3_client = boto3.client('s3')
# List all S3 buckets
buckets = s3_client.list_buckets()
# Iterate over each bucket
for bucket in buckets['Buckets']:
bucket_name = bucket['Name']
try:
# Check if the bucket has at least one object
response = s3_client.list_objects_v2(Bucket=bucket_name, MaxKeys=1)
# If no objects found, print the bucket name
if 'Contents' not in response:
print(f'Empty bucket: {bucket_name}')
except ClientError as e:
# If access is denied, print the bucket name
if e.response['Error']['Code'] == 'AccessDenied':
print(f'Access denied for bucket: {bucket_name}')
else:
raise e
if __name__ == "__main__":
list_empty_buckets()
また注意点として、上記スクリプトはVersioningを考慮していません。そのため、すべてのオブジェクトの最新版がDelete Markerである場合(つまりVersioningが有効のバケットで、すべてのオブジェクトが削除済みの場合)、list_objects_v2はContentsを返しません。しかし本当は空でないため削除できません。
そのため、Versioningが有効な場合、ソースコードを以下のように変更する必要があります。
【変更前】
response = s3_client.list_objects_v2(Bucket=bucket_name, MaxKeys=1)
if 'Contents' not in response:
【変更後】
response = s3_client.list_object_versions(Bucket=bucket_name, MaxKeys=1)
if 'Versions' not in versions_response and 'DeleteMarkers' not in versions_response: