How to do it...

Create a new CloudFormation template. We're going to add a total of 12 parameters to it:

  1. The first three parameters will contain the values we mentioned in the Getting ready section:
Parameters:
VPCId:
Type: AWS::EC2::VPC::Id
Description: VPC where DB will launch
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>
Description: Subnets where the DB will launch (pick at least 2)
SecurityGroupAllowCidr:
Type: String
Description: Allow this CIDR block to access the DB
Default: "172.30.0.0/16"
  1. We're also going to add the database credentials as parameters. This is better than storing credentials in our infrastructure source code, but you should also investigate AWS Secret Manager and Parameter Store for even more secure options. Note that the password contains the NoEcho parameter set to true. This stops CloudFormation from outputting the password wherever the CloudFormation stack details are displayed:
  DBUsername: 
Type: String
Description: Username to access the database
MinLength: 1
AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*"
ConstraintDescription: must start with a letter, must
be alphanumeric
DBPassword:
Type: String
Description: Password to access the database
MinLength: 1
AllowedPattern: "[a-zA-Z0-9]*"
NoEcho: true
ConstraintDescription: must be alphanumeric
  1. The next block of parameters pertains to cost and performance. They should be mostly self-explanatory. Refer to the AWS documentation on database instance types should you wish to change the instance class for this example. We're supplying a default value of 10 GB for the storage size and choosing a magnetic (standard) volume for the storage type. gp2 offers better performance, but it costs a little more:
  DBInstanceClass: 
Type: String
Description: The instance type to use for this database
Default: db.t2.micro
DBStorageAmount:
Type: Number
Description: Amount of storage to allocate (in GB)
Default: 10
DBStorageType:
Type: String
Description: Type of storage volume to use
(standard [magnetic] or gp2)
Default: standard
AllowedValues:
- standard
- gp2

  1. We need to set some additional parameters for our database. These are the MySQL engine version and port. Refer to the AWS documentation for a list of all of the available versions. We are setting a default value for this parameter as the latest version of MySQL at the time of writing:
  DBEngineVersion: 
Type: String
Description: DB engine version
Default: "5.7.26"
DBPort:
Type: Number
Description: Port number to allocate
Default: 3306
MinValue: 1150
MaxValue: 65535
  1. Finally, we are going to define some parameters relating to backup and availability. We want our database to run in multi-AZ mode; we set this to true by default. We also set a backup retention period of 1 day by default; you might want to choose a period larger than this. If you set this value to 0, backups will be disabled (not recommended!):
  DBMultiAZ: 
Type: String
Description: Should this DB be deployed in Multi-AZ configuration?
Default: true
AllowedValues:
- true
- false
DBBackupRetentionPeriod:
Type: Number
Description: How many days to keep backups (0 disables backups)
Default: 1
MinValue: 0
MaxValue: 35
  1. We're done with the parameters for this template; we can now go ahead and start defining our Resources parameters. First of all, we want a security group for our DB to reside in. This security group allows inbound access to the database port from the CIDR range we've defined:
Resources:
ExampleDBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Example security group for inbound access to DB
SecurityGroupIngress:
- IpProtocol: tcp
CidrIp: !Ref SecurityGroupAllowCidr
FromPort: !Ref DBPort
ToPort: !Ref DBPort
VpcId: !Ref VPCId
  1. Next, we need to define a DBSubnetGroup resource. This resource is used to declare which subnet(s) our DB will reside in. We define two subnets for this resource so that the primary and standby servers will reside in separate AVs:
  ExampleDBSubnetGroup: 
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Example subnet group for example DB
SubnetIds:
- Fn::Select: [ 0, Ref: SubnetIds ]
- Fn::Select: [ 1, Ref: SubnetIds ]
  1. Finally, we define our RDS instance resource. We specify it as being a MySQL database and the rest of the properties are made up of the parameters and resources that we've defined previously. Lots of !Ref is required here:
  ExampleDBInstance: 
Type: AWS::RDS::DBInstance
Properties:
AllocatedStorage: !Ref DBStorageAmount
BackupRetentionPeriod: !Ref DBBackupRetentionPeriod
DBInstanceClass: !Ref DBInstanceClass
DBSubnetGroupName: !Ref ExampleDBSubnetGroup
Engine: mysql
EngineVersion: !Ref DBEngineVersion
MasterUsername: !Ref DBUsername
MasterUserPassword: !Ref DBPassword
MultiAZ: !Ref DBMultiAZ
StorageType: !Ref DBStorageType
VPCSecurityGroups:
- !GetAtt ExampleDBSecurityGroup.GroupId
  1. For good measure, we can add an output to this template that will return the hostname for this RDS database:
Outputs: 
ExampleDbHostname:
Value: !GetAtt ExampleDBInstance.Endpoint.Address

  1. You can provision the database via the CloudFormation web console or use a CLI command like so:
 aws cloudformation create-stack 
--stack-name rds1
--template-body
file://06-create-database-with-automatic-failover.yaml
--parameters
ParameterKey=DBUsername,ParameterValue=<username>
ParameterKey=DBPassword,ParameterValue=<password>
ParameterKey=SubnetIds,"ParameterValue='<subnet-id-a>,
<subnet-id-b>'"
ParameterKey=VPCId,ParameterValue=<vpc-id>

Be sure to delete the stack if you have no further use for it, to avoid any future charges.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset