--- AWSTemplateFormatVersion: 2010-09-09 Description: SASKV5N RDS # Database stack creation prerequisite: First create a VPC stack - see README for more info Parameters: NetworkStackName: Description: Name of an active CloudFormation stack that contains networking resources Type: String MinLength: 1 MaxLength: 255 AllowedPattern: "^[a-zA-Z][-a-zA-Z0-9]*$" DatabaseUser: Default: startupadmin Type: String Description: Database admin account name MinLength: 5 MaxLength: 16 AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" ConstraintDescription: Name must begin with a letter and contain only alphanumeric characters DatabasePassword: NoEcho: true Type: String Description: Database admin account password MinLength: 6 MaxLength: 41 AllowedPattern: "[a-zA-Z0-9]*" ConstraintDescription: Password must contain only alphanumeric characters DatabaseName: Default: StartupDB Type: String Description: Database name MinLength: 1 MaxLength: 30 AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" ConstraintDescription: Name must begin with a letter and contain only alphanumeric characters DatabaseSize: Default: 5 Type: Number Description: Database storage size in gigabytes (GB) MinValue: 5 ConstraintDescription: Enter a size of at least 5 GB # Default is 500 MB DatabaseAlarmMinFreeSpaceInBytes: Default: 524288000 Type: Number Description: Number of min free space bytes for alarm (if enabled) MinValue: 1 ConstraintDescription: A value of one byte or more # Default is 200 MB DatabaseAlarmSwapUsageInBytes: Default: 209715200 Type: Number Description: Number of swap usage bytes for alarm (if enabled) MinValue: 1 ConstraintDescription: A value of one byte or more DatabaseEngine: Default: postgres Type: String Description: Database engines - PostgreSQL, MariaDB or MySQL ConstraintDescription: Choose an engine from the drop down AllowedValues: - postgres - mariadb - mysql EncryptionAtRest: Default: false Type: String Description: The optional flag for encryption at rest (db.t2.small and above) ConstraintDescription: Only true or false are allowed AllowedValues: - true - false DatabaseInstanceClass: Default: db.t2.micro Type: String Description: "Database instance class, e.g. db.t2.micro (free tier) - Engine support: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.DBInstanceClass.html" ConstraintDescription: DB instance class not supported AllowedValues: - db.t2.micro - db.t2.small - db.t2.medium - db.t2.large - db.t2.xlarge - db.t2.2xlarge - db.m4.large - db.m4.xlarge - db.m4.2xlarge - db.m4.4xlarge - db.m4.10xlarge - db.m4.16xlarge - db.r4.large - db.r4.xlarge - db.r4.2xlarge - db.r4.4xlarge - db.r4.8xlarge - db.r4.16xlarge EnvironmentName: Description: Environment name, either dev or prod Type: String Default: dev AllowedValues: - dev - prod ConstraintDescription: Specify either dev or prod DatabaseAlarmMaxCpuPercent: Description: Database CPU % max for alarm Type: Number Default: 80 MinValue: 1 MaxValue: 99 ConstraintDescription: Must be a percentage between 1-99% DatabaseAlarmReadLatencyMaxSeconds: Description: Read latency max for alarm Type: Number Default: 1 MinValue: 1 DatabaseAlarmWriteLatencyMaxSeconds: Description: Write latency max for alarm Type: Number Default: 1 MinValue: 1 DatabaseAlarmEvaluationPeriods: Description: The number of periods over which data is compared to the specified threshold Type: Number Default: 2 MinValue: 2 DatabaseAlarmEvaluationPeriodSeconds: Description: The time over which the specified statistic is applied. Specify time in seconds, in multiples of 60. Enhanced monitoring must be enabled if less than 500 seconds Type: Number Default: 300 MinValue: 60 ConstraintDescription: Must be at least 60 seconds EnhancedMonitoring: Default: false Type: String Description: The optional flag for enhanced monitoring (additional charges apply - https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html) ConstraintDescription: Only true or false are allowed AllowedValues: - true - false EnableAlarms: Default: false Type: String Description: Set to true to enable (additional charges - https://aws.amazon.com/cloudwatch/pricing/) ConstraintDescription: Only true or false are allowed AllowedValues: - true - false Conditions: IsProd: !Equals [ !Ref EnvironmentName, prod ] AlarmsEnabled: !Equals [ !Ref EnableAlarms, true ] EnhancedMonitoringSupprtedAndEnabled: !And - !Condition AlarmsEnabled - !Equals [ !Ref EnhancedMonitoring, true ] - !Not [ !Equals [ !Ref DatabaseInstanceClass, "db.m1.small" ] ] Resources: EnhancedMonitoringRole: Type: AWS::IAM::Role Condition: EnhancedMonitoringSupprtedAndEnabled Properties: Path: / AssumeRolePolicyDocument: 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 DatabaseAlarmTopic: Type: AWS::SNS::Topic Condition: AlarmsEnabled Properties: DisplayName: Database Alarm Topic DatabaseSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: DBSubnetGroupDescription: Database subnet group SubnetIds: - Fn::ImportValue: !Sub ${NetworkStackName}-PrivateSubnet1ID - Fn::ImportValue: !Sub ${NetworkStackName}-PrivateSubnet2ID Tags: - Key: Name Value: !Ref AWS::StackName Database: Type: AWS::RDS::DBInstance Properties: DBSubnetGroupName: !Ref DatabaseSubnetGroup VPCSecurityGroups: - Fn::ImportValue: !Sub ${NetworkStackName}-DatabaseGroupID Engine: !Ref DatabaseEngine DBName: !Ref DatabaseName MasterUsername: !Ref DatabaseUser MasterUserPassword: !Ref DatabasePassword DBInstanceClass: !Ref DatabaseInstanceClass AllocatedStorage: !Ref DatabaseSize StorageType: gp2 MultiAZ: !If [ IsProd, true, false ] StorageEncrypted: !Ref EncryptionAtRest MonitoringInterval: !If [ EnhancedMonitoringSupprtedAndEnabled, 60, 0 ] MonitoringRoleArn: !If [ EnhancedMonitoringSupprtedAndEnabled, !GetAtt EnhancedMonitoringRole.Arn, !Ref "AWS::NoValue" ] CopyTagsToSnapshot: true Tags: - Key: Name Value: !Ref AWS::StackName DependsOn: DatabaseSubnetGroup DatabaseCpuAlarm: Type: AWS::CloudWatch::Alarm Condition: AlarmsEnabled Properties: AlarmDescription: !Sub DB CPU utilization is over ${DatabaseAlarmMaxCpuPercent}% for ${DatabaseAlarmEvaluationPeriods} period(s) of ${DatabaseAlarmEvaluationPeriodSeconds} seconds TreatMissingData: notBreaching Namespace: AWS/RDS MetricName: CPUUtilization Unit: Percent Statistic: Average EvaluationPeriods: !Ref DatabaseAlarmEvaluationPeriods Period: !Ref DatabaseAlarmEvaluationPeriodSeconds Threshold: !Ref DatabaseAlarmMaxCpuPercent ComparisonOperator: GreaterThanOrEqualToThreshold Dimensions: - Name: DBInstanceIdentifier Value: !Ref Database AlarmActions: - !Ref DatabaseAlarmTopic DependsOn: Database DatabaseFreeStorageSpaceAlarm: Type: AWS::CloudWatch::Alarm Condition: AlarmsEnabled Properties: AlarmDescription: !Sub DB free storage space is less than ${DatabaseAlarmMinFreeSpaceInBytes} for ${DatabaseAlarmEvaluationPeriods} period(s) of ${DatabaseAlarmEvaluationPeriodSeconds} seconds TreatMissingData: notBreaching Namespace: AWS/RDS MetricName: FreeStorageSpace Unit: Bytes Statistic: Average EvaluationPeriods: !Ref DatabaseAlarmEvaluationPeriods Period: !Ref DatabaseAlarmEvaluationPeriodSeconds Threshold: !Ref DatabaseAlarmMinFreeSpaceInBytes ComparisonOperator: LessThanOrEqualToThreshold Dimensions: - Name: DBInstanceIdentifier Value: !Ref Database AlarmActions: - !Ref DatabaseAlarmTopic DependsOn: Database DatabaseSwapUsageAlarm: Type: AWS::CloudWatch::Alarm Condition: AlarmsEnabled Properties: AlarmDescription: !Sub DB swap usage is greater than than ${DatabaseAlarmSwapUsageInBytes} for ${DatabaseAlarmEvaluationPeriods} period(s) of ${DatabaseAlarmEvaluationPeriodSeconds} seconds TreatMissingData: notBreaching Namespace: AWS/RDS MetricName: SwapUsage Unit: Bytes Statistic: Average EvaluationPeriods: !Ref DatabaseAlarmEvaluationPeriods Period: !Ref DatabaseAlarmEvaluationPeriodSeconds Threshold: !Ref DatabaseAlarmSwapUsageInBytes ComparisonOperator: GreaterThanOrEqualToThreshold Dimensions: - Name: DBInstanceIdentifier Value: !Ref Database AlarmActions: - !Ref DatabaseAlarmTopic DependsOn: Database DatabaseReadLatencyAlarm: Type: AWS::CloudWatch::Alarm Condition: AlarmsEnabled Properties: AlarmDescription: !Sub DB read latency is over ${DatabaseAlarmReadLatencyMaxSeconds} for ${DatabaseAlarmEvaluationPeriods} period(s) of ${DatabaseAlarmEvaluationPeriodSeconds} seconds TreatMissingData: notBreaching Namespace: AWS/RDS MetricName: ReadLatency Unit: Seconds Statistic: Average EvaluationPeriods: !Ref DatabaseAlarmEvaluationPeriods Period: !Ref DatabaseAlarmEvaluationPeriodSeconds Threshold: !Ref DatabaseAlarmReadLatencyMaxSeconds ComparisonOperator: GreaterThanOrEqualToThreshold Dimensions: - Name: DBInstanceIdentifier Value: !Ref Database AlarmActions: - !Ref DatabaseAlarmTopic DependsOn: Database DatabaseWriteLatencyAlarm: Type: AWS::CloudWatch::Alarm Condition: AlarmsEnabled Properties: AlarmDescription: !Sub DB write latency is over ${DatabaseAlarmWriteLatencyMaxSeconds} for ${DatabaseAlarmEvaluationPeriods} period(s) of ${DatabaseAlarmEvaluationPeriodSeconds} seconds TreatMissingData: notBreaching Namespace: AWS/RDS MetricName: WriteLatency Unit: Seconds Statistic: Average EvaluationPeriods: !Ref DatabaseAlarmEvaluationPeriods Period: !Ref DatabaseAlarmEvaluationPeriodSeconds Threshold: !Ref DatabaseAlarmWriteLatencyMaxSeconds ComparisonOperator: GreaterThanOrEqualToThreshold Dimensions: - Name: DBInstanceIdentifier Value: !Ref Database AlarmActions: - !Ref DatabaseAlarmTopic DependsOn: Database Outputs: Name: Description: RDS Stack Name Value: !Ref AWS::StackName Export: Name: !Sub ${AWS::StackName}-Name RdsDbId: Description: RDS Database ID Value: !Ref Database Export: Name: !Sub ${AWS::StackName}-DatabaseID RdsDbURL: Description: RDS Database URL Value: !GetAtt Database.Endpoint.Address Export: Name: !Sub ${AWS::StackName}-DatabaseURL DbUser: Description: RDS Database admin account user Value: !Ref DatabaseUser Export: Name: !Sub ${AWS::StackName}-DatabaseUser DbPassword: Description: RDS Database admin account password Value: !Ref DatabasePassword Export: Name: !Sub ${AWS::StackName}-DatabasePassword DatabaseAlarmTopicArn: Description: Database Alarm Topic ARN Condition: AlarmsEnabled Value: !Ref DatabaseAlarmTopic Export: Name: !Sub ${AWS::StackName}-DatabaseAlarmTopicArn DatabaseAlarmTopicName: Description: Database Alarm Topic Name Condition: AlarmsEnabled Value: !GetAtt DatabaseAlarmTopic.TopicName Export: Name: !Sub ${AWS::StackName}-DatabaseAlarmTopicName