S3 Express One Zoneを使ったときのメモ
Posted On 2024-01-16
re:Invent2023で発表された、AWSのS3の新機能である「S3 Express One Zone」を使って、定期削除をしようとしたら結構ハマったのでメモを書いておきます。
目次
内容
S3 Express One Zoneを使ったら結構ハマったので個人的な覚え書きとしてのメモ
S3 Express One Zoneとは
re:Invent2023 で発表された、S3の新しいストレージクラス、「Amazon S3 Express One Zone」
- S3 Express One Zoneと標準S3の性能をAWSCLIで比較してみた
- re:Invent 2023 で発表されたAmazon S3 Express One Zoneを使ってみる
- PUT, COPY, POST, LIST / GET, SELECTが安く、ストレージ費用が高いため、非同期APIの一時ファイル置き場にして定期的に削除するという運用には向いていると思われる
扱いはディレクトリバケット
- S3 Express One Zoneの扱いは「ディレクトリバケット」となり、汎用バケットとは異なる
- CLIやBoto3、ポリシーが別扱い
バケットのライフサイクルが適用できない
- S3のオブジェクトを定期的に削除するなら、普通はバケットにライフサイクルを適用するのだが、S3 Express One Zoneはライフサイクルが適用できない
- How is S3 Express One Zone different?
- > Amazon S3 features not supported by S3 Express One Zone
S3 Lifecycle - ライフサイクル使えませんよときっちり書いてある。他にはMD5が使えない
- > Amazon S3 features not supported by S3 Express One Zone
- 定期的に削除するには、別途Lambdaを立てて、EventBridgeで定期的に回すしかない(ちょっとめんどい)
Lambdaまわり
boto3関連
- Lambdaのboto3やbotocoreが古くて、S3 Express One Zoneが対応していない
- https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
python3.12 : boto3-1.28.72 botocore-1.31.72
だった(2024/1現在)- 最新のboto3は1.34.19なので、かなりラグがある
- 1.28.72は2023/10/27リリースで、re:Invent2023の前
- S3 Express One Zone: no such bucket
- 同じハマり方をしている人がいる
- 最新版のboto3レイヤーを別途追加する必要がある
タイムゾーン
- 「作成後一定時間経過したら削除する」という処理を行うのだが、ListObjectV2でとってきた作成時刻がタイムゾーンを持つUTC時刻なのに対し、
datetime.datetime.utcnow()
がタイムゾーン情報を持たないため、そのままだと引き算できない - タイムゾーンのライブラリを使って変換する必要があるのだが、dateutilはデフォルトのLambda環境に組み込まれており、別途レイヤーをインストールする必要はなく便利
Paginator
- S3のListObjectV2は一度に取得できる数に上限がある(1000個)。再帰的に取得しないといけない
- Boto3のPaginatorを使うと便利にできる
- List系APIの取得数上限とPaginator
コード
Lambdaのコードをざっくり書くとこんな感じ。これは作成後1時間経過したファイルを削除するもの
import boto3
import datetime
from dateutil import tz
threshold = datetime.timedelta(minutes=60)
bucket_name = '{your-s3-express-bucket-name}'
def lambda_handler(event, context):
session = boto3.Session()
s3 = session.client('s3')
current_time = datetime.datetime.utcnow()
payload = {
'Bucket': bucket_name,
}
delete_cnt = 0
for response in s3.get_paginator('list_objects_v2').paginate(**payload):
for obj in response.get('Contents', []):
aware_datetime_utc = obj['LastModified'].astimezone(tz.tzutc()).replace(tzinfo=None)
elapsed = current_time - aware_datetime_utc
if elapsed > threshold:
s3.delete_object(Bucket=bucket_name, Key=obj['Key'])
delete_cnt += 1
return {
'statusCode': 200,
'body': f'Deleted {delete_cnt} files'
}
ポリシー
- S3 Express One Zoneは、S3とはポリシーが別扱いなので、S3FullAccessを付与したとしても権限が不足する
- Amazon S3 Express One Zone へアクセスに必要な IAM ポリシーについて #AWSreInvent
- この記事に記載されているポリシーを付与したら動いた。S3FullAccessを削除しても大丈夫なので、S3FullAcesssはこのケースだといらない
EventBridge
- CRON式で記述しなくても、
"rate (3 hours)"
のように記述すれば定期実行してくれる - ただ複数形に気をつける必要はある。
1 hour、2 hours
のように複数形を意識して書かないといけない
Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー