[レポート] JAWS-UG CLI 専門支部 #173R S3基礎 (レプリケーション) に参加しました #jawsug_cli
2020-12-11JAWS-UG CLI専門支部 #173R S3基礎 (レプリケーション) に参加したので、そのレポートです。と言っても耳だけ参加だったので、 S3 レプリケーションについての概要まとめとハンズオン + α の内容になってます。(いつもそんな感じか)
connpass のイベントページはこちら。
これまでの CLI 専門支部参加レポートはこちら。
- #172R S3基礎 (オブジェクト)
- #171R S3基礎 通知 (Lambdaの自動実行)
- #170R S3基礎 ライフサイクル
- #169R S3基礎 バージョニング
- #168R S3基礎 Webサイト&ログ
- #167R EventBridge入門
目次
S3 のレプリケーションとは
そもそも S3 のレプリケーションの機能について理解が乏しかったので、公式ドキュメントを元に概要をまとめてみます。
概要
- S3 のレプリケーションとは、異なる S3 バケット間でオブジェクトを自動的に非同期でコピーできる機能
- メタデータ (作成日時、バージョン IDなど) は保持される
- レプリケーション用に指定する S3 バケットは
- 同一リージョンでも別リージョンでも OK
- 同一リージョン内のレプリケーション : 同一リージョンレプリケーション (SRR - Same Region Replication)
- 異なるリージョンのバケットへのレプリケーション : クロスリージョンレプリケーション (CRR - Cross Region Replication)
- 同一アカウントでも別アカウントでも OK
- 異なるストレージクラスでも OK
- 同一リージョンでも別リージョンでも OK
- レプリケーションの設定は、レプリケーション 元 のバケットに追加する
レプリケーションの利用用途
- 全体としての用途・メリット
- メタデータも保持されるので、単純にレプリカを保持できる
- 異なるストレージクラスにレプリケーションすることで、レプリカ保持のコストを削減できる
- 異なるアカウントにレプリケーションすることで、別の所有権で同一のオブジェクトを扱える
- CRR を利用する場合の用途・メリット
- コンプライアンス要件への対応
- レイテンシー縮小
- SRR を利用する場合の用途・メリット
- 同種のオブジェクト (e.g ログ) の集約
- 異なるステージ間 (本番/ステージング/開発) とのオブジェクト共有
要件
- ソースバケットの所有者は、レプリケーション先のリージョンを有効にしている必要がある
- レプリケート元と先の両方のバケットでバージョニングを有効にする必要がある
その他、詳細な仕様については公式ドキュメントをどうぞ。
レプリケーション - Amazon Simple Storage Service
ハンズオン
今回のハンズオンでは、同一アカウントの同一リージョン内にあるバケット同士でレプリケーションをするという内容でしたが、ここでは別リージョンのバケットへのレプリケーション (CRR) としてやってみます。
なお、手元で実行する際は macOS 環境で、 AWS CLI のバージョンは 2.1.9
です。
aws --version
aws-cli/2.1.9 Python/3.7.4 Darwin/19.6.0 exe/x86_64 prompt/off
レプリケーション元とレプリケーション先の S3 バケット作成
レプリケーション元を 東京 ap-northeast-1
に、レプリケーション先を オレゴン us-west-2
に作成します。まずは必要な情報を変数に設定します。
$ AWS_ACCOUNT_ID=$( \
aws sts get-caller-identity \
--query 'Account' \
--output text )
$ S3_SRC_REGION="ap-northeast-1"
$ S3_DST_REGION="us-west-2"
$ S3_SRC_BUCKET_NAME="handson-cli-s3-replication-replication-source-${AWS_ACCOUNT_ID}"
$ S3_DST_BUCKET_NAME="handson-cli-s3-replication-replication-destination-${AWS_ACCOUNT_ID}"
それぞれのバケットを作成し、バージョニングを有効にします。
$ aws s3api create-bucket \
--bucket ${S3_SRC_BUCKET_NAME} \
--create-bucket-configuration "LocationConstraint=${S3_SRC_REGION}" \
--region ${S3_SRC_REGION} \
&& aws s3api put-bucket-versioning \
--bucket ${S3_SRC_BUCKET_NAME} \
--versioning-configuration Status=Enabled \
--region ${S3_SRC_REGION}
$ aws s3api create-bucket \
--bucket ${S3_DST_BUCKET_NAME} \
--create-bucket-configuration "LocationConstraint=${S3_DST_REGION}" \
--region ${S3_DST_REGION} \
&& aws s3api put-bucket-versioning \
--bucket ${S3_DST_BUCKET_NAME} \
--versioning-configuration Status=Enabled \
--region ${S3_DST_REGION}
それぞれのバケットの存在と、リージョン、バージョニングのステータスを確認します。
$ aws s3api get-bucket-location \
--bucket ${S3_SRC_BUCKET_NAME} \
--output text \
&& aws s3api get-bucket-versioning \
--bucket ${S3_SRC_BUCKET_NAME} \
--query "Status" \
--output text
ap-northeast-1
Enabled
$ aws s3api get-bucket-location \
--bucket ${S3_DST_BUCKET_NAME} \
--output text \
&& aws s3api get-bucket-versioning \
--bucket ${S3_DST_BUCKET_NAME} \
--query "Status" \
--output text
us-west-2
Enabled
ちなみに、 S3 バケットに対するコマンドには下記のようなものがあります。
$ aws s3api help | grep bucket
o create-bucket
o delete-bucket
o delete-bucket-analytics-configuration
o delete-bucket-cors
o delete-bucket-encryption
o delete-bucket-intelligent-tiering-configuration
o delete-bucket-inventory-configuration
o delete-bucket-lifecycle
o delete-bucket-metrics-configuration
o delete-bucket-ownership-controls
o delete-bucket-policy
o delete-bucket-replication
o delete-bucket-tagging
o delete-bucket-website
o get-bucket-accelerate-configuration
o get-bucket-acl
o get-bucket-analytics-configuration
o get-bucket-cors
o get-bucket-encryption
o get-bucket-intelligent-tiering-configuration
o get-bucket-inventory-configuration
o get-bucket-lifecycle-configuration
o get-bucket-location
o get-bucket-logging
o get-bucket-metrics-configuration
o get-bucket-notification-configuration
o get-bucket-ownership-controls
o get-bucket-policy
o get-bucket-policy-status
o get-bucket-replication
o get-bucket-request-payment
o get-bucket-tagging
o get-bucket-versioning
o get-bucket-website
o head-bucket
o list-bucket-analytics-configurations
o list-bucket-intelligent-tiering-configurations
o list-bucket-inventory-configurations
o list-bucket-metrics-configurations
o list-buckets
o put-bucket-accelerate-configuration
o put-bucket-acl
o put-bucket-analytics-configuration
o put-bucket-cors
o put-bucket-encryption
o put-bucket-intelligent-tiering-configuration
o put-bucket-inventory-configuration
o put-bucket-lifecycle-configuration
o put-bucket-logging
o put-bucket-metrics-configuration
o put-bucket-notification-configuration
o put-bucket-ownership-controls
o put-bucket-policy
o put-bucket-replication
o put-bucket-request-payment
o put-bucket-tagging
o put-bucket-versioning
o put-bucket-website
今回のように S3 バケットのリージョンとかバージョニングとかの情報をひとつのコマンドで取得したいと思うのは私だけでしょうか。他のリソースで言う describe-***
コマンドがあってそれで取得できればいいのになと思いました。
レプリケーション設定を追加
レプリケーション設定を追加するには s3api put-bucket-replication
コマンドを使いますが、その際にレプリケーションの設定情報を下記のような JSON で指定します。
{
"Role": "<IAM ロールの ARN>",
"Rules": [
{
"Status": "Enabled",
"Priority": 1,
"DeleteMarkerReplication": { "Status": "Disabled" },
"Filter" : { "Prefix": ""},
"Destination": {
"Bucket": "<レプリケーション先の S3 バケットの ARN>"
}
}
]
}
見てもらうと分かる通り S3 がユーザーに代わってオブジェクトをレプリケートするための IAM ロールが必要になるので、まずはそれを作ります。
IAM ロールの作成
順番としては、IAM ポリシーを作って、 IAM ロールを作ってアタッチする流れです。作成する IAM ロールには S3 が Assume Role できるように信頼ポリシーを付与します。
アタッチするポリシーの作成
下記のようなポリシードキュメントを policy.json
として作成しておいて、 iam create-policy
コマンドで --policy-document file://policy.json
で指定して IAM ポリシーを作成します。(コマンド実行については新しいものではないので省略します)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObjectVersion"
"s3:GetObjectVersionAcl",
"s3:GetObjectVersionTagging",
],
"Resource": [
"arn:aws:s3:::handson-cli-s3-replication-replication-source-************/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetReplicationConfiguration"
],
"Resource": [
"arn:aws:s3:::handson-cli-s3-replication-replication-source-************"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ReplicateObject",
"s3:ReplicateDelete",
"s3:ReplicateTags"
],
"Resource": "arn:aws:s3:::handson-cli-s3-replication-replication-destination-************/*"
}
]
}
ハンズオン資料では下記の公式ドキュメントと異なる設定だったのですが、後述するおかしな現象が発生したため公式ドキュメント通りの内容にしました。
IAM ロールを作成、 IAM ポリシーをアタッチ
IAM ロール作成にあたって、下記のような信頼ポリシーを trust-policy.json
として作成し、 iam create-role
コマンドで --assume-role-policy-document file://trust-policy.json
で指定して IAM ロールを作成します。(コマンド実行については新しいものではないのでry)
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
IAM ロールを作成したら、先ほど作成した IAM ポリシーをアタッチします。コマンドは iam attach-role-policy
でアタッチします。(コマンド実行についてはry)
レプリケーションの設定を追加
レプリケーションの設定情報も、下記のように事前に JSON ファイルとして作成しておきます。
$ cat << EOF > ./replication-doc.json
{
"Role": "${S3_REPLICA_ROLE_ARN}",
"Rules": [
{
"Status": "Enabled",
"Priority": 1,
"DeleteMarkerReplication": { "Status": "Disabled" },
"Filter" : { "Prefix": ""},
"Destination": {
"Bucket": "arn:aws:s3:::${S3_DST_BUCKET_NAME}"
}
}
]
}
EOF
レプリケーションを S3 バケットに追加するには s3api put-bucket-replication
コマンドを使用します。
$ aws s3api put-bucket-replication \
--bucket ${S3_SRC_BUCKET_NAME} \
--replication-configuration file://replication-doc.json
オブジェクトを Put して確認
適当なファイルを作成して、レプリケーション元の S3 バケットに Put し、レプリケーション先の S3 バケットで確認します。
$ echo "This is a sample file." > ./sample.txt
メタデータなども含めてレプリケートされるとのことなので、色々付与して Put します。
$ aws s3api put-object \
--bucket ${S3_SRC_BUCKET_NAME} \
--key sample.txt \
--body ./sample.txt \
--metadata custom-metadata-1=value1,custom-metadata-2=value2,Custom-Metadata-3=value3 \
--cache-control "public, max-age=1209600" \
--content-type "text/plain8" \
--tagging "TagKey1=TagValue1"
レプリケーションは通常 15 分以内に行われるため、それまではレプリケーション元のオブジェクトの ReplicationStatus
は PENDING
となっています。
$ aws s3api head-object \
--bucket ${S3_SRC_BUCKET_NAME} \
--key sample2.txt
{
"AcceptRanges": "bytes",
"LastModified": "2020-12-10T14:26:18+00:00",
"ContentLength": 26,
"ETag": "\"6d8b1ff98614bae68f36f5d2986f9e3c\"",
"VersionId": "L1CTlhLzrDmtq.Aupo_hzVb5uSBXmprQ",
"CacheControl": "public, max-age=1209600",
"ContentType": "text/plain8",
"Metadata": {
"custom-metadata-1": "value1",
"custom-metadata-2": "value2",
"custom-metadata-3": "value3"
},
"ReplicationStatus": "PENDING"
}
それぞれのオブジェクトの情報を s3api head-object
コマンドで取得して差分を見てみます。
$ aws s3api head-object \
--bucket ${S3_SRC_BUCKET_NAME} \
--key sample.txt \
>| src-object.json \
&& aws s3api head-object \
--bucket ${S3_DST_BUCKET_NAME} \
--key sample.txt \
>| dst-object.json \
&& diff -u src-object.json dst-object.json
--- src-object.json 2020-12-10 23:51:04.000000000 +0900
+++ dst-object.json 2020-12-10 23:51:05.000000000 +0900
@@ -11,5 +11,5 @@
"custom-metadata-2": "value2",
"custom-metadata-3": "value3"
},
- "ReplicationStatus": "COMPLETED"
+ "ReplicationStatus": "REPLICA"
}
ReplicationStatus
以外は一致しています。レプリケーション元のオブジェクトの ReplicationStatus
は COMPLETED
で、レプリケーション先のオブジェクトの ReplicationStatus
は REPLICA
となっています。
知らんかったぞ、ではなく、ハマったぞそれ
この 「知らんかったぞ、それ」 コーナー密かな人気があるとのことなので今回もいくつか個人的に知らなかったことを取り上げたかったのですが、今回はレプリケーションの機能自体ほとんど知らなかったので、代わりにハンズオンでハマったポイントについて書きます。
ReplicationStatus が Failed なのにレプリケートされている
ハンズオンのとおりに進めていって最後にレプリケーション元と先のオブジェクトの情報を比較すると、おかしな現象が起きました。
$ aws s3api head-object \
--bucket ${S3_SRC_BUCKET_NAME} \
--key failed-sample.txt \
>| src-failed-object.json \
&& aws s3api head-object \
--bucket ${S3_DST_BUCKET_NAME} \
--key failed-sample.txt \
>| dst-failed-object.json \
&& diff -u src-failed-object.json dst-failed-object.json
--- src-failed-object.json 2020-12-11 00:04:18.000000000 +0900
+++ dst-failed-object.json 2020-12-11 00:04:19.000000000 +0900
@@ -11,5 +11,5 @@
"custom-metadata-2": "value2",
"custom-metadata-3": "value3"
},
- "ReplicationStatus": "FAILED"
+ "ReplicationStatus": "REPLICA"
}
手順の途中にも書きましたが、ハンズオンの手順書と公式ドキュメントでは IAM ポリシーに下記のような差異がありました。
--- policy-handson.json 2020-12-10 23:57:25.000000000 +0900
+++ policy.json 2020-12-10 23:58:45.000000000 +0900
@@ -4,8 +4,9 @@
{
"Effect": "Allow",
"Action": [
- "s3:GetObjectVersionForReplication",
- "s3:GetObjectVersionAcl"
+ "s3:GetObjectVersion",
+ "s3:GetObjectVersionAcl",
+ "s3:GetObjectVersionTagging"
],
"Resource": [
"arn:aws:s3:::handson-cli-s3-replication-replication-source-************/*"
@@ -26,8 +27,7 @@
"Action": [
"s3:ReplicateObject",
"s3:ReplicateDelete",
- "s3:ReplicateTags",
- "s3:GetObjectVersionTagging"
+ "s3:ReplicateTags"
],
"Resource": "arn:aws:s3:::handson-cli-s3-replication-replication-destination-************/*"
}
違いとしては、レプリケーション元の S3 バケットに s3:GetObjectVersionTagging
がなかったという点です。これが原因でなぜこのような状況が発生するのかはわからなかったのですが、ちょっとハマったポイントでした。
LT
今回は SAYJOY@gringriffin さんによる LT がありました。
以前に JAWS-UG 千葉支部で開催されたサーバーレスハンズオン (の一部) の内容を AWS CLI で構築した際の振り返りや気付きなどについて話されていました。CLI 専門支部のハンズオン資料を元に資料化をされている途中とのことなので、もしかしたらご自身のブログで公開されるかも?しれません。
(終わってから言うのもあれなんですが) 自分も資料が整えば LT しようかと思っていましたが、結局間に合わずでしたので供養ブログを書きました。
まとめ
JAWS-UG CLI専門支部 #173R S3基礎 (レプリケーション) に参加したので、そのレポートでした。
今回はリアルタイムでは耳だけ参加で、終わってからハンズオンをやってみました。S3 のレプリケーション機能は今まで使ったことがなかったのですが、思っていた以上に簡単であっさりしているなという印象です。異なるリージョン、異なるアカウント、異なるストレージクラスへのレプリケーションも可能ということで、あらゆるシチュエーションに対応できるのでは、と思いました。
年内のハンズオンは今回で最後だったようなのですが、来年以降もスケジュールは用意されているということなので引き続き参加していきたいと思います。もともと今年に入ってからオフラインで参加しようとしていたところで今のような状況になってしまいました。その後、すぐにオンラインでの開催していただけるようになったので、そこからはほぼ毎回参加してきました。おかげさまで抵抗なく、むしろ好んで AWS CLI を使うようになりました。開催していただいている波田野さんには感謝です。
そういえば、自分も AWS CLI を使ったハンズオン資料のようなものを作成中なので、近々公開できるかなと思ってます。
comments powered by Disqus