[AWS]Aurora PostgreSQLをCloudFormationで構築する

コンニチハ、千葉です。

CloudFormationにて、Aurora PostgreSQL を構築する機会がありましたので、コピペできるようにCloudFormationテンプレートを置いておきます。 Aurora PostgreSQLを作成するスニペットがなかったので、CloudFormationのドキュメントを読みまくって作りました。実際書くと結構苦労することが多いと思いますので、コピペできるようにブログ化しておきます!

はじめに

作成したCloudFormationテンプレートを利用するにあたり、前提やポイントをまとめます。

前提

CloudFormationスタックを作成する前に、以下を確認しておきましょう。

  • VPCが作成済みであること
  • RDS用のセキュリティグループが作成済みであること

作成されるリソース

このテンプレートで作成されるリソースは以下です。

  • DBサブネットグループ
  • クラスターパラメータグループ
  • DBパラメータグループ
  • マスターインスタンス
  • リードレプリカインスタンス
  • 拡張モニタリング用のIAMロール

ポイント

こちらのテンプレートは以下のパラメータになります。

  • DBインスタンスの削除保護が有効
  • 拡張モニタリングが有効
  • PerformanceInsightsが有効
  • ディスクを暗号化
  • パブリックアクセスが無効

注意事項

マスターが配置されるAZを指定できないので、任意のAZにマスターを移動したい場合は、手動でフェイルオーバーを行なってください。

CloudFormationテンプレート

コピペで利用できます。Mappingsパラメータを適宜変更してご利用ください。

AWSTemplateFormatVersion: '2010-09-09'
Description: This CloudFormation template to create RDS db instances.

Mappings:
  prd:
    DBSubnet1a:       { ID: subnet-xxx }
    DBSubnet1c:       { ID: subnet-xxx }
    RdsSecurityGroup: { ID: sg-xxx }
    DBInstance:
      Engine: aurora-postgresql
      EngineVersion: 10.6
      RDS1AvailabilityZone: ap-northeast-1a
      RDS2AvailabilityZone: ap-northeast-1c
      BackupRetentionPeriod: 7
      PreferredBackupWindow: 13:00-13:30
      ClusterPreferredMaintenanceWindow: tue:13:30-tue:14:00
      InstancePreferredMaintenanceWindow: wed:13:30-wed:14:00
      DatabaseName: chiba_db
      AutoMinorVersionUpgrade: true
      DBInstanceClass: db.r5.large
    DBParameterGroup:
      DBEngineFamily: aurora-postgresql10

Parameters:
  Environment:
    Description: Type of this environment.
    Type: String
    Default: prd
    AllowedValues:
      - prd
      - stg
  SystemName:
    Description: Name of this system.
    Type: String
    Default: chiba-rds
  Username:
    Description: Name of DB mater username.
    Type: String
    Default: admin
  Password:
    Description: Name of DB mater user password.
    Type: String
    NoEcho: true

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: Environment Configuration
      Parameters:
        - SystemName
        - Environment
    - Label:
        default: RDS DB instace Configuration
      Parameters:
        - Username
        - Password

Resources:
  # IAM Role for enhanced monitoring
  RDSMonitoringRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${SystemName}-${Environment}-rds-monitoring-role
      Path: /
      AssumeRolePolicyDocument:
        !Sub |
          {
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Principal": {
                  "Service": "monitoring.rds.amazonaws.com"
                },
                "Action": "sts:AssumeRole"
              }
            ]
          }
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole

  RDSCluster:
    Type: AWS::RDS::DBCluster
    Properties:
      MasterUsername: !Ref Username
      MasterUserPassword: !Ref Password
      Engine: !FindInMap [ !Ref Environment, DBInstance, Engine ]
      DBSubnetGroupName: !Ref DBSubnetGroup
      DBClusterParameterGroupName: !Ref RDSDBClusterParameterGroup
      VpcSecurityGroupIds:
        - !FindInMap [ !Ref Environment, RdsSecurityGroup, ID ]
      BackupRetentionPeriod: !FindInMap [ !Ref Environment, DBInstance, BackupRetentionPeriod ]
      PreferredBackupWindow: !FindInMap [ !Ref Environment, DBInstance, PreferredBackupWindow ]
      DatabaseName: !FindInMap [ !Ref Environment, DBInstance, DatabaseName ]
      DBClusterIdentifier: !Sub ${SystemName}-${Environment}-aurora-posgre
      DeletionProtection: true
      EngineMode: provisioned
      EngineVersion: !FindInMap [ !Ref Environment, DBInstance, EngineVersion ]
      PreferredMaintenanceWindow: !FindInMap [ !Ref Environment, DBInstance, ClusterPreferredMaintenanceWindow ]
      StorageEncrypted: true
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${Environment}-aurora-posgre-cluster

  RDSDBInstance1:
    Type: AWS::RDS::DBInstance
    Properties:
      DBSubnetGroupName: !Ref DBSubnetGroup
      DBParameterGroupName: !Ref RDSDBParameterGroup
      Engine: !FindInMap [ !Ref Environment, DBInstance, Engine ]
      EngineVersion: !FindInMap [ !Ref Environment, DBInstance, EngineVersion ]
      DBClusterIdentifier: !Ref RDSCluster
      PubliclyAccessible: 'false'
      AvailabilityZone: !FindInMap [ !Ref Environment, DBInstance, RDS1AvailabilityZone ]
      DBInstanceClass: !FindInMap [ !Ref Environment, DBInstance, DBInstanceClass ]
      AutoMinorVersionUpgrade: !FindInMap [ !Ref Environment, DBInstance, AutoMinorVersionUpgrade ]
      CopyTagsToSnapshot: true
      DBInstanceIdentifier: !Sub ${SystemName}-${Environment}-aurora-posgre-1
      EnablePerformanceInsights: true
      PreferredMaintenanceWindow: !FindInMap [ !Ref Environment, DBInstance, InstancePreferredMaintenanceWindow ]
      DeletionProtection: true
      MonitoringInterval: 60
      MonitoringRoleArn: !GetAtt RDSMonitoringRole.Arn
      PubliclyAccessible: false
      PromotionTier: 1
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${Environment}-aurora-posgre-1

  RDSDBInstance2:
    Type: AWS::RDS::DBInstance
    Properties:
      DBSubnetGroupName: !Ref DBSubnetGroup
      DBParameterGroupName: !Ref RDSDBParameterGroup
      Engine: !FindInMap [ !Ref Environment, DBInstance, Engine ]
      EngineVersion: !FindInMap [ !Ref Environment, DBInstance, EngineVersion ]
      DBClusterIdentifier: !Ref RDSCluster
      PubliclyAccessible: 'false'
      AvailabilityZone: !FindInMap [ !Ref Environment, DBInstance, RDS2AvailabilityZone ]
      DBInstanceClass: !FindInMap [ !Ref Environment, DBInstance, DBInstanceClass ]
      AutoMinorVersionUpgrade: !FindInMap [ !Ref Environment, DBInstance, AutoMinorVersionUpgrade ]
      CopyTagsToSnapshot: true
      DBInstanceIdentifier: !Sub ${SystemName}-${Environment}-aurora-posgre-2
      EnablePerformanceInsights: true
      PreferredMaintenanceWindow: !FindInMap [ !Ref Environment, DBInstance, InstancePreferredMaintenanceWindow ]
      DeletionProtection: true
      MonitoringInterval: 60
      MonitoringRoleArn: !GetAtt RDSMonitoringRole.Arn
      PubliclyAccessible: false
      PromotionTier: 2
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${Environment}-aurora-posgre-2

  # DB subnet group
  DBSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupName: !Sub ${SystemName}-${Environment}-db-subnet-group
      DBSubnetGroupDescription: !Sub ${SystemName}-${Environment}-db-subnet-group
      SubnetIds:
        - !FindInMap [ !Ref Environment, DBSubnet1a, ID ]
        - !FindInMap [ !Ref Environment, DBSubnet1c, ID ]
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${Environment}-db-subnet-group

  # DB Cluster Parameter Group
  RDSDBClusterParameterGroup:
    Type: AWS::RDS::DBClusterParameterGroup
    Properties:
      Description: !Sub ${SystemName}-${Environment}-db-cluster-param-group
      Family: !FindInMap [ !Ref Environment, DBParameterGroup, DBEngineFamily ]
      Parameters:
        client_encoding: UTF8
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${Environment}-db-cluster-param-group

  # DB parameter group
  RDSDBParameterGroup:
    Type: AWS::RDS::DBParameterGroup
    Properties:
      Description: !Sub ${SystemName}-${Environment}-db-param-group
      Family: !FindInMap [ !Ref Environment, DBParameterGroup, DBEngineFamily ]
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${Environment}-db-param-group

最後に

RDSのCloudFormation化はやっていたのですが、Auroraは初でした。RDSだとDBInstanceにバックアップパラメータを指定しますが、AuroraだとDBClusterリソースがあり、こちらにバックアップなどのいくつかの定義をする必要があります。また、AuroraはマスターとリードレプリカそれぞれDBInstanceリソースを作る必要がありました。いざ作ってみると、はまることもあると思うので、参考にしてみてください!

参考

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html