[レポート] JAWS-UG CLI 専門支部 #172R S3基礎 (オブジェクト) に参加しました #jawsug_cli
2020-11-26JAWS-UG CLI 専門支部 #172R S3基礎 (オブジェクト) に参加したので、そのレポートです。
connpass のイベントページはこちら。
これまでの CLI 専門支部参加レポートはこちら。
- #171R S3基礎 通知 (Lambdaの自動実行)
- #170R S3基礎 ライフサイクル
- #169R S3基礎 バージョニング
- #168R S3基礎 Webサイト&ログ
- #167R EventBridge入門
目次
S3 の全体像、オブジェクトの操作
-
※基本的には前回までと同内容
-
Outposts 用の
s3outposts
コマンドが出てきた$ aws s3outposts help ... NAME s3outposts - DESCRIPTION Amazon S3 on Outposts provides access to S3 on Outposts operations. AVAILABLE COMMANDS o create-endpoint o delete-endpoint o help o list-endpoints
-
その他、 S3 としては下記のコマンドがある
s3
: ハイレベルコマンドs3api
: 基本の APIs3control
: アクセスポイント、バッチオペレーション、 Storage Lens などの操作
-
ファイルを置くだけではなく、他の人・リソースに共有するための仕組みも多数
-
ストレージの分類
- ブロックストレージ
- 固定長
- OS が管理している (論理的に可変長にしている)
- ファイルストレージ
- NAS など
- オブジェクトストレージ
- ブロックストレージ
-
S3 オブジェクトの名前スキーマ
- バージョニング無効 :
S3://<バケット名>/<キー>
- バージョニング有効 :
S3://<バケット名>/<キー><バージョンID>
- バージョニング無効 :
2020/11/26 時点での AWS CLI のバージョン
これまでにもレポートを書いてきましたが、その当時の AWS CLI バージョンを書いておこうと思います。今回のハンズオンがあった 2020/11/26 時点での v1 および v2 それぞれの最新バージョンは下記のとおりでした。
-
v1
aws-cli-v1 $ aws --version aws-cli/1.18.185 Python/3.8.5 Darwin/19.6.0 botocore/1.19.25
-
v2
$ aws --version aws-cli/2.1.4 Python/3.7.4 Darwin/19.6.0 exe/x86_64
今回は特に最新の機能を使うわけではないので、 v2 を使用していきます。ここ数日は re:Invent 前のアップデートが怒涛の勢いで出てきていますが、新しい API に関しては (後に v2 でも使えるものの) v1 でのみ対応している場合があるので、最新の機能を CLI で試す場合には v1 を使ったほうがよさそうです。
- 参考
ハンズオン
今回のハンズオンでは、新たに作成した S3 バケットに対してオブジェクトを追加し、そのオブジェクトに対してコピーや属性の更新などを実行した後、削除するところまでを CLI で操作しました。
今回も、ハンズオンの詳細な手順についてはイベントページの資料におまかせするとして、手順の中で気になったところを抜粋して確認してみます。
2.2 S3 オブジェクトの新規アップロード
オブジェクトのアップロードには s3api put-object
コマンドを使います。オプションはたくさんありますが、必須なのは --bucket
と --key
のみです。
$ aws s3api put-object help
...
SYNOPSIS
put-object
[--acl <value>]
[--body <value>]
--bucket <value>
[--cache-control <value>]
[--content-disposition <value>]
[--content-encoding <value>]
[--content-language <value>]
[--content-length <value>]
[--content-md5 <value>]
[--content-type <value>]
[--expires <value>]
[--grant-full-control <value>]
[--grant-read <value>]
[--grant-read-acp <value>]
[--grant-write-acp <value>]
--key <value>
[--metadata <value>]
[--server-side-encryption <value>]
[--storage-class <value>]
[--website-redirect-location <value>]
[--sse-customer-algorithm <value>]
[--sse-customer-key <value>]
[--sse-customer-key-md5 <value>]
[--ssekms-key-id <value>]
[--ssekms-encryption-context <value>]
[--request-payer <value>]
[--tagging <value>]
[--object-lock-mode <value>]
[--object-lock-retain-until-date <value>]
[--object-lock-legal-hold-status <value>]
[--expected-bucket-owner <value>]
[--cli-input-json | --cli-input-yaml]
[--generate-cli-skeleton <value>]
各オプションの詳細については下記の公式ドキュメントを参照してください。
ここでは新たにオブジェクトをアップロードするので、 --body
オプションでローカルにあるファイルを指定します。
$ cat alpha.txt
This is A text.
$ aws s3api put-object \
--bucket ${S3_BUCKET_NAME} \
--key alpha/message_a.txt \
--body ./alpha.txt
{
"ETag": "\"75721060f35a9f9f6bdaf9985394e9a8\""
}
同様に
$ cat beta.txt
This is B text.
$ aws s3api put-object
–bucket ${S3_BUCKET_NAME}
–key beta/message_b.txt
–body ./beta.txt
{ “ETag”: “"424e9ac2402771285730c91435c5a23d"” }
正しくアップロードできたか確認します。ここでは簡潔に s3 ls
コマンドで確認します。
$ aws s3 ls s3://${S3_BUCKET_NAME}/alpha/
2020-11-26 22:49:09 16 message_a.txt
$ aws s3 ls s3://${S3_BUCKET_NAME}/beta/
2020-11-26 22:49:17 17 message_b.txt
2.4 S3 バケットのオブジェクト一覧取得
S3 バケット内のオブジェクト一覧を取得するコマンドとしては list-objects
と list-objects-v2
が存在しますが、ドキュメントでは Warning として次のように書かれています。
This API has been revised. We recommend that you use the newer version, ListObjectsV2 , when developing applications. For backward compatibility, Amazon S3 continues to support ListObjects .
ということで、 list-objects-v2
を使うようにしましょう。
$ aws s3api list-objects-v2 \
--bucket ${S3_BUCKET_NAME}
{
"Contents": [
{
"Key": "alpha/message_a.txt",
"LastModified": "2020-11-26T13:49:09+00:00",
"ETag": "\"75721060f35a9f9f6bdaf9985394e9a8\"",
"Size": 16,
"StorageClass": "STANDARD"
},
{
"Key": "beta/message_b.txt",
"LastModified": "2020-11-26T13:49:17+00:00",
"ETag": "\"424e9ac2402771285730c91435c5a23d\"",
"Size": 17,
"StorageClass": "STANDARD"
}
]
}
2.7 S3 オブジェクトの更新
S3 オブジェクトの更新には、新規アップロードの時と同じ put-object
コマンドを使います。先程も書いたように、必須のオプションは --bucket
と --key
です。オブジェクト自体を更新しない場合は --body
の指定は不要で、更新したい属性に対応するオプションを指定すれば OK です。例えば、オブジェクトにメタデータを追加する場合は --metadata
オプションを使って下記のように実行します。
$ aws s3api put-object \
--bucket ${S3_BUCKET_NAME} \
--key alpha/message_a.txt \
--metadata secretLevel=1,Category="sample text"
{
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\""
}
確認してみます。
$ aws s3api head-object \
--bucket ${S3_BUCKET_NAME} \
--key alpha/message_a.txt
{
"AcceptRanges": "bytes",
"LastModified": "2020-11-26T13:54:44+00:00",
"ContentLength": 0,
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
"ContentType": "binary/octet-stream",
"Metadata": {
"category": "sample text",
"secretlevel": "1"
}
}
ここで注意したいのが、メタデータのキーは大文字/小文字が区別されないことです。 put-object
コマンドでは secretLevel
と Category
を指定しましたが、実際には category
と secretlevel
が設定されています。 ただし、 SDK for Go でメタデータにアクセスする際、レスポンスのキー名はキャメルケースになるのが個人的にはハマりポイントかなと思います。
メタデータ以外の例として、ストレージクラスを変更してみます。
$ aws s3api put-object \
--bucket ${S3_BUCKET_NAME} \
--key beta/message_b.txt \
--storage-class ONEZONE_IA
{
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\""
}
確認しておきます。
$ aws s3api list-objects-v2 \
--bucket ${S3_BUCKET_NAME}
{
"Contents": [
{
"Key": "alpha/message_a.txt",
"LastModified": "2020-11-26T13:58:42+00:00",
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
"Size": 0,
"StorageClass": "STANDARD"
},
{
"Key": "beta/message_b.txt",
"LastModified": "2020-11-26T14:08:24+00:00",
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
"Size": 0,
"StorageClass": "ONEZONE_IA"
}
]
}
知らんかったぞ、それ
今回に限らずハンズオンでは新しく知ることがたくさんあるので、この 知らんかったぞ、それ 項目では新しく知ったことを自分なりに深堀りしてみたいと思います。(恒例化したい)
というわけで、前回と前々回はこのコーナーがなかったのですが、今回はいくつか取り上げてみます。
S3 バケットのロケーション (リージョン) だけ取得する
かなりの小ネタっぽい内容ですが、対象のバケットのリージョンだけを取得するコマンド (API) が存在していることを初めて知りました。
$ aws s3api get-bucket-location \
--bucket ${S3_BUCKET_NAME}
{
"LocationConstraint": "ap-northeast-1"
}
head-object でストレージクラスの確認
オブジェクトのストレージクラスを確認するには list-object-v2
コマンドを使うしか無いと思っていたのですが、 head-object
コマンドでも取得できるようでした。ただし条件があります。まずは beta/message_b.txt
の情報を取得してみます。
$ aws s3api head-object \
--bucket ${S3_BUCKET_NAME} \
--key beta/message_b.txt
{
"AcceptRanges": "bytes",
"LastModified": "2020-11-26T14:08:24+00:00",
"ContentLength": 0,
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
"ContentType": "binary/octet-stream",
"Metadata": {},
"StorageClass": "ONEZONE_IA"
}
取得できてますね。では alpha/message_a.txt
も取得してみます。
$ aws s3api head-object \
--bucket ${S3_BUCKET_NAME} \
--key alpha/message_a.txt
{
"AcceptRanges": "bytes",
"LastModified": "2020-11-26T13:58:42+00:00",
"ContentLength": 0,
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
"ContentType": "binary/octet-stream",
"Metadata": {
"category": "sample text",
"secretlevel": "1"
}
}
はい。 StorageClass
の属性がありません。
これはどういうことかというと、どうやらストレージクラスが S3 標準 (STANDARD) の場合は head-object
のレスポンス内に情報が含まれないようです。
個人的には、 head-object
で取得できないと思っていたので嬉しい誤算でしたが、基本的に扱うのは標準クラスのオブジェクトなので、やっぱりちょっと残念だなという思いです。
delete-object と delete-objects
S3 オブジェクトを削除するコマンドとして delete-object
と delete-objects
が存在しています。コマンド名だけ見ると delete-objects
のほうは複数のオブジェクトをまとめて削除できそうなので便利かなと思うんですが、実際は対象のオブジェクトをすべて列挙する必要があるため逆に使いづらいようです。
$ aws s3api delete-objects help
...
OPTIONS
...
--delete (structure)
Container for the request.
Objects -> (list)
The objects to delete.
(structure)
Object Identifier is unique value to identify objects.
Key -> (string)
Key name of the object to delete.
VersionId -> (string)
VersionId for the specific version of the object to
delete.
Quiet -> (boolean)
Element to enable quiet mode for the request. When you add this
element, you must set its value to true.
Shorthand Syntax:
Objects=[{Key=string,VersionId=string},{Key=string,VersionId=string}],Quiet=boolean
JSON Syntax:
{
"Objects": [
{
"Key": "string",
"VersionId": "string"
}
...
],
"Quiet": true|false
}
削除対象は --delete
オプションで指定するのですが、 Shorthand Syntax で指定するにしても
Objects=[{Key=string,VersionId=string},{Key=string,VersionId=string}],Quiet=boolean
のような形で指定する必要があり、この文字列を生成するのはなかなか面倒です。
であれば、削除対象のオブジェクトを list-objects-v2
コマンドで取得して、それらに対して delete-object
を使ったほうが楽そうです。実際には次のような形で実行します。
$ for i in $(
aws s3api list-objects-v2 \
--bucket ${S3_BUCKET_NAME} \
--query 'Contents[].Key' \
--output text
); do
aws s3api delete-object \
--bucket ${S3_BUCKET_NAME} \
--key ${i}
done
これで list-objects-v2
で取得できるオブジェクトをすべて削除することができます。
まとめ
JAWS-UG CLI 専門支部 #172R S3基礎 (オブジェクト) に参加したので、そのレポートでした。
今回はオブジェクトに対する操作を、ハイレベルコマンドの aws s3
ではなく API と対になっている aws s3api
で実行しました。 s3
コマンドでは cp
や ls
といったサブコマンドで操作できるので、単にオブジェクトの移動や削除を行う際には非常に簡単です。一方 s3api
コマンドでは、 API と対になったサブコマンドを使用して操作するため、 JSON 形式で生の情報を取得することができます。そのため、実行結果から必要な部分を --query
で抜き出したり、他のコマンドに渡したりしやすくなります。
それ以前に、やはり API ベースで何が行われているのかがわかるのが s3api
コマンドの良いところだと思います。
次回のレプリケーションで S3 については一旦区切りかなと思いますが、だいぶ S3 に関する知識がついてきたような気がします。そんな中で感じるのが、やっぱり S3 は Simple じゃないってことですね。
comments powered by Disqus