Skip to content

Instantly share code, notes, and snippets.

@sjparkinson
Last active May 10, 2022 10:43
Show Gist options
  • Star 54 You must be signed in to star a gist
  • Fork 29 You must be signed in to fork a gist
  • Save sjparkinson/e1c2f74475d2e8625ce4af85b892ab13 to your computer and use it in GitHub Desktop.
Save sjparkinson/e1c2f74475d2e8625ce4af85b892ab13 to your computer and use it in GitHub Desktop.
A basic CloudFormation template for an RDS Aurora cluster.
---
AWSTemplateFormatVersion: 2010-09-09
Description: >
A basic CloudFormation template for an RDS Aurora cluster.
Parameters:
DatabaseUsername:
AllowedPattern: "[a-zA-Z0-9]+"
ConstraintDescription: must be between 1 to 16 alphanumeric characters.
Description: The database admin account user name, between 1 to 16 alphanumeric characters.
MaxLength: '16'
MinLength: '1'
Type: String
DatabasePassword:
AllowedPattern: "[a-zA-Z0-9]+"
ConstraintDescription: must be between 8 to 41 alphanumeric characters.
Description: The database admin account password, between 8 to 41 alphanumeric characters.
MaxLength: '41'
MinLength: '8'
NoEcho: 'true'
Type: String
Mappings:
'000000000000':
us-east-1:
Subnets:
- subnet-00000000
- subnet-11111111
- subnet-22222222
SecurityGroups:
- sg-00000000
InstanceType: db.r4.large
BackupRetentionPeriod: 7
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Database Configuration
Parameters:
- DatabaseUsername
- DatabasePassword
ParameterLabels:
DatabaseUsername:
default: Database Username
DatabasePassword:
default: Database Password
Resources:
StackAlarmTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: Stack Alarm Topic
DatabaseSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: CloudFormation managed DB subnet group.
SubnetIds: !FindInMap [!Ref "AWS::AccountId", !Ref "AWS::Region", "Subnets"]
DatabaseCluster:
Type: AWS::RDS::DBCluster
Properties:
Engine: aurora
MasterUsername: !Ref "DatabaseUsername"
MasterUserPassword: !Ref "DatabasePassword"
BackupRetentionPeriod: !FindInMap [!Ref "AWS::AccountId", !Ref "AWS::Region", "BackupRetentionPeriod"]
PreferredBackupWindow: 01:00-02:00
PreferredMaintenanceWindow: mon:03:00-mon:04:00
DBSubnetGroupName: !Ref "DatabaseSubnetGroup"
VpcSecurityGroupIds: !FindInMap [!Ref "AWS::AccountId", !Ref "AWS::Region", "SecurityGroups"]
DatabasePrimaryInstance:
Type: AWS::RDS::DBInstance
Properties:
Engine: aurora
DBClusterIdentifier: !Ref "DatabaseCluster"
DBInstanceClass: !FindInMap [!Ref "AWS::AccountId", !Ref "AWS::Region", "InstanceType"]
DBSubnetGroupName: !Ref "DatabaseSubnetGroup"
DatabasePrimaryCPUAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Primary database CPU utilization is over 80%.
Namespace: AWS/RDS
MetricName: CPUUtilization
Unit: Percent
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 80
ComparisonOperator: GreaterThanOrEqualToThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref "DatabasePrimaryInstance"
AlarmActions:
- Ref: StackAlarmTopic
InsufficientDataActions:
- Ref: StackAlarmTopic
DatabasePrimaryMemoryAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Primary database freeable memory is under 700MB.
Namespace: AWS/RDS
MetricName: FreeableMemory
Unit: Bytes
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 700000000
ComparisonOperator: LessThanOrEqualToThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref "DatabasePrimaryInstance"
AlarmActions:
- Ref: StackAlarmTopic
InsufficientDataActions:
- Ref: StackAlarmTopic
DatabasePrimaryReplicationAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Database replication latency is over 200ms.
Namespace: AWS/RDS
MetricName: AuroraReplicaLag
Unit: Milliseconds
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 200
ComparisonOperator: GreaterThanOrEqualToThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref "DatabaseReplicaInstance"
AlarmActions:
- Ref: StackAlarmTopic
DatabaseReplicaInstance:
Type: AWS::RDS::DBInstance
Properties:
Engine: aurora
DBClusterIdentifier: !Ref "DatabaseCluster"
DBInstanceClass: !FindInMap [!Ref "AWS::AccountId", !Ref "AWS::Region", "InstanceType"]
DBSubnetGroupName: !Ref "DatabaseSubnetGroup"
DatabaseReplicaCPUAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Replica database CPU utilization is over 80%.
Namespace: AWS/RDS
MetricName: CPUUtilization
Unit: Percent
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 80
ComparisonOperator: GreaterThanOrEqualToThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref "DatabaseReplicaInstance"
AlarmActions:
- Ref: StackAlarmTopic
InsufficientDataActions:
- Ref: StackAlarmTopic
DatabaseReplicaMemoryAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Replica database freeable memory is under 700MB.
Namespace: AWS/RDS
MetricName: FreeableMemory
Unit: Bytes
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 700000000
ComparisonOperator: LessThanOrEqualToThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref "DatabaseReplicaInstance"
AlarmActions:
- Ref: StackAlarmTopic
InsufficientDataActions:
- Ref: StackAlarmTopic
DatabaseReplicaReplicationAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Database replication latency is over 200ms.
Namespace: AWS/RDS
MetricName: AuroraReplicaLag
Unit: Milliseconds
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 200
ComparisonOperator: GreaterThanOrEqualToThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref "DatabaseReplicaInstance"
AlarmActions:
- Ref: StackAlarmTopic
@larriebee
Copy link

👍 Yep, I had to take one of them out as well to get the template to work.

@zerokelvin-27315
Copy link

DatabasePrimaryMemoryAlarm is defined twice - it looks like the second instance should be: DatabaseReplicaMemoryAlarm

@phette
Copy link

phette commented Oct 4, 2017

The primary and replica instances will come up in parallel where the replica might complete first and therefore become the primary of the cluster. It's fairly inconsequential, but it happened to me as I was explicitly specifying the name of each instance with "primary" and "replica" append to the name of each. You can remedy that by adding a DependsOn where the replica can't come up until the primary is complete. However, that will drastically increase the initial deployment time. Otherwise, you could change the logic ids to be agnostic about which one is the primary/replica.

@sjparkinson
Copy link
Author

Thanks for all the comments. I've gone ahead and made some changes, and fixed the copy pasta issue.

We've learnt a few things at the FT since I first wrote this template, one of the major things was to make more use of mappings instead of parameters.

Found it tricky to find a good name for the instance resources @phette, so left them as they are.

At the time of writing, we're also currently looking for a Cloud Platform Engineer for anyone interested, see https://aboutus.ft.com/en-gb/careers/current-openings.

@ernievd
Copy link

ernievd commented Jan 28, 2019

I am just starting to write CloudFormation templates and I am trying to get this to run. First off I notice that I need to replace the '000000000000' in mappings with my user id correct? Next, is this referencing default subnets and security groups? Should I just add a VPC to this template and create my own subnets and security groups? Anything else for a newbie to know to try and get this going? Also, any good resources for me to learn all the basics of cloudformation with? I am also looking into using troposhere and/or terraform after i get a solid foundation with purring together cloudformation templates on there own. Any suggestions on these?

Thanks for any advice!!!

Ernie

@sjparkinson
Copy link
Author

My goodness, sorry @ernievd, I've only just got the notification about your comment!

I am also looking into using troposhere and/or terraform after i get a solid foundation with purring together cloudformation templates on there own. Any suggestions on these?

If you're only working with AWS resources, I'd say stick with CloudFormation. The others shine best only when you are building infrastructure across a number of providers, but have to deal with more yourself such as state file management.

First off I notice that I need to replace the '000000000000' in mappings with my user id correct?

That needs to be replaced with your AWS account ID.

Next, is this referencing default subnets and security groups?

Nope, they also need to be looked up and replaced. The defaults for every AWS account will have different IDs. You may want to define your own security group as part of this template too rather than use the default ones.

Anything else for a newbie to know to try and get this going?

Hard for me to know. But if you did find out some things please do post them, I'd be interested to hear!

Again, sorry it's taken so many months to reply 😬

@garbageman-phil
Copy link

👍

@Venkatachandu0225
Copy link

Hi ,

I am trying to create the infra for aurora posrgres and but still it pointing port 3306 only. Even I am trying change the 'Engine: aurora Postgres' but still poinging to port 3306. kindly let me know any suggestion how mapp with aurora postgres with port 5432.

@Chris-PFM
Copy link

@Venkatachandu0225,

You should explicitly set the Port property to 5432 in your cloud formation template for the cluster resource. When the engine mode is provisioned it will default to 3306 for both MySQL and Postgre:

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment