この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
題名通り、CloudFormation で Aurora (MySQL) と RDS Proxy を作成します。
ただし、Aurora と RDS Proxy を作成する上で、以下のawsリソースも必要になりますので、CloudFormation のテンプレートに記載します。
- Secrets Manager (AuroraのDB情報を保存)
- IAM ロールとポリシー (RDS Proxy 用)
- セキュリティグループ (Aurora,RDS Proxy )
- インターフェイス型VPCエンドポイント (RDS Proxy が Secrets Manager にアクセスするため)
注意点として、RDS Proxy を作成すると、VPCエンドポイントは、自動作成されるようです。私は、ここでつまづきました。。
そのため、CloudFormation のテンプレートファイルには、VPCエンドポイントは、記載しません。
VPCエンドポイントの自動作成の挙動
ドキュメントでは該当の記述が見つけられませんでしたが、今回の CloudFormation での作成や、コンソール画面から RDS Proxy を作成し確認した限りでは、VPCエンドポイントは自動生成されておりました。
前提条件
- VPC と 2つの Private Subnet (アベイラビリティゾーン2つ) を作成済み
- RDS Proxy にアクセスする EC2 や Lambda の作成方法は説明しません。
構成図
前提条件にも記載しましたが、Lambda や EC2は、今回の CloudFormation では、作成しません。
テンプレートの作成
テンプレートは、ymlファイルを採用し、下記のymlファイルをそのままコピペして使用します。
RDS Proxy のセキュリティグループのインバウンドには、例として Lambda のセキュリティグループを作成し、許可するようにしています。
そのため、下記テンプレート内の Resources の LambdaSecurityGroup
は、個々で作成したいセキュリティグループに変えても大丈夫です。
CloudFormationテンプレート (クリックすると展開します)
AWSTemplateFormatVersion: '2010-09-09'
Description: Create Aurora and RDS Proxy
Parameters:
PJPrefix:
Type: String
VpcId:
Type: AWS::EC2::VPC::Id
Description: vpc id
EngineType:
Type: String
Default: aurora-mysql
MySQLMajorVersion:
Type: String
Default: 5.7
MySQLMinorVersion:
Type: String
Default: 2.11.0
DBInstanceClass:
Type: String
Default: db.t3.small
PrivateSubnetIdA:
Type: AWS::EC2::Subnet::Id
PrivateSubnetIdC:
Type: AWS::EC2::Subnet::Id
DatabaseName:
Type: String
MasterUsername:
NoEcho: true
Type: String
MinLength: 1
MaxLength: 16
AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
ConstraintDescription: Must begin with a letter and contain only alphanumeric characters.
MasterUserPassword:
NoEcho: true
Type: String
MinLength: 8
MaxLength: 41
AllowedPattern: '[a-zA-Z0-9]*'
ConstraintDescription: Must contain only alphanumeric characters.
SecretsManagerKMSKeyId:
Type: String
Description: AWS managed key in aws/secretsmanager
Resources:
RDSProxySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub ${PJPrefix}-rds-proxy
GroupName: !Sub ${PJPrefix}-rds-proxy
Tags:
- Key: Name
Value: !Sub ${PJPrefix}-rds-proxy
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref LambdaSecurityGroup
SourceSecurityGroupOwnerId: !Ref AWS::AccountId
Description: !Sub ${PJPrefix}-lambda
FromPort: 3306
IpProtocol: tcp
ToPort: 3306
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
VpcId: !Ref VpcId
RDSSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub ${PJPrefix}-rds
GroupName: !Sub ${PJPrefix}-rds
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref RDSProxySecurityGroup
SourceSecurityGroupOwnerId: !Ref AWS::AccountId
Description: !Sub ${PJPrefix}-rds-proxy
FromPort: 3306
IpProtocol: tcp
ToPort: 3306
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
IpProtocol: '-1'
Tags:
- Key: Name
Value: !Sub ${PJPrefix}-rds
VpcId: !Ref VpcId
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub ${PJPrefix}-lambda
GroupName: !Sub ${PJPrefix}-lambda
Tags:
- Key: Name
Value: !Sub ${PJPrefix}-lambda
VpcId: !Ref VpcId
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
IpProtocol: '-1'
DBCluster:
Type: AWS::RDS::DBCluster
DeletionPolicy: Delete
Properties:
BackupRetentionPeriod: 7
DatabaseName: !Ref DatabaseName
DBSubnetGroupName: !Ref DBSubnetGroup
DBClusterParameterGroupName: !Ref DBClusterParameterGroup
DBClusterIdentifier: !Ref PJPrefix
DeletionProtection: false
Engine: !Ref EngineType
EngineMode: provisioned
EngineVersion: !Sub ${MySQLMajorVersion}.mysql_aurora.${MySQLMinorVersion}
MasterUsername: !Ref MasterUsername
MasterUserPassword: !Ref MasterUserPassword
PreferredBackupWindow: 16:00-17:00
PreferredMaintenanceWindow: tue:18:00-tue:19:00
StorageEncrypted: true
VpcSecurityGroupIds:
- !Ref RDSSecurityGroup
DBClusterParameterGroup:
Type: AWS::RDS::DBClusterParameterGroup
Properties:
Description: !Sub ${PJPrefix}-DBClusterParameterGroup
Family: aurora-mysql5.7
Parameters:
time_zone: Asia/Tokyo
DBInstance:
Type: AWS::RDS::DBInstance
DeletionPolicy: Delete
Properties:
AutoMinorVersionUpgrade: false
AvailabilityZone: !Sub ${AWS::Region}a
DBClusterIdentifier: !Ref DBCluster
DBParameterGroupName: !Ref DBParameterGroup
DBInstanceClass: !Ref DBInstanceClass
DBSubnetGroupName: !Ref DBSubnetGroup
DBInstanceIdentifier: !Sub ${PJPrefix}-instance
Engine: !Ref EngineType
EngineVersion: !Sub ${MySQLMajorVersion}.mysql_aurora.${MySQLMinorVersion}
EnablePerformanceInsights: false
MonitoringInterval: 0
PubliclyAccessible: false
PreferredMaintenanceWindow: tue:18:00-tue:19:00
PromotionTier: 1
DBParameterGroup:
Type: AWS::RDS::DBParameterGroup
Properties:
Description: !Sub ${PJPrefix}-DBParameterGroup
Family: !Sub ${EngineType}${MySQLMajorVersion}
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupName: !Sub ${PJPrefix}-subnet
DBSubnetGroupDescription: '-'
SubnetIds:
- !Ref PrivateSubnetIdA
- !Ref PrivateSubnetIdC
DBProxy:
Type: AWS::RDS::DBProxy
Properties:
Auth:
- AuthScheme: SECRETS
SecretArn: !Ref SecretsManager
IAMAuth: DISABLED
DBProxyName: !Ref PJPrefix
DebugLogging: false
EngineFamily: MYSQL
IdleClientTimeout: 1800
RequireTLS: false
RoleArn: !GetAtt RDSProxyIAMRole.Arn
VpcSecurityGroupIds:
- !Ref RDSProxySecurityGroup
VpcSubnetIds:
- !Ref PrivateSubnetIdA
- !Ref PrivateSubnetIdC
DBProxyTargetGroup:
Type: AWS::RDS::DBProxyTargetGroup
Properties:
ConnectionPoolConfigurationInfo:
MaxConnectionsPercent: 100
MaxIdleConnectionsPercent: 50
ConnectionBorrowTimeout: 120
DBProxyName: !Ref DBProxy
DBClusterIdentifiers:
- !Ref DBCluster
TargetGroupName: default
SecretsManager:
Type: AWS::SecretsManager::Secret
Properties:
Name: !Sub ${PJPrefix}-proxy
Description: !Sub ${PJPrefix}-proxy
SecretString: !Sub '{
"username": "${MasterUsername}",
"password": "${MasterUserPassword}",
"engine":"mysql",
"host": "${DBCluster.Endpoint.Address}",
"port":"3306",
"dbClusterIdentifier": "${DBCluster}"
}'
Tags:
- Key: Name
Value: !Sub ${PJPrefix}-rds-proxy
RDSProxyIAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- rds.amazonaws.com
Action:
- sts:AssumeRole
MaxSessionDuration: 3600
ManagedPolicyArns:
- !Ref SecretsManagerManagedPolicy
Path: /service-role/
RoleName: !Sub ${PJPrefix}-rds-proxy
SecretsManagerManagedPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Description: Get values from Secrets Manager
ManagedPolicyName: !Sub ${PJPrefix}-rds-proxy
Path: /
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource: !Ref SecretsManager
- Effect: Allow
Action:
- kms:Decrypt
Resource: !Sub arn:aws:kms:${AWS::Region}:${AWS::AccountId}:key/${SecretsManagerKMSKeyId}
Condition:
StringEquals:
kms:ViaService: !Sub secretsmanager.${AWS::Region}.amazonaws.com
パラメータ SecretsManagerKMSKeyId の説明
Secrets Manager では、KMS キーで暗号化を行うため、KMS キーが必要になります。
KMS キーには、AWS マネージド型キー
と カスタマー管理型のキー
の2種類ありますが、今回は、AWS マネージド型キー
を利用します。
スタックのパラメータのうち SecretsManagerKMSKeyId
は、 AWS マネージド型キー
のエイリアスaws/secretsmanager
のキーIDの値になります。
KMS キー aws/secretsmanager
が存在しない場合、Secrets Manager を利用されたことがない可能性があります。
適当にシークレットを作成すると、表示されるようになります。
Secrets Managerのコンソールに移動し、適当にシークレットを作成すると、キーが作成されます。
このキーIDをSecretsManagerKMSKeyId
に指定しましょう。
スタック作成
スタックを作成しましょう。
スタックが作成されるまで20分弱かかります。
成功を確認後、以下のリソースが作成されているか確認しましょう。
- Aurora (MySQL)
- RDS Proxy
- Secrets Manager (AuroraのDB情報を保存)
- IAM ロールとポリシー(RDS Proxy用)
- セキュリティグループ (Aurora, RDS Proxy, Lambda用)
- VPCエンドポイント
無事、作成することができました。
コンソールではなく、CloudFormation を利用することで、必要なときにパッと作成することができるので、便利ですね!
参考
AWS CloudFormation の Template reference