1
1

More than 1 year has passed since last update.

AWS CloudFormationでS3のクロスリージョン相互レプリケーションを構築しよう

Posted at

はじめに

AWS CloudFormationを利用してS3のクロスリージョン相互レプリケーション構築のテンプレートのサンプルです。
東京リージョンと大阪リージョンにS3バケットを作成し、相互レプリケーションの設定をします。
S3バケットのARNを相互参照するため、一度作成した後に、変更セットでレプリケーションルールを設定します。

テンプレートの概要が分からない場合は、はじめてのAWS CloudFormationテンプレートを理解するを参考にしてください。

コードはGitHubにもあります。

今回は、akane というシステムの dev 環境を想定しています。
同じ構成で違う環境を作成する場合は、{環境名}-parameters.jsonを別途作成します。

ディレクトリ構成
akane (システム)
  ├── s3 (スタック)
  │   ├── dev-parameters.json (dev 環境のパラメータ)
  │   └── s3.yml (CFnテンプレート)
  └── s3-replication (スタック)
      ├── dev-parameters.json (dev 環境のパラメータ)
      └── s3-replication.yml -> ../s3/s3.yml (CFnテンプレートのシンボリックリンク)

AWS リソース構築内容

  1. s3スタック
    • IAMロール (s3)
    • s3バケット (akane-dev-s3)

実行環境の準備

AWS CloudFormationを動かすためのAWS CLIの設定を参考にしてください。

AWS リソース構築手順

  1. 下記を実行してスタックを作成

    ./create_stacks.sh
    
  2. 下記を実行してスタックを削除

    ./delete_stacks.sh
    

構築テンプレート

1. s3スタック

s3.yml
AWSTemplateFormatVersion: 2010-09-09
Description: S3 For Akane

# Metadata:

Parameters:
  SystemName:
    Type: String
    AllowedPattern: '[a-zA-Z0-9-]*'
  EnvType:
    Description: Environment type.
    Type: String
    AllowedValues: [all, dev, stg, prod]
    ConstraintDescription: must specify all, dev, stg, or prod.
  IsFirstTime:
    Type: String
    AllowedValues: [true, false]

Mappings:
  AnotherAz:
    ap-northeast-1:
      Region: ap-northeast-3
    ap-northeast-3:
      Region: ap-northeast-1

Conditions:
  IsFirstTime: !Not [ !Equals [ !Ref IsFirstTime, true ] ]

# Transform

Resources:
  # ロール作成
  akaneS3ReplicationRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - s3.amazonaws.com
            Action:
              - sts:AssumeRole
      Description: !Sub
        - ${SystemName}-${EnvType}-role-s3-replication-${AWS::Region}
        - {SystemName: !Ref SystemName, EnvType: !Ref EnvType}
      Path: /
      Policies:
        - PolicyName: !Sub
            - ${SystemName}-${EnvType}-policy-s3-replication-${AWS::Region}
            - {SystemName: !Ref SystemName, EnvType: !Ref EnvType}
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - s3:Get*
                  - s3:ListBucket
                Resource:
                  - !Join
                    - ''
                    - - 'arn:aws:s3:::'
                      - !Sub
                        - ${SystemName}-${EnvType}-s3-${AWS::Region}
                        - {SystemName: !Ref SystemName, EnvType: !Ref EnvType}
                  - !Join
                    - ''
                    - - 'arn:aws:s3:::'
                      - !Sub
                        - ${SystemName}-${EnvType}-s3-${AWS::Region}
                        - {SystemName: !Ref SystemName, EnvType: !Ref EnvType}
                      - /*
              - Effect: Allow
                Action:
                  - s3:ReplicateObject
                  - s3:ReplicateDelete
                  - s3:ReplicateTags
                  - s3:GetObjectVersionTagging
                Resource:
                  - !Join
                    - ''
                    - - 'arn:aws:s3:::'
                      - !Sub
                        - ${SystemName}-${EnvType}-s3-
                        - {SystemName: !Ref SystemName, EnvType: !Ref EnvType}
                      - !FindInMap [AnotherAz, !Ref AWS::Region, Region]
                      - /*
      RoleName: !Sub
        - ${SystemName}-${EnvType}-role-s3-replication-${AWS::Region}
        - {SystemName: !Ref SystemName, EnvType: !Ref EnvType}
      Tags:
        - Key: Name
          Value: !Sub
          - ${SystemName}-${EnvType}-role-s3-replication-${AWS::Region}
          - {SystemName: !Ref SystemName, EnvType: !Ref EnvType}
        - Key: SystemName
          Value: !Ref SystemName
        - Key: EnvType
          Value: !Ref EnvType

  # S3 Bucket作成
  akaneS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: Private
      BucketName: !Sub
        - ${SystemName}-${EnvType}-s3-${AWS::Region}
        - {SystemName: !Ref SystemName, EnvType: !Ref EnvType}
      VersioningConfiguration:
        Status: Enabled
      ReplicationConfiguration: !If
        - IsFirstTime
        - Role: !GetAtt akaneS3ReplicationRole.Arn
          Rules:
            - Destination:
                Bucket: !Join
                  - ''
                  - - !Sub arn:aws:s3:::${SystemName}-${EnvType}-s3-
                    - !FindInMap [AnotherAz, !Ref AWS::Region, Region]
              Id: ClossRegionSync
              Prefix: ''
              Status: Enabled
        - !Ref AWS::NoValue
      Tags:
        - Key: Name
          Value: !Sub
            - ${SystemName}-${EnvType}-s3-${AWS::Region}
            - {SystemName: !Ref SystemName, EnvType: !Ref EnvType}
        - Key: SystemName
          Value: !Ref SystemName
        - Key: EnvType
          Value: !Ref EnvType

Outputs:
  akaneS3BucketArn:
    Value: !GetAtt akaneS3Bucket.Arn
    Export:
      Name: !Sub
        - ${SystemName}-${EnvType}-s3-arn-${AWS::Region}
        - {SystemName: !Ref SystemName, EnvType: !Ref EnvType}
dev-parameters.json
{
    "Parameters": [
        {
            "ParameterKey": "SystemName",
            "ParameterValue": "akane"
        },
        {
            "ParameterKey": "EnvType",
            "ParameterValue": "dev"
        },
        {
            "ParameterKey": "IsFirstTime",
            "ParameterValue": "true"
        }
    ],
    "Capabilities": [
        "CAPABILITY_NAMED_IAM"
    ]
}

2. s3スタック

s3-replication.yml は、s3.yml のシンボリックリンクのため記載を割愛する。

dev-parameters.json
{
    "Parameters": [
        {
            "ParameterKey": "SystemName",
            "ParameterValue": "akane"
        },
        {
            "ParameterKey": "EnvType",
            "ParameterValue": "dev"
        },
        {
            "ParameterKey": "IsFirstTime",
            "ParameterValue": "false"
        }
    ],
    "Capabilities": [
        "CAPABILITY_NAMED_IAM"
    ]
}

3. 実行ファイル

create_stacks.sh
#!/bin/sh

cd `dirname $0`

SYSTEM_NAME=akane

create_stack () {
    ENV_TYPE=$1
    STACK_NAME=$2
    export AWS_DEFAULT_REGION=$3
    aws cloudformation create-stack \
    --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} \
    --template-body file://./${SYSTEM_NAME}/${STACK_NAME}/${STACK_NAME}.yml \
    --cli-input-json file://./${SYSTEM_NAME}/${STACK_NAME}/${ENV_TYPE}-parameters.json

    aws cloudformation wait stack-create-complete \
    --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME}
}

create_change_set () {
    ENV_TYPE=$1
    STACK_NAME=$2
    export AWS_DEFAULT_REGION=$3

    if [ ${STACK_NAME} == "s3-replication" ]; then
        STACK_FULLNAME=${SYSTEM_NAME}-${ENV_TYPE}-s3
    else
        STACK_FULLNAME=${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME}
    fi

    aws cloudformation create-change-set \
    --stack-name ${STACK_FULLNAME} \
    --change-set-name ${STACK_FULLNAME}-change-set \
    --template-body file://./${SYSTEM_NAME}/${STACK_NAME}/${STACK_NAME}.yml \
    --cli-input-json file://./${SYSTEM_NAME}/${STACK_NAME}/${ENV_TYPE}-parameters.json

    aws cloudformation wait change-set-create-complete \
    --stack-name ${STACK_FULLNAME} \
    --change-set-name ${STACK_FULLNAME}-change-set

    aws cloudformation execute-change-set \
    --stack-name ${STACK_FULLNAME} \
    --change-set-name ${STACK_FULLNAME}-change-set
}

create_stack dev s3 ap-northeast-1
create_stack dev s3 ap-northeast-3
create_change_set dev s3-replication ap-northeast-1
create_change_set dev s3-replication ap-northeast-3

exit 0
delete_stacks.sh
#!/bin/sh

cd `dirname $0`

SYSTEM_NAME=akane

delete_stack () {
    ENV_TYPE=$1
    STACK_NAME=$2
    export AWS_DEFAULT_REGION=$3
    aws cloudformation delete-stack \
    --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME}

    aws cloudformation wait stack-delete-complete \
    --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME}
}

delete_stack dev s3 ap-northeast-1
delete_stack dev s3 ap-northeast-3

exit 0
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1