CFNでクロスリージョンレプリケーションを有効化したバケットを作成する

CloudFormationを使ってクロスリージョンレプリケーションを有効化したバケットを作成する

CloudFormationを使用して、クロスリージョンレプリケーションを有効化したバケットを作成する

AWS SAAの出題範囲の1つである、弾力性に優れたアーキテクチャの設計に関する内容です。

S3が提供する機能の1つに、レプリケーションがあります。

レプリケーションを使用すると、Amazon S3 バケット間でオブジェクトを自動で非同期的にコピーできます。

オブジェクトのレプリケーション

レプリケーション先のバケットは、同一リージョンだけでなく、別リージョンを指定することができます。
これをクロスリージョンレプリケーション(CRR)と呼びます。

今回はCloudFormationを使用して、CRR環境を構築します。

構築する環境

Diagram of create S3 Bucket with Cross-Region Replication enabled using CloudFormation

2つのリージョンにS3バケットを作成します。

一方のバケットではレプリケーションを有効化します。

もう一方のバケットはレプリケーションの送信先バケットです。

今回の構成では、2つのバケットを以下のリージョンに配置します。

  • 送信元バケット:ap-northeast-1
  • 送信先バケット:us-east-1

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-saa/tree/main/01/003

テンプレートファイルのポイント解説

送信先バケット

Resources:
  ReplicationBucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: Private
      BucketName: !Ref Prefix
      VersioningConfiguration:
        Status: Enabled
Code language: YAML (yaml)

送信先バケットを作成する上でのポイントはバージョニング設定です。

レプリケート元とレプリケート先の両方のバケットで、バージョニングを有効にする必要があります。

レプリケーションの要件

上記に従い、バージョニングの設定を有効化します。

バージョニングはVersioningConfigurationプロパティで設定します。
詳細につきましては、以下のページをご確認ください。

https://awstut.com/2023/01/04/create-s3-bucket-with-versioning-enabled-with-cfn

送信元バケット

Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: Private
      BucketName: !Ref Prefix
      ReplicationConfiguration:
        Role: !GetAtt S3BucketReplicationRole.Arn
        Rules:
          - Destination:
              Bucket: !Sub "arn:aws:s3:::${ReplicationBucketName}"
            Status: Enabled
      VersioningConfiguration:
        Status: Enabled
Code language: YAML (yaml)

送信元バケットでも、バージョニングを有効化する必要があります。

ReplicationConfigurationプロパティでレプリケーション設定を行います。

Rulesプロパティ内に送信先バケットを指定します。

Roleプロパティで、レプリケーションするために必要となる権限を有したIAMロールを指定します。

Resources:
  S3BucketReplicationRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - s3.amazonaws.com
      Policies:
        - PolicyName: !Sub "${Prefix}-S3BucketReplicationPolicy"
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetReplicationConfiguration
                  - s3:ListBucket
                Resource:
                  - !Sub "arn:aws:s3:::${Prefix}"
              - Effect: Allow
                Action:
                  - s3:GetObjectVersionForReplication
                  - s3:GetObjectVersionAcl
                  - s3:GetObjectVersionTagging
                Resource:
                  - !Sub "arn:aws:s3:::${Prefix}/*"
              - Effect: Allow
                Action:
                  - s3:ReplicateObject
                  - s3:ReplicateDelete
                  - s3:ReplicateTags
                Resource:
                  - !Sub "arn:aws:s3:::${ReplicationBucketName}/*"
Code language: YAML (yaml)

ポリシーの設定は、以下のAWS公式サイトを参考に設定しました。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/setting-repl-config-perm-overview.html

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

https://awstut.com/2021/12/02/cloudformation-nested-stacks

今回は以下のコマンドで2つのリージョンにスタックを作成します。

$ aws cloudformation create-stack \
--stack-name saa-01-003-2 \
--template-url https://[bucket-url]/saa-01-003-2.yaml \
--capabilities CAPABILITY_IAM \
--region us-east-1

$ aws cloudformation create-stack \
--stack-name saa-01-003-1 \
--template-url https://[bucket-url]/saa-01-003-1.yaml \
--capabilities CAPABILITY_IAM \
--region ap-northeast-1
Code language: Bash (bash)

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • 送信元S3バケット:saa-01-003-1
  • 送信先S3バケット:saa-01-003-2

AWS Management Consoleから各リソースを確認します。

Detail of S3 1.

確かに2つのバケットが作成されています。
両バケットが異なるリージョンに作成されていることもわかります。

送信先バケットを確認します。

Detail of S3 2.

バージョニングが有効化されています。

送信元S3バケットを確認します。

Detail of S3 3.

こちらのバケットも確かにバージョニングが有効化されています。

レプリケーション設定を確認します。

Detail of S3 4.

us-east-1に作成したバケットが送信先に設定されていることがわかります。

動作確認

準備が整いましのたで、送信元バケットにオブジェクトをアップロードします。
オブジェクトのアップロードはAWS CLIを使用します。

$ echo 'hogehoge' > sample1.txt

$ aws s3 cp sample1.txt s3://saa-01-003-1/
upload: ./sample1.txt to s3://saa-01-003-1/sample1.txt
Code language: Bash (bash)

送信元バケットを確認します。

Detail of S3 5.

確かにオブジェクトが配置されています。

このオブジェクトの詳細を確認します。

Detail of S3 6.

Replication Statusを見ると「COMPLETED」とあります。
つまりレプリケーションが正常に完了したことを意味しています。

送信先バケットを確認します。

Detail of S3 7.

オブジェクトが配置されてます。
送信元バケットに配置したオブジェクトと同名です。

このオブジェクトの詳細を確認します。

Detail of S3 8.

Replication Statusを見ると「REPLICA」とあります。
つまりこのオブジェクトがレプリケーションされたオブジェクトであるということを意味しています。

このようにリージョンの異なるバケット間でレプリケーションを実施することができます。

(参考)オブジェクトのバージョニング

設定時に両バケットともバージョニングを有効化しましたので、古いバージョンについてもレプリケーションされるのか確認します。

まずオブジェクトを更新します。

$ echo 'fugafuga' >> sample1.txt

$ aws s3 cp sample1.txt s3://saa-01-003-1/
upload: ./sample1.txt to s3://saa-01-003-1/sample1.txt
Code language: Bash (bash)

オブジェクトが更新されました。

送信先バケットで、このオブジェクトのバージョン情報を確認します。

$ aws s3api list-object-versions \
--bucket saa-01-003-2 \
--prefix sample1.txt
{
    "Versions": [
        {
            "ETag": "\"304693ccbc28bbeac4689b24bda76e0e\"",
            "Size": 18,
            "StorageClass": "STANDARD",
            "Key": "sample1.txt",
            "VersionId": "X53EqnDUikg9zw827hBU0J5pr6BpmZS.",
            "IsLatest": true,
            "LastModified": "2022-12-28T07:01:41+00:00",
            "Owner": {
                "DisplayName": "[owner-name]",
                "ID": "[owner-id]"
            }
        },
        {
            "ETag": "\"d9a3fdfc7ca17c47ed007bed5d2eb873\"",
            "Size": 9,
            "StorageClass": "STANDARD",
            "Key": "sample1.txt",
            "VersionId": ".fp.Pb7WSzlbBjsXStbPbIE63uGDF9_c",
            "IsLatest": false,
            "LastModified": "2022-12-28T06:58:55+00:00",
            "Owner": {
                "DisplayName": "[owner-name]",
                "ID": "[owner-id]"
            }
        }
    ]
}
Code language: Bash (bash)

確かにバージョンについてもレプリケーションされていることがわかります。
2つ目のデータが古いバージョンのオブジェクトです。

送信元バケットから古いバージョンのオブジェクトをダウンロードします。

$ aws s3api get-object \
--bucket saa-01-003-2 \
--key sample1.txt \
--version-id .fp.Pb7WSzlbBjsXStbPbIE63uGDF9_c \
sample1_replica.txt
{
    "AcceptRanges": "bytes",
    "LastModified": "2022-12-28T06:58:55+00:00",
    "ContentLength": 9,
    "ETag": "\"d9a3fdfc7ca17c47ed007bed5d2eb873\"",
    "VersionId": ".fp.Pb7WSzlbBjsXStbPbIE63uGDF9_c",
    "ContentType": "text/plain",
    "Metadata": {},
    "ReplicationStatus": "REPLICA"
}

$ cat sample1_replica.txt
hogehoge
Code language: Bash (bash)

内容が更新前のものです。
確かに送信元バケットから、古いバージョンのオブジェクトを取得することができました。

まとめ

CloudFormationを使用して、CRR環境を構築する方法を確認しました。