バージョニングが有効な特定の S3 のバケットにおいて、プリフィックスを指定して定期的に latest 以外のバージョンを削除するという要件があったので試してみました。
IAM ロール作成
S3 の権限が必要なので次のような IAM ポリシーを作成し、IAM ロールにアタッチしてください。 (他に AWSLambdaBasicExecutionRole も合わせてアタッチしてください)
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:DeleteObjectVersion", "s3:ListBucketVersions" ], "Resource": [ "arn:aws:s3:::バケット名", "arn:aws:s3:::バケット名/*" ] } ] }
Lambda の作成
Python 3.7 で新規に Lambda を作成し、さきほどの IAM ロールをアタッチします。
実際の Python のコードはこちらです。
import boto3 BUCKET = 'バケット名' PREFIX = 'プリフィックス' s3 = boto3.client('s3') def lambda_handler(event, context): keys = get_all_versions( bucket=BUCKET, prefix=PREFIX ) for key in keys: response = s3.delete_object( Bucket=BUCKET, Key=key['key'], VersionId=key['version_id'] ) def get_all_versions(bucket: str, prefix: str, next_key: str=None, next_version_id: str=None, keys: []=[]): if next_key is not None and next_version_id is not None: response = s3.list_object_versions( Bucket=bucket, Prefix=prefix, KeyMarker=next_key, VersionIdMarker=next_version_id ) else: response = s3.list_object_versions( Bucket=bucket, Prefix=prefix ) if 'Versions' in response: for content in response['Versions']: if not content['IsLatest']: keys.append({'key': content['Key'], 'version_id': content['VersionId']}) if 'DeleteMarkers' in response: for content in response['DeleteMarkers']: keys.append({'key': content['Key'], 'version_id': content['VersionId']}) if response['IsTruncated'] and 'NextKeyMarker' in response and 'NextVersionIdMarker' in response: get_all_versions( bucket=bucket, prefix=prefix, next_key=response['NextKeyMarker'], next_version_id=response['NextVersionIdMarker'], keys=keys ) return keys
デフォルトだと Timeout が 3 秒なので、タイムアウトしないように 1 分くらいに変更しておくと良いと思います。
この Lambda を実行すると Latest version 以外のバージョンは全て削除されます。
定期的に実行できるようにする
定期的に Lambda を実行したいので CloudWatch Events に Rule を作成します。
毎日 AM 4:00 GMT に設定したい場合は
このように設定し、Targets の function には先ほど作成した Lambda を指定してください。
まとめ
Lambda + CloudWatch Events の組み合わせを使うと、cron のようなことができるのでとても便利でした。
今回はバージョンを削除するという要件だったため S3 のライフサイクルは使用できませんでしたが、機会があったらこの辺も実際に試していきたいと思います!