S3の条件付き書き込みをAWSCLIで試してみた
2024年8月20日、
Amazon S3 が 条件付きの書き込み (conditional writes) をサポート、書き込み先のS3上にキーが重複するファイルが存在する場合、上書きを回避できるアップデートがありました。
今回、サポートされた S3の条件付き書き込みの動作を AWS CLIを利用して確認する機会がありましたので、紹介させていただきます。
準備
CloudShell
AWS CloudShellを利用して、S3の動作確認を行いました。
AWSCLI
AWS CLI バージョン「1.34.2」で S3の conditional writes のサポートを確認しました。
{
"category": "``s3``",
"description": "Amazon Simple Storage Service / Features : Add support for conditional writes for PutObject and CompleteMultipartUpload APIs.",
"type": "api-change"
}
https://github.com/aws/aws-cli/blob/develop/.changes/1.34.2.json
AWSCLI(v1) を最新バージョンに更新しました。
curl -s "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "/tmp/awscli-bundle.zip"
unzip -q /tmp/awscli-bundle.zip -d /tmp/
sudo /usr/bin/python3 /tmp/awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws
$ aws --version
aws-cli/1.34.2 Python/3.9.16 Linux/6.1.102-108.177.amzn2023.x86_64 exec-env/CloudShell botocore/1.35.2
動作確認
help
引数として 「--if-none-match」 の指定が追加されていることを確認しました。
$ aws s3api put-object help
--if-none-match (string)
Uploads the object only if the object key name does not already ex-
ist in the bucket specified. Otherwise, Amazon S3 returns a 412 Pre-
condition Failed error.
If a conflicting operation occurs during the upload S3 returns a 409
ConditionalRequestConflict response. On a 409 failure you should
retry the upload.
Expects the '*' (asterisk) character.
For more information about conditional requests, see RFC 7232 , or
Conditional requests in the Amazon S3 User Guide .
S3準備
テスト用のS3バケットと、put に利用するダミーファイルを用意しました。
S3_BUCKET='test-20240820'
aws s3 mb "s3://${S3_BUCKET}"
date > dummy.txt
S3_KEY='dummy.txt'
put-object
条件付き書き込み --if-none-match "*"
を利用して、ダミーファイルのアップロードを試みました。
aws s3api put-object --bucket ${S3_BUCKET} --key ${S3_KEY} --body ./dummy.txt --if-none-match "*"
初回
$ aws s3api put-object --bucket ${S3_BUCKET} --key ${S3_KEY} --body ./dummy.txt
{
"ETag": "\"***\"",
"ServerSideEncryption": "AES256"
}
2回目
条件付き書き込み指定のエラーが発生しました。
$ aws s3api put-object --bucket ${S3_BUCKET} --key ${S3_KEY} --body ./dummy.txt --if-none-match "*"
An error occurred (PreconditionFailed) when calling the PutObject operation: At least one of the pre-conditions you specified did not hold
3回目
--if-none-match "*"
を省略、条件付き書き込みを指定しない場合は、アップロードに成功しました。
$ aws s3api put-object --bucket ${S3_BUCKET} --key ${S3_KEY} --body ./dummy.txt
{
"ETag": "\"***\"",
"ServerSideEncryption": "AES256"
}
4回目
重複する対象をS3から削除する事で、条件付き書き込みが有効な状態でも アップロードに成功しました。
$ aws s3 rm s3://${S3_BUCKET}/dummy.txt
delete: s3://***-20240820/dummy.txt
$ aws s3api put-object --bucket ${S3_BUCKET} --key ${S3_KEY} --body ./dummy.txt --if-none-match "*"
{
"ETag": "\"***\"",
"ServerSideEncryption": "AES256"
}
まとめ
S3を利用するシステムで、ファイルの整合性維持のため上書きを回避する必要がある場合、今回サポートされた条件付き込みと、適切な例外処理を実装する事で、シンプルな利用が可能となる可能性があります。
分散システムのノード間でS3の上書き回避するため事前にキーの重複チェックを実施していたり、S3のバージョニング情報を利用してファイルの上書き更新が発生していないことを確認していた場合、APIの実行課金の回避や、性能向上についても改善が期待出来る場合があります。
AWS SDKを最新版に更新し、S3の 条件付き書き込みを評価頂くことをお勧めします。