[レポート] JAWS-UG CLI 専門支部 #169R S3基礎 バージョニング に参加しました #jawsug_cli
2020-10-08JAWS-UG CLI 専門支部 #169R S3基礎 バージョニング に参加したので、そのレポートです。
connpass のイベントページはこちら。
前回、前々回のレポートはこちら。
- [レポート] JAWS-UG CLI 専門支部 #168R S3基礎 Webサイト&ログ に参加しました #jawsug_cli - michimani.net
- [レポート] JAWS-UG CLI 専門支部 #167R EventBridge入門 に参加しました #jawsug_cli - michimani.net
目次
S3 の全体像とサービス概要
S3 の全体像とサービス概要については 前回 のレポートを参照してください。今回はその差分のみ。
- Outposts に Amazon S3 が対応
- 今回はオブジェクトに関する部分のハンズオン
- バージョニング自体はバケットに対して設定する
- オブジェクトはその影響を受ける
- S3 全体が名前空間というイメージ
- 故にバケット名はグローバルユニーク
- S3 はファイルシステムではない
- マネコンではオブジェクトのキーに含まれる
/
でフォルダ構造っぽく見せている
- マネコンではオブジェクトのキーに含まれる
- バージョンが異なる別のオブジェクトが生成される (※重要)
- 差分が生成されるわけではない
- 特定のバージョンを削除しても他のバージョンに影響はない
- バージョンを指定しないと、一番最近のバージョンのオブジェクトが取得される
- バージョニングを使うか否か
- バケットの外 (Git や Mercurial) でバージョン管理
- バケットの中身は使い捨て
- Web サイトなど
- バケットでバージョン管理
- バケットの中身がマスターになる
- バケットの外 (Git や Mercurial) でバージョン管理
- バージョニングを利用する S3 の機能
- リテーションモード
- オブジェクトロック
- リーガルホールド
ハンズオン
今回のハンズオンでは、バージョニングを有効にした S3 バケットに対してオブジェクトをアップロード・更新し、特定バージョンの取得や削除を行いました。
今回も、ハンズオンの詳細な手順についてはイベントページの資料 及び下記のハンズオン資料におまかせするとして、個人的に気になった部分のコマンドについて書いておきます。
1.3. IAMポリシーの作成
IAM ポリシーを作成する際にパスを使用することで、その後の管理がやりやすくなります。
$ aws iam create-policy help
...
SYNOPSIS
create-policy
--policy-name <value>
[--path <value>]
--policy-document <value>
[--description <value>]
[--cli-input-json | --cli-input-yaml]
[--generate-cli-skeleton <value>]
[--cli-auto-prompt <value>]
iam create-policy
コマンドの --path
オプションを使って、次のように実行します。
$ aws iam create-policy \
--policy-name "michimani-sample-policy" \
--path "/michimani/sample/" \
--policy-document file://policy
パスを使うことで、 list-policies
コマンドの --path-prefix
で結果を絞ることができます。
$ aws iam list-policies \
--path-prefix "/michimani/sample/"
{
"Policies": [
{
"PolicyName": "michimani-sample-policy",
"PolicyId": "ANPA2FQKQ3TXXXXXXXXXX",
"Arn": "arn:aws:iam::1234XXXXXXXX:policy/michimani/sample/michimani-sample-policy",
"Path": "/michimani/sample/",
"DefaultVersionId": "v1",
"AttachmentCount": 0,
"PermissionsBoundaryUsageCount": 0,
"IsAttachable": true,
"CreateDate": "2020-10-08T11:34:10+00:00",
"UpdateDate": "2020-10-08T11:34:10+00:00"
}
]
}
2. S3バケットのバージョニング有効化
s3api put-bucket-versioning
コマンドを使用します。
$ aws s3api put-bucket-versioning help
...
SYNOPSIS
put-bucket-versioning
--bucket <value>
[--content-md5 <value>]
[--mfa <value>]
--versioning-configuration <value>
[--expected-bucket-owner <value>]
[--cli-input-json | --cli-input-yaml]
[--generate-cli-skeleton <value>]
[--cli-auto-prompt <value>]
--versioning-configuration
オプションでバージョニングを有効にします。
$ aws s3api put-bucket-versioning \
--bucket ${S3_BUCKET_NAME} \
--versioning-configuration Status=Enabled
バージョニングのステータスを確認するには s3api get-bucket-versioning
コマンドを使って、出力結果から Status
の部分を抜き出します。
$ aws s3api get-bucket-versioning \
--bucket ${S3_BUCKET_NAME} \
--query 'Status' \
--output text
Enabled
無効化する場合は Status=Enabled
として実行します。 (ハンズオンの手順 4)
$ aws s3api put-bucket-versioning \
--bucket ${S3_BUCKET_NAME} \
--versioning-configuration Status=Suspended
なお、バージョニングの設定を一度も触っていない場合、 get-buket-versioning
では出力結果を得られず、 Status
だけ抜出層としても None
になります。
$ aws s3api get-bucket-versioning \
--bucket ${OTHER_S3_BUCKET_NAME} \
--query 'Status' \
--output text
None
なので、上記の無効化は、 無効化 というよりも 一時停止 (= Suspended) というイメージです。
3.1. ファイルの作成
バージョニングを有効にしたバケットに対してファイルをアップロードします。アップロードには s3 cp
コマンドを使用します。
$ aws s3 cp sample_file.txt s3://${S3_BUCKET_NAME}
ちなみに、 sample_file.txt
の中身は下記の内容です。
$ cat sample_file.txt
This is a sample file. (v1)
マネジメントコンソールで確認すると、オブジェクトの詳細画面にバージョンを指定するプルダウンが表示されています。
プルダウンからバージョンを指定すると、 バージョン ID が表示されます。
バージョン ID を構成する文字列にはピリオド .
が含まれる場合もあります。
S3 オブジェクトを更新する場合、特に追加のパラメータなどは必要なく、先ほどと同じ s3 cp
コマンドを使います。 sample_file.txt
の中身の v1
の部分を変更して何度かアップロードを実行し、作成されたバージョンを確認してみます。オブジェクトのバージョン一覧を取得するには、 s3api list-object-versions
コマンドを使用します。
$ aws s3api list-object-versions help
...
SYNOPSIS
list-object-versions
--bucket <value>
[--delimiter <value>]
[--encoding-type <value>]
[--prefix <value>]
[--expected-bucket-owner <value>]
[--cli-input-json | --cli-input-yaml]
[--starting-token <value>]
[--page-size <value>]
[--max-items <value>]
[--generate-cli-skeleton <value>]
[--cli-auto-prompt <value>]
バケット名とオブジェクトキーを指定して実行。今回は、各バージョンのバージョン ID と最終更新日時を、最終更新日時の降順で出力してみます。
$ aws s3api list-object-versions \
--bucket ${S3_BUCKET_NAME} \
--prefix sample_file.txt \
--query 'reverse(sort_by(Versions,&LastModified))[].{LM:LastModified,VID:VersionId}'
[
{
"LM": "2020-10-08T12:02:16+00:00",
"VID": "PWdCD9sEmem67CqNHA2cBMUSQCY6t5Sv"
},
{
"LM": "2020-10-08T12:02:09+00:00",
"VID": "b4234JLABtdRGlQ9AGreIuSsqoaf964n"
},
{
"LM": "2020-10-08T12:01:59+00:00",
"VID": "jfbONeI0pJ1h9unJgRrvzmIFBvUBa0xv"
},
{
"LM": "2020-10-08T12:01:49+00:00",
"VID": "baLmE30tSBAuiZ8lhQ3.LcyAf3P2fv7N"
},
{
"LM": "2020-10-08T11:56:26+00:00",
"VID": "sRfncD5dSroDAQYq4s3gAinHWQpQp4VW"
}
]
3.5 S3オブジェクトの特定バージョンのダウンロード
オブジェクトのダウンロードには s3api get-object
コマンドを使用します。
$ s3api get-object help
...
SYNOPSIS
get-object
--bucket <value>
[--if-match <value>]
[--if-modified-since <value>]
[--if-none-match <value>]
[--if-unmodified-since <value>]
--key <value>
[--range <value>]
[--response-cache-control <value>]
[--response-content-disposition <value>]
[--response-content-encoding <value>]
[--response-content-language <value>]
[--response-content-type <value>]
[--response-expires <value>]
[--version-id <value>]
[--sse-customer-algorithm <value>]
[--sse-customer-key <value>]
[--sse-customer-key-md5 <value>]
[--request-payer <value>]
[--part-number <value>]
[--expected-bucket-owner <value>]
<outfile>
オプションがたくさんありますが、今回使用するのは --version-id
オプションです。
--version-id
で指定するのは s3api list-object-versions
で確認できた VersionId
ですが、今回は最新のものから数えて 3 番目にあたるバージョンのオブジェクトをダウンロードしてみます。対象のバージョン ID を次のようにして取得します。
$ TARGET_VERSION_ID=$(\
aws s3api list-object-versions \
--bucket ${S3_BUCKET_NAME} \
--prefix sample_file.txt \
--query 'reverse(sort_by(Versions,&LastModified))[2].VersionId' \
--output text) \
&& echo $TARGET_VERSION_ID
jfbONeI0pJ1h9unJgRrvzmIFBvUBa0xv
バージョン ID が取得できたので、そのバージョンを指定してオブジェクトをダウンロードします。3 番目ということで、オブジェクトの中身は This is a sample file. (v3)
になっているはずなので、ダウンロード後に中身を出力するところまでやってみます。
$ aws s3api get-object \
--bucket ${S3_BUCKET_NAME} \
--key sample_file.txt \
--version-id ${TARGET_VERSION_ID} \
./out/sample_file_v3.txt > /dev/null \
&& cat ./out/sample_file_v3.txt
This is a sample file. (v3)
想定通りの内容でした。
3.6 S3オブジェクトの特定バージョンを削除
特定バージョンの削除には s3api delete-object
を --version-id
オプションと合わせて使用します。
$ aws s3api delete-object help
...
SYNOPSIS
delete-object
--bucket <value>
--key <value>
[--mfa <value>]
[--version-id <value>]
[--request-payer <value>]
[--bypass-governance-retention | --no-bypass-governance-retention]
[--expected-bucket-owner <value>]
[--cli-input-json | --cli-input-yaml]
[--generate-cli-skeleton <value>]
[--cli-auto-prompt <value>]
今回は、先ほど取得したバージョンを削除します。
$ aws s3api delete-object \
--bucket ${S3_BUCKET_NAME} \
--key sample_file.txt \
--version-id ${TARGET_VERSION_ID}
{
"VersionId": "jfbONeI0pJ1h9unJgRrvzmIFBvUBa0xv"
}
続けて、あらためて最新のものから 3 番目にあたるバージョンのオブジェクトをダウンロードしてみます。今度は中身が This is a sample file. (v2)
になるはずです。
$ TARGET_VERSION_ID=$(\
aws s3api list-object-versions \
--bucket ${S3_BUCKET_NAME} \
--prefix sample_file.txt \
--query 'reverse(sort_by(Versions,&LastModified))[2].VersionId' \
--output text) \
&& echo $TARGET_VERSION_ID
baLmE30tSBAuiZ8lhQ3.LcyAf3P2fv7N
$ aws s3api get-object \
--bucket ${S3_BUCKET_NAME} \
--key sample_file.txt \
--version-id ${TARGET_VERSION_ID} \
./out/sample_file_v2.txt > /dev/null \
&& cat ./out/sample_file_v2.txt
This is a sample file. (v2)
想定通りの内容でした。
知らんかったぞ、それ
今回に限らずハンズオンでは新しく知ることがたくさんあるので、この 知らんかったぞ、それ 項目では新しく知ったことを自分なりに深堀りしてみたいと思います。(恒例化したい)
というわけで、今回もいくつか取り上げてみます。
クレデンシャルファイルに任意のファイルを指定する
環境変数 AWS_SHARED_CREDENTIALS_FILE
に任意のファイルを指定することで、 ~/.aws/credentials
以外のファイルをクレデンシャルファイルとして指定できます。
今回のようにハンズオン用のプロファイルを作成する際に ~/.aws/credentials
を編集すると、ハンズオン後の掃除がしにくくなり、事故の原因にもなります。ハンズオン用のクレデンシャルファイルを作って AWS_SHARED_CREDENTIALS_FILE
で指定すれば、 ~/.aws/credentials
は汚れずに済むというわけです。
シェルの for 文
AWS CLI というかシェルの使い方の話ですが。
今回のハンズオンでは、シェルの for 文と CLI コマンドを組み合わせて、すべてのバージョンを削除していました。今までシェルの for 文を使ったことがなかったのと、 CLI コマンドとの組み合わせに感動しました。…と言っても自分で良い例が思いつかないので、ハンズオンと同じくすべてのバージョンを削除してみます。
削除前に、対象のバージョンの件数を確認しておきます。
$ aws s3api list-object-versions \
--bucket ${S3_BUCKET_NAME} \
--prefix sample_file.txt \
--query 'length(Versions)' \
--output text
4
for 文で削除します。
$ for i in $(
aws s3api list-object-versions \
--bucket ${S3_BUCKET_NAME} \
--prefix sample_file.txt \
--query 'Versions[].VersionId' \
--output text
); do
aws s3api delete-object \
--bucket ${S3_BUCKET_NAME} \
--key sample_file.txt \
--version-id ${i}
done
{
"VersionId": "PWdCD9sEmem67CqNHA2cBMUSQCY6t5Sv"
}
{
"VersionId": "b4234JLABtdRGlQ9AGreIuSsqoaf964n"
}
{
"VersionId": "baLmE30tSBAuiZ8lhQ3.LcyAf3P2fv7N"
}
{
"VersionId": "sRfncD5dSroDAQYq4s3gAinHWQpQp4VW"
}
s3api list-object-versions
コマンドの出力結果から --query
オプションで各バージョンの VersionId
を抜き出して、その値を s3api delete-object
に渡しています。出力としては、 s3api delete-object
で削除されたバージョンの VersionId
が出力されます。
念のため削除後の件数を確認しておきます。
$ aws s3api list-object-versions \
--bucket ${S3_BUCKET_NAME} \
--prefix sample_file.txt \
--query 'length(Versions)' \
--output text
In function length(), invalid type for value: None, expected one of: ['string', 'array', 'object'], received: "null"
まとめ
JAWS-UG CLI 専門支部 #169R S3基礎 バージョニング の参加レポートでした。
S3 のバージョニングって、そういえば普段の業務や個人的な利用でも有効にしたことがなかったので、今回その挙動について試すことができてよかったです。S3 のバージョニングは差分を保持する形ではなく、別のオブジェクトとして保持するので、大量にバージョンを生成する際にはストレージコストに注意する必要がありそうです。
今回もシェルについて新たに for 文の知識を得たので、どんどん使っていってシェル芸を上達させたいと思います。
comments powered by Disqus