この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
どーもsutoです。
AuroraのリードレプリカのAutoscaling設定をCloudFormationで作成しようとAWS公式ページのAutoscalingテンプレートスニペットをコピペしてスタック作成したところ、エラーとなってスタックが完了しなかった話をします。
ハマったところ
こちら公式ページの「Aurora DB クラスターのスケーリングポリシーの宣言」の内容でAuroraのAutoscaling設定を作成できるか検証してみたところ、
「No scalable target registered for 〜〜」というエラーメッセージが表示され、ロールバックしてしまいました。
多少数値を変えたりDBクラスター識別子を自分の検証用の名前に変えたりはしましたが、公式ページとまったく同じプロパティを使っているのに何故なんだ〜!
当初は「まさか公式で紹介しているコードが間違っているわけないよな」と思い込み、7〜8回再試行してみましたが何故か1回だけCREATE_COMPLETEでき、残りの試行は全てROLLBACKに。
むしろ何故1回だけ成功した?
これって低確率で成功するテンプレなのか。。。(そんなわけがないだろ!)とテンパリつつも、冷静にエラーメッセージを確認。
対策について
scalable targetが見つからないというエラーだから、テンプレート内にある「ScalableTarget」が先にリソース作成されないとダメなのか。ということはリソース作成の優先順位をしっかりつければいいいのだろうけど、プロパティのなかで他に代替できる項目があるかな〜?
てなわけで公式ページのリファレンスを眺めてみると、
あー、この「ScalindTargetId」に置き換えればいいんじゃない?と思い、以下のようにテンプレートを修正しました。
ScalableTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
Properties:
MaxCapacity: 3
MinCapacity: 1
RoleARN:
Fn::Sub: 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/rds.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_RDSCluster'
ServiceNamespace: rds
ScalableDimension: 'rds:cluster:ReadReplicaCount'
ResourceId: !Sub cluster:${SampleDBCluster}
ScalingPolicyDBCluster:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: !Sub ${SampleDBCluster}-asg
PolicyType: TargetTrackingScaling
ScalingTargetId: !Ref ScalableTarget
TargetTrackingScalingPolicyConfiguration:
TargetValue: 80
PredefinedMetricSpecification:
PredefinedMetricType: RDSReaderAverageCPUUtilization
ScaleInCooldown: 600
ScaleOutCooldown: 300
{SampleDBCluster}は既存のAuroraDBクラスター識別子が入ります。
これでスタックを実行してみると、
無事STACK_COMPLETEになりました!(もちろん成功率100%です!!)
リードレプリカがAutoscalingするAuroraDBを作成するテンプレート
せっかくトラブルが解決できたので、Auroraクラスターもまとめて新規作成できるようなテンプレートを作ってみました。
- 構成は、クラスター:1台、Writerノード:1台、Readerノード:1台
- CPU使用率70%以上でReaderノードがスケール
- スケールキャパシティは、最小:1、最大:3
- クールダウンは、スケールイン:10分、スケールアウト:5分
- masterユーザ名/パスワードはSecret Managerで自動生成
- "DeletionProtection"は、本番利用時にはコメント(#)を外して設定するようにしましょう。
AWSTemplateFormatVersion: "2010-09-09"
Description: Provision of Aurora MySQL
Parameters:
ProjectName:
Description: ProjectName
Type: String
EngineVersion:
Type: String
InstanceClass:
Type: String
VPCId:
Type: String
Description: ID for VPC.
PrimarySubnetId:
Type: String
Description: Subnet id on which Aurora instance locates.
SecondarySubnetId:
Type: String
Description: Subnet id on which Aurora instance locates.
EC2SGId:
Type: String
Description: ID for EC2 Security Group.
Resources:
SampleDBCluster:
Type: AWS::RDS::DBCluster
Properties:
DBClusterIdentifier: !Sub ${ProjectName}-auroradb
DBClusterParameterGroupName: !Ref 'SampleDBClusterParameterGroup'
DBSubnetGroupName: !Ref SampleDBSubnetGroup
Engine: aurora-mysql
EngineVersion: !Ref 'EngineVersion'
MasterUserPassword: !Sub "{{resolve:secretsmanager:${AuroraDBSecret}:SecretString:password::}}"
MasterUsername: !Sub '{{resolve:secretsmanager:${AuroraDBSecret}:SecretString:username}}'
VpcSecurityGroupIds:
- !GetAtt 'SampleSecurityGroup.GroupId'
#DeletionProtection: 'True'
PreferredMaintenanceWindow: 'Sun:14:30-Sun:15:00'
Tags:
- Key: Name
Value: !Sub ${ProjectName}-aurora
- Key: backup
Value: 'True'
SampleDBClusterParameterGroup:
Type: AWS::RDS::DBClusterParameterGroup
Properties:
Description: !Sub ${ProjectName}-aurora
Family: aurora-mysql5.7
Parameters:
time_zone: Asia/Tokyo
SampleDBInstanceA:
Type: AWS::RDS::DBInstance
Properties:
DBClusterIdentifier: !Ref 'SampleDBCluster'
DBInstanceClass: !Ref 'InstanceClass'
Engine: aurora-mysql
PreferredMaintenanceWindow: 'Sun:15:00-Sun:15:30'
SampleDBInstanceB:
Type: AWS::RDS::DBInstance
Properties:
DBClusterIdentifier: !Ref 'SampleDBCluster'
DBInstanceClass: !Ref 'InstanceClass'
Engine: aurora-mysql
PreferredMaintenanceWindow: 'Sun:15:30-Sun:16:00'
SampleDBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: sample-aurora
DBSubnetGroupName: !Sub ${ProjectName}-aurora-nw
SubnetIds:
- !Ref PrimarySubnetId
- !Ref SecondarySubnetId
SampleSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub ${ProjectName}-aurora
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref EC2SGId
FromPort: 3306
IpProtocol: tcp
ToPort: 3306
VpcId: !Ref VPCId
AuroraDBSecret:
Type: AWS::SecretsManager::Secret
Properties:
GenerateSecretString:
SecretStringTemplate: '{"username": "admin"}'
GenerateStringKey: "password"
PasswordLength: 16
ExcludeCharacters: '"@/\'
Name: !Sub ${ProjectName}-aurora-secret
ScalableTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
Properties:
MaxCapacity: 3
MinCapacity: 1
RoleARN:
Fn::Sub: 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/rds.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_RDSCluster'
ServiceNamespace: rds
ScalableDimension: 'rds:cluster:ReadReplicaCount'
ResourceId: !Sub cluster:${SampleDBCluster}
ScalingPolicyDBCluster:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: !Sub ${SampleDBCluster}-asg
PolicyType: TargetTrackingScaling
ScalingTargetId: !Ref ScalableTarget
TargetTrackingScalingPolicyConfiguration:
TargetValue: 80
PredefinedMetricSpecification:
PredefinedMetricType: RDSReaderAverageCPUUtilization
ScaleInCooldown: 600
ScaleOutCooldown: 300
Outputs:
GetSecretValueByCLI:
Value: !Sub |+
aws secretsmanager get-secret-value
--secret-id ${AuroraDBSecret}
--region ${AWS::Region}
--query SecretString
まとめ
冒頭で紹介したように、公式ページのスニペットをそのまま使おうとすると私と同じエラーを経験をすることになるかと思うのでご注意を。
同じ境遇になった方や、これから似たようなテンプレを作ろうとしている方に本記事が参考になれば幸いです。