東京・大阪でAmazon Aurora Global Databaseを組み、大阪はヘッドレスクラスターにする構成を、AWS CloudFormationで構築してみた
Amazon AuroraのGlobal Database(東京・大阪)で、大阪だけヘッドレスにしたい
おのやんです。
みなさんAmazon Aurora(以下、Aurora)のストレージはマルチリージョンでバックアップを取り、かつコストを抑えた構成にしたいと思ったことはありますか?私はあります。
AuroraにはGlobal Databaseという構成をとることができ、例えば東京・大阪といったマルチリージョン間でデータを同期させることができます。
また、Auroraには別途ヘッドレスクラスターという構成もとることができます。Auroraではコンピューティングとストレージが分離しており、ストレージを残してコンピューティング部分だけ削除して、コンピューティング部分の課金を抑えるような構成が可能です。
以上を組み合わせて、「東京・大阪にまたがるAurora Global Database構成を取ってマルチリージョンにデータを同期し、大阪だけヘッドレス構成にして大阪はインスタンス課金が発生しない(ストレージ課金のみ)」ような構成を組むことができます。
ヘッドレスクラスターは、通常のAWSマネジメントコンソール上からは作成できないので、AWS CLIやAWS SDK(Boto3など)、IaCなどを使って構築する必要があります。
現在、RDS コンソールでは、ヘッドレスクラスターの作成はサポートされていません。
この構成を実現するために、AWS CloudFormation(以下、CFn)テンプレートをどう記述する必要があるのか検証しましたので、その内容を今回は紹介します。
CFnテンプレート
今回使用したCFnテンプレートはこんな感じで、東京と大阪で2つのCFnテンプレートを使います。東京の方で記述しているAWS::RDS::DBInstance
のリソースを、大阪の方では記述しないことで、大阪リージョンのクラスターがストレージのみとなります。
東京リージョンデプロイ分テンプレート
AWSTemplateFormatVersion: '2010-09-09'
Description: Aurora PostgreSQL Global Database Primary Cluster in Tokyo Region
Parameters:
SystemName:
Type: String
Default: aws
EnvName:
Type: String
Default: test
Resources:
#============================================================#
# VPC
#============================================================#
AWSTestVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: Aurora-Global-VPC-Tokyo
#============================================================#
# Private subnets
#============================================================#
AWSTestPrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref AWSTestVPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: Aurora-Private-Subnet-1
AWSTestPrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref AWSTestVPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: !Select [1, !GetAZs '']
Tags:
- Key: Name
Value: Aurora-Private-Subnet-2
#============================================================#
# DB Subnet Group
#============================================================#
AWSTestDBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnet group for Aurora Global Database
SubnetIds:
- !Ref AWSTestPrivateSubnet1
- !Ref AWSTestPrivateSubnet2
Tags:
- Key: Name
Value: Aurora-Global-SubnetGroup
#============================================================#
# Security Group for Aurora
#============================================================#
AWSTestAuroraSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Aurora PostgreSQL
VpcId: !Ref AWSTestVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
CidrIp: 10.0.0.0/16
Tags:
- Key: Name
Value: Aurora-Global-SecurityGroup
#============================================================#
# Aurora Global Database
#============================================================#
# Aurora Global Database
AWSTestAuroraGlobalDatabase:
Type: AWS::RDS::GlobalCluster
Properties:
GlobalClusterIdentifier: !Sub ${SystemName}-${EnvName}-aurora-global-cluster
Engine: aurora-postgresql
EngineVersion: 15.4
StorageEncrypted: true
#============================================================#
# Primary Aurora DB Cluster
#============================================================#
# Primary Aurora DB Cluster
AWSTestAuroraDBCluster:
Type: AWS::RDS::DBCluster
Properties:
DBClusterIdentifier: !Sub ${SystemName}-${EnvName}-aurora-db-cluster-primary
Engine: aurora-postgresql
EngineVersion: 15.4
MasterUsername: postgres
MasterUserPassword: password # 本番環境ではAWS Secrets Managerなどで強力なパスワードを必ず管理してください
DBSubnetGroupName: !Ref AWSTestDBSubnetGroup
VpcSecurityGroupIds:
- !Ref AWSTestAuroraSecurityGroup
StorageEncrypted: true
BackupRetentionPeriod: 7
PreferredBackupWindow: 03:00-04:00
PreferredMaintenanceWindow: sun:04:00-sun:05:00
GlobalClusterIdentifier: !Ref AWSTestAuroraGlobalDatabase
#============================================================#
# Primary Aurora DB Instance
#============================================================#
# Primary Aurora DB Instance
AWSTestAuroraDBInstance:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: !Sub ${SystemName}-${EnvName}-aurora-db-instance-primary
DBInstanceClass: db.r5.large
Engine: aurora-postgresql
DBClusterIdentifier: !Ref AWSTestAuroraDBCluster
PubliclyAccessible: false
Outputs:
GlobalClusterIdentifier:
Description: Aurora Global Database Identifier
Value: !Ref AWSTestAuroraGlobalDatabase
Export:
Name: !Sub ${AWS::StackName}-GlobalClusterIdentifier
大阪リージョンデプロイ分テンプレート
AWSTemplateFormatVersion: '2010-09-09'
Description: Aurora PostgreSQL Global Database Headless Secondary Cluster in Osaka Region
Parameters:
SystemName:
Type: String
Default: aws
Description: System name of each resource names
EnvName:
Type: String
Default: test
Description: Environment name of each resource names
GlobalClusterIdentifier:
Type: String
Description: Global cluster identifier from primary region
Resources:
#============================================================#
# VPC
#============================================================#
AWSTestVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.1.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: Aurora-Global-VPC-Osaka
#============================================================#
# Private subnets
#============================================================#
AWSTestPrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref AWSTestVPC
CidrBlock: 10.1.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: Aurora-Private-Subnet-1
AWSTestPrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref AWSTestVPC
CidrBlock: 10.1.2.0/24
AvailabilityZone: !Select [1, !GetAZs '']
Tags:
- Key: Name
Value: Aurora-Private-Subnet-2
#============================================================#
# DB Subnet Group
#============================================================#
AWSTestDBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnet group for Aurora Global Database Secondary
SubnetIds:
- !Ref AWSTestPrivateSubnet1
- !Ref AWSTestPrivateSubnet2
Tags:
- Key: Name
Value: Aurora-Global-SubnetGroup-Secondary
#============================================================#
# Security Group for Aurora
#============================================================#
AWSTestAuroraSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Aurora PostgreSQL Secondary
VpcId: !Ref AWSTestVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
CidrIp: 10.1.0.0/16
Tags:
- Key: Name
Value: Aurora-Global-SecurityGroup-Secondary
#============================================================#
# Secondary Aurora DB Cluster (Headless - no instances)
#============================================================#
AWSTestAuroraDBCluster:
Type: AWS::RDS::DBCluster
Properties:
DBClusterIdentifier: !Sub ${SystemName}-${EnvName}-aurora-db-cluster-secondary
Engine: aurora-postgresql
EngineVersion: 15.4
DBSubnetGroupName: !Ref AWSTestDBSubnetGroup
VpcSecurityGroupIds:
- !Ref AWSTestAuroraSecurityGroup
StorageEncrypted: true
KmsKeyId: alias/aws/rds
GlobalClusterIdentifier: !Ref GlobalClusterIdentifier
東京では、このようにAuroraクラスターに加えてAuroraインスタンスも記述しています。
#============================================================#
# Primary Aurora DB Cluster
#============================================================#
# Primary Aurora DB Cluster
AWSTestAuroraDBCluster:
Type: AWS::RDS::DBCluster
Properties:
DBClusterIdentifier: !Sub ${SystemName}-${EnvName}-aurora-db-cluster-primary
Engine: aurora-postgresql
EngineVersion: 15.4
MasterUsername: postgres
MasterUserPassword: password # 本番環境ではAWS Secrets Managerなどで強力なパスワードを必ず管理してください
DBSubnetGroupName: !Ref AWSTestDBSubnetGroup
VpcSecurityGroupIds:
- !Ref AWSTestAuroraSecurityGroup
StorageEncrypted: true
BackupRetentionPeriod: 7
PreferredBackupWindow: 03:00-04:00
PreferredMaintenanceWindow: sun:04:00-sun:05:00
GlobalClusterIdentifier: !Ref AWSTestAuroraGlobalDatabase
#============================================================#
# Primary Aurora DB Instance
#============================================================#
# Primary Aurora DB Instance
AWSTestAuroraDBInstance:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: !Sub ${SystemName}-${EnvName}-aurora-db-instance-primary
DBInstanceClass: db.r5.large
Engine: aurora-postgresql
DBClusterIdentifier: !Ref AWSTestAuroraDBCluster
PubliclyAccessible: false
一方で大阪では、Auroraクラスターのみを記述することで、大阪リージョンではヘッドレスクラスターになります。
#============================================================#
# Secondary Aurora DB Cluster (Headless - no instances)
#============================================================#
AWSTestAuroraDBCluster:
Type: AWS::RDS::DBCluster
Properties:
DBClusterIdentifier: !Sub ${SystemName}-${EnvName}-aurora-db-cluster-secondary
Engine: aurora-postgresql
EngineVersion: 15.4
DBSubnetGroupName: !Ref AWSTestDBSubnetGroup
VpcSecurityGroupIds:
- !Ref AWSTestAuroraSecurityGroup
StorageEncrypted: true
KmsKeyId: alias/aws/rds
GlobalClusterIdentifier: !Ref GlobalClusterIdentifier
構築
実際の構築手順は次のようになります。
- 東京用テンプレートを使って、東京リージョンにAurora Global Databaseを構築
- Aurora Global DatabaseのクラスターIDをメモ
- 大阪用テンプレートを使って、大阪リージョンにAurora Global Databaseを構築
- この際、メモしたクラスターIDをパラメータとして入力
まずは、東京用テンプレートを使って、東京リージョンにAurora Global Databaseを構築します。
% aws cloudformation create-stack \
--stack-name aurora-global-primary-tokyo \
--template-body file://aurora-global-headless-tokyo.yaml \
--region ap-northeast-1
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:************:stack/aurora-global-primary-tokyo/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
構築には数分かかりますが、構築が完了すると、このようにAuroraクラスターの上位にGlobal Databaseが設定されていることが分かります。
このGlobal DatabaseのIDをメモします。
このIDをパラメータとして入力して、同様に大阪リージョンでも作成していきます。
% aws cloudformation create-stack \
--stack-name aurora-global-secondary-osaka \
--template-body file://aurora-global-headless-osaka.yaml \
--parameters ParameterKey=GlobalClusterIdentifier,ParameterValue=<取得したGlobal Database ID> \
--region ap-northeast-3
{
"StackId": "arn:aws:cloudformation:ap-northeast-3:************:stack/aurora-global-secondary-osaka/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
作成が完了すると、このように大阪リージョンでGlobal Databaseの確認ができるようになります。
クロスリージョンですので、東京リージョンでも同様にコンソールに表示されます。
既存のGlobal Databaseを指定した状態で、セカンダリリージョンではインスタンスを作成しないことでヘッドレスクラスターとする
CFnテンプレートに関しては、東京リージョンと大阪リージョンで別々のCFnテンプレートを用意し、先にデプロイした東京のGlobal Databaseを大阪デプロイ時に指定する必要があると分かりました。
また、大阪側をヘッドレスクラスターにする場合は、Auroraインスタンスを記載しないことが必要です。
構築するにあたって気になる部分でしたので、ひとまず検証できました。この記事が参考にされば幸いです。では!