Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
408 lines (407 sloc) 15.5 KB
---
# Copyright 2018 widdix GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
AWSTemplateFormatVersion: '2010-09-09'
Description: 'State: RDS Aurora, a cloudonaut.io template, sponsored by https://github.com/ngault'
Metadata:
'AWS::CloudFormation::Interface':
ParameterGroups:
- Label:
default: 'Parent Stacks'
Parameters:
- ParentVPCStack
- ParentClientStack
- ParentKmsKeyStack
- ParentZoneStack
- ParentSSHBastionStack
- ParentAlertStack
- Label:
default: 'RDS Parameters'
Parameters:
- Engine
- DBSnapshotIdentifier
- DBInstanceClass
- DBName
- DBBackupRetentionPeriod
- DBMasterUsername
- DBMasterUserPassword
- SubDomainNameWithDot
- ReadSubDomainNameWithDot
- PreferredBackupWindow
- PreferredMaintenanceWindow
Parameters:
ParentVPCStack:
Description: 'Stack name of parent VPC stack based on vpc/vpc-*azs.yaml template.'
Type: String
ParentClientStack:
Description: 'Stack name of parent client stack based on state/client-sg.yaml template.'
Type: String
ParentKmsKeyStack:
Description: 'Optional Stack name of parent KMS key stack based on security/kms-key.yaml template (ignored when DBSnapshotIdentifier is set, value used from snapshot).'
Type: String
Default: ''
ParentZoneStack:
Description: 'Optional stack name of parent zone stack based on vpc/vpc-zone-*.yaml template.'
Type: String
Default: ''
ParentSSHBastionStack:
Description: 'Optional but recommended stack name of parent SSH bastion host/instance stack based on vpc/vpc-*-bastion.yaml template.'
Type: String
Default: ''
ParentAlertStack:
Description: 'Optional but recommended stack name of parent alert stack based on operations/alert.yaml template.'
Type: String
Default: ''
Engine:
Description: 'The name of the database engine that you want to use for this DB cluster.'
Type: String
AllowedValues:
- aurora # MySQL 5.6-compatible Aurora
- 'aurora-mysql' # MySQL 5.7-compatible Aurora
- 'aurora-postgresql'
Default: aurora
DBSnapshotIdentifier:
Description: 'Optional identifier for the DB cluster snapshot from which you want to restore (leave blank to create an empty cluster).'
Type: String
Default: ''
DBInstanceClass:
Description: 'The instance type of database server (see https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Concepts.DBInstanceClass.html).'
Type: String
Default: 'db.t2.small'
DBName:
Description: 'Name of the database (ignored when DBSnapshotIdentifier is set, value used from snapshot).'
Type: String
Default: ''
DBBackupRetentionPeriod:
Description: 'The number of days to keep snapshots of the cluster.'
Type: Number
MinValue: 1
MaxValue: 35
Default: 30
DBMasterUsername:
Description: 'The master user name for the DB instance (ignored when DBSnapshotIdentifier is set, value used from snapshot).'
Type: 'String'
Default: master
DBMasterUserPassword:
Description: 'The master password for the DB instance (ignored when DBSnapshotIdentifier is set, value used from snapshot).'
Type: String
NoEcho: true
Default: ''
SubDomainNameWithDot:
Description: 'Name that is used to create the DNS entry with trailing dot, e.g. §{SubDomainNameWithDot}§{HostedZoneName}. Leave blank for naked (or apex and bare) domain. Requires ParentZoneStack parameter!'
Type: String
Default: 'aurora.'
ReadSubDomainNameWithDot:
Description: 'Name that is used to create the read DNS entry with trailing dot, e.g. §{SubDomainNameWithDot}§{HostedZoneName}. Leave blank for naked (or apex and bare) domain. Requires ParentZoneStack parameter!'
Type: String
Default: 'read-aurora.'
PreferredBackupWindow:
Description: 'The daily time range in UTC during which you want to create automated backups.'
Type: String
Default: '09:54-10:24'
PreferredMaintenanceWindow:
Description: The weekly time range (in UTC) during which system maintenance can occur.
Type: String
Default: 'sat:07:00-sat:07:30'
Mappings:
EngineMap:
aurora:
EngineVersion: '5.6.10a'
Port: 3306
ClusterParameterGroupFamily: 'aurora5.6'
ParameterGroupFamily: 'aurora5.6'
'aurora-mysql':
EngineVersion: '5.7.12'
Port: 3306
ClusterParameterGroupFamily: 'aurora-mysql5.7'
ParameterGroupFamily: 'aurora-mysql5.7'
'aurora-postgresql':
EngineVersion: '9.6.3'
Port: 5432
ClusterParameterGroupFamily: 'aurora-postgresql9.6'
ParameterGroupFamily: 'aurora-postgresql9.6'
Conditions:
HasKmsKey: !Not [!Equals [!Ref ParentKmsKeyStack, '']]
HasZone: !Not [!Equals [!Ref ParentZoneStack, '']]
HasSSHBastionSecurityGroup: !Not [!Equals [!Ref ParentSSHBastionStack, '']]
HasAlertTopic: !Not [!Equals [!Ref ParentAlertStack, '']]
HasDBSnapshotIdentifier: !Not [!Equals [!Ref DBSnapshotIdentifier, '']]
HasKmsKeyAndNotDBSnapshotIdentifier: !And [!Condition HasKmsKey, !Not [!Condition HasDBSnapshotIdentifier]]
HasEngineMySQL: !Or [!Equals [!Ref Engine, 'aurora'], !Equals [!Ref Engine, 'aurora-mysql']]
Resources:
RecordSet:
Condition: HasZone
Type: 'AWS::Route53::RecordSet'
Properties:
HostedZoneId: {'Fn::ImportValue': !Sub '${ParentZoneStack}-HostedZoneId'}
Name: !Sub
- '${SubDomainNameWithDot}${HostedZoneName}'
- SubDomainNameWithDot: !Ref SubDomainNameWithDot
HostedZoneName: {'Fn::ImportValue': !Sub '${ParentZoneStack}-HostedZoneName'}
ResourceRecords:
- !GetAtt 'DBCluster.Endpoint.Address'
TTL: '60'
Type: CNAME
ReadRecordSet:
Condition: HasZone
Type: 'AWS::Route53::RecordSet'
Properties:
HostedZoneId: {'Fn::ImportValue': !Sub '${ParentZoneStack}-HostedZoneId'}
Name: !Sub
- '${ReadSubDomainNameWithDot}${HostedZoneName}'
- ReadSubDomainNameWithDot: !Ref ReadSubDomainNameWithDot
HostedZoneName: {'Fn::ImportValue': !Sub '${ParentZoneStack}-HostedZoneName'}
ResourceRecords:
- !GetAtt 'DBCluster.ReadEndpoint.Address'
TTL: '60'
Type: CNAME
ClusterSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: !Ref 'AWS::StackName'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: !FindInMap [EngineMap, !Ref Engine, Port]
ToPort: !FindInMap [EngineMap, !Ref Engine, Port]
SourceSecurityGroupId: {'Fn::ImportValue': !Sub '${ParentClientStack}-ClientSecurityGroup'}
VpcId: {'Fn::ImportValue': !Sub '${ParentVPCStack}-VPC'}
ClusterSecurityGroupInSSHBastion:
Type: 'AWS::EC2::SecurityGroupIngress'
Condition: HasSSHBastionSecurityGroup
Properties:
GroupId: !Ref ClusterSecurityGroup
IpProtocol: tcp
FromPort: !FindInMap [EngineMap, !Ref Engine, Port]
ToPort: !FindInMap [EngineMap, !Ref Engine, Port]
SourceSecurityGroupId: {'Fn::ImportValue': !Sub '${ParentSSHBastionStack}-SecurityGroup'}
DBSubnetGroup:
Type: 'AWS::RDS::DBSubnetGroup'
Properties:
DBSubnetGroupDescription: !Ref 'AWS::StackName'
SubnetIds: !Split [',', {'Fn::ImportValue': !Sub '${ParentVPCStack}-SubnetsPrivate'}]
DBClusterParameterGroup:
Type: 'AWS::RDS::DBClusterParameterGroup'
Properties:
Description: !Ref 'AWS::StackName'
Family: !FindInMap [EngineMap, !Ref Engine, ClusterParameterGroupFamily]
Parameters: !If
- HasEngineMySQL
- character_set_client: utf8
character_set_connection: utf8
character_set_database: utf8
character_set_filesystem: utf8
character_set_results: utf8
character_set_server: utf8
collation_connection: utf8_general_ci
collation_server: utf8_general_ci
- client_encoding: 'UTF8'
DBCluster:
DeletionPolicy: Snapshot # default
UpdateReplacePolicy: Snapshot
Type: 'AWS::RDS::DBCluster'
Properties:
BackupRetentionPeriod: !Ref DBBackupRetentionPeriod
DatabaseName: !If [HasDBSnapshotIdentifier, !Ref 'AWS::NoValue', !Ref DBName]
DBClusterParameterGroupName: !Ref DBClusterParameterGroup
DBSubnetGroupName: !Ref DBSubnetGroup
Engine: !Ref Engine
EngineMode: provisioned
EngineVersion: !FindInMap [EngineMap, !Ref Engine, EngineVersion]
KmsKeyId: !If [HasKmsKeyAndNotDBSnapshotIdentifier, {'Fn::ImportValue': !Sub '${ParentKmsKeyStack}-KeyId'}, !Ref 'AWS::NoValue']
MasterUsername: !If [HasDBSnapshotIdentifier, !Ref 'AWS::NoValue', !Ref DBMasterUsername]
MasterUserPassword: !If [HasDBSnapshotIdentifier, !Ref 'AWS::NoValue', !Ref DBMasterUserPassword]
Port: !FindInMap [EngineMap, !Ref Engine, Port]
PreferredBackupWindow: !Ref PreferredBackupWindow
PreferredMaintenanceWindow: !Ref PreferredMaintenanceWindow
SnapshotIdentifier: !If [HasDBSnapshotIdentifier, !Ref DBSnapshotIdentifier, !Ref 'AWS::NoValue']
StorageEncrypted: !If [HasDBSnapshotIdentifier, !Ref 'AWS::NoValue', !If [HasKmsKey, true, false]]
VpcSecurityGroupIds:
- !Ref ClusterSecurityGroup
DBParameterGroup:
Type: 'AWS::RDS::DBParameterGroup'
Properties:
Description: !Ref 'AWS::StackName'
Family: !FindInMap [EngineMap, !Ref Engine, ParameterGroupFamily]
DBInstanceA:
Type: 'AWS::RDS::DBInstance'
Properties:
AllowMajorVersionUpgrade: false
AutoMinorVersionUpgrade: true
CopyTagsToSnapshot: true
DBClusterIdentifier: !Ref DBCluster
DBInstanceClass: !Ref DBInstanceClass
DBParameterGroupName: !Ref DBParameterGroup
DBSubnetGroupName: !Ref DBSubnetGroup
Engine: !Ref Engine
DBInstanceB:
Type: 'AWS::RDS::DBInstance'
Properties:
AllowMajorVersionUpgrade: false
AutoMinorVersionUpgrade: true
CopyTagsToSnapshot: true
DBClusterIdentifier: !Ref DBCluster
DBInstanceClass: !Ref DBInstanceClass
DBParameterGroupName: !Ref DBParameterGroup
DBSubnetGroupName: !Ref DBSubnetGroup
Engine: !Ref Engine
DatabaseACPUUtilizationTooHighAlarm:
Condition: HasAlertTopic
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
AlarmDescription: 'Average database CPU utilization over last 10 minutes too high.'
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref DBInstanceA
EvaluationPeriods: 1
MetricName: CPUUtilization
Namespace: 'AWS/RDS'
OKActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
Period: 600
Statistic: Average
Threshold: 80
DatabaseBCPUUtilizationTooHighAlarm:
Condition: HasAlertTopic
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
AlarmDescription: 'Average database CPU utilization over last 10 minutes too high.'
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref DBInstanceB
EvaluationPeriods: 1
MetricName: CPUUtilization
Namespace: 'AWS/RDS'
OKActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
Period: 600
Statistic: Average
Threshold: 80
DatabaseACPUCreditBalanceTooLowAlarm:
Condition: HasAlertTopic
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
AlarmDescription: 'Average database CPU credit balance over last 10 minutes too low, expect a significant performance drop soon.'
ComparisonOperator: LessThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref DBInstanceA
EvaluationPeriods: 1
MetricName: CPUCreditBalance
Namespace: 'AWS/RDS'
OKActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
Period: 600
Statistic: Average
Threshold: 20
DatabaseBCPUCreditBalanceTooLowAlarm:
Condition: HasAlertTopic
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
AlarmDescription: 'Average database CPU credit balance over last 10 minutes too low, expect a significant performance drop soon.'
ComparisonOperator: LessThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref DBInstanceB
EvaluationPeriods: 1
MetricName: CPUCreditBalance
Namespace: 'AWS/RDS'
OKActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
Period: 600
Statistic: Average
Threshold: 20
DatabaseAFreeableMemoryTooLowAlarm:
Condition: HasAlertTopic
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
AlarmDescription: 'Average database freeable memory over last 10 minutes too low, performance may suffer.'
ComparisonOperator: LessThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref DBInstanceA
EvaluationPeriods: 1
MetricName: FreeableMemory
Namespace: 'AWS/RDS'
OKActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
Period: 600
Statistic: Average
Threshold: 64000000 # 64 Megabyte in Byte
DatabaseBFreeableMemoryTooLowAlarm:
Condition: HasAlertTopic
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
AlarmDescription: 'Average database freeable memory over last 10 minutes too low, performance may suffer.'
ComparisonOperator: LessThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref DBInstanceB
EvaluationPeriods: 1
MetricName: FreeableMemory
Namespace: 'AWS/RDS'
OKActions:
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
Period: 600
Statistic: Average
Threshold: 64000000 # 64 Megabyte in Byte
DatabaseClusterEventSubscription:
Condition: HasAlertTopic
Type: 'AWS::RDS::EventSubscription'
Properties:
EventCategories:
- failover
- failure
- notification
SnsTopicArn: {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}
SourceIds: [!Ref DBCluster]
SourceType: 'db-cluster'
Outputs:
TemplateID:
Description: 'cloudonaut.io template id.'
Value: 'state/rds-aurora'
TemplateVersion:
Description: 'cloudonaut.io template version.'
Value: '__VERSION__'
StackName:
Description: 'Stack name.'
Value: !Sub '${AWS::StackName}'
ClusterName:
Description: 'The name of the cluster.'
Value: !Ref DBCluster
Export:
Name: !Sub '${AWS::StackName}-ClusterName'
DNSName:
Description: 'The connection endpoint for the DB cluster.'
Value: !GetAtt 'DBCluster.Endpoint.Address'
Export:
Name: !Sub '${AWS::StackName}-DNSName'
ReadDNSName:
Description: 'The reader endpoint for the DB cluster.'
Value: !GetAtt 'DBCluster.ReadEndpoint.Address'
Export:
Name: !Sub '${AWS::StackName}-ReadDNSName'
You can’t perform that action at this time.