The AWS Relational Database Service (RDS AWS) is a web service that makes it easier to set up & operate a relational database in the cloud. To understand more about RDS search for “How to setup an RDS MySql (Relation Database MySql ) instance on AWS” article. 

AWS CloudFormation allows us to use programming languages (yaml/json) or a simple text file to model and provision all the resources needed for our applications. This gives us a single source of truth for our AWS resources.

In this article, we will see the steps to create an RDS MySql Instance using Cloudformation Stack.

Pre-requisites

  1. AWS Account (Create if you don’t have one). 
  2. Basic understanding of Cloudformation Stack.
  3. Basic understanding of RDS MySql (Relation Database MySql ) instance on AWS.

What will we do?

  1. Login to AWS.
  2. Create an RDS MySql Instance using Cloudformation Stack

Login to AWS

  1. Click here to go to AWS Login Page.

When we hit the above link, we will see a web page as follows where we are required to login using our login details.

<img alt="Log into AWS" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_11.55_.16_AM_.png61890f4b90c77.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

Once we login into AWS successfully, we will see the main console with all the services listed.

<img alt="AWS Management Console" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_11.56_.52_AM_.png61890f4be4fa7.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

Create an RDS MySql Instance using Cloudformation.

Before we create an instance using Cloudformation Stack, copy the code from the following block or download the template from here and save it on your local machine. 

---
AWSTemplateFormatVersion: '2010-09-09'
Description: This stack creates an RDS MySql 5.7 Instance
Parameters:
  Owner:
    Description: Enter the Name of the owner for this Stack.
    Type: String
    Default: Name
  VPC:
    Description: Select VPC form the available VPCs in your account.
    Type: AWS::EC2::VPC::Id
  PrivateSubnet1:
    Description: Select Private Subnet 1.
    Type: AWS::EC2::Subnet::Id
  PrivateSubnet2:
    Description: Select Private Subnet 2.
    Type: AWS::EC2::Subnet::Id
  PrivateSubnet3:
    Description: Select Private Subnet 3.
    Type: AWS::EC2::Subnet::Id
  MasterUsername:
    Description: Database administration name.
    Type: String
    Default: rdsroot
  MasterUserPassword:
    NoEcho: 'true'
    Description: Database administration password.
    Type: String
    MinLength: '8'
    AllowedPattern: "[a-zA-Z0-9!?]*"
    ConstraintDescription: Must only contain upper and lowercase letters and numbers
  BackupRetentionPeriod:
    Description: Enter Backup Retention Period in Days.
    Type: Number
    Default: '5'
  MultiAvailabilityZone:
    Description: Do you want to Enable Multi Availability Zones?
    Type: String
    Default: 'true'
    AllowedValues:
    - 'true'
    - 'false'
  TcpPort:
    Description: Enter RDS Listening TCP Port number.
    Type: Number
    Default: '3306'
  PreferredBackupWindow:
    Description: Enter Preferred Backup Window Time.
    Type: String
    Default: 15:00-17:00
  PreferredMaintenanceWindow:
    Description: Enter Preferred Maintenance Window Time.
    Type: String
    Default: Sun:18:00-Sun:22:00
  AllocatedStorage:
    Default: '15'
    Description: Enter the size of the database (Gb)
    Type: Number
    MinValue: '5'
    MaxValue: '6144'
    ConstraintDescription: Must be between 5-6144
  SnapshotOnDelete:
    Description: Do you want to create a Snapshot on instance delete?
    Type: String
    Default: 'true'
    AllowedValues:
    - 'true'
    - 'false'
  AutoMinorVersionUpgrade:
    Description: Do you want to allow automatic minor version upgrade?
    Type: String
    Default: 'true'
    AllowedValues:
    - 'true'
    - 'false'
  InstanceType:
    Description: Select Instance Type.
    Type: String
    Default: db.t2.micro
    ConstraintDescription: Must be a valid EC2 instance type.
Mappings:
  Settings:
    MySQL:
      Engine: MySQL
      Version: '5.7'
Conditions:
  ConfigureSnapshotOnDelete:
    Fn::Equals:
    - Ref: SnapshotOnDelete
    - 'true'

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: Ownership
      Parameters:
      - Owner
    - Label:
        default: Network Configuration
      Parameters:
      - VPC
      - PrivateSubnet1
      - PrivateSubnet2
      - PrivateSubnet3
    - Label:
        default: RDS Configuration
      Parameters:
      - InstanceType
      - MasterUsername
      - MasterUserPassword
      - BackupRetentionPeriod
      - PreferredBackupWindow
      - PreferredMaintenanceWindow
      - SnapshotOnDelete
      - AllocatedStorage
      - AutoMinorVersionUpgrade
      - TcpPort
      - MultiAvailabilityZone
    ParameterLabels:
      Owner:
        default: Team or Individual Owner
      InstanceType:
        default: Instance Type
      PrivateSubnet1:
        default: Private Subnet 1
      PrivateSubnet2:
        default: Private Subnet 2
      PrivateSubnet3:
        default: Private Subnet 3
      MasterUsername:
        default: Master Username
      MasterUserPassword:
        default: Master User Password
      BackupRetentionPeriod:
        default: Backup Retention Period
      PreferredBackupWindow:
        default: Preferred Backup Window
      PreferredMaintenanceWindow:
        default: Preferred Maintenance Window
      AllocatedStorage:
        default: Allocated Storage
      AutoMinorVersionUpgrade:
        default: Auto Minor Version Upgrade
      TcpPort:
        default: TCP Port
      MultiAvailabilityZone:
        default: Multi Availability Zone?
      SnapshotOnDelete:
        default: Snapshot On Delete?

Resources:
  RDSAccessSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Instance to RDS Access
      VpcId:
        Ref: VPC
      Tags:
      - Key: Name
        Value:
          Fn::Join:
          - ''
          - - Ref: AWS::StackName
            - "-rds"
      - Key: Owner
        Value:
          Ref: Owner
  AccessSecurityGroupIngress:
    Type: AWS::EC2::SecurityGroupIngress
    DependsOn: RDSAccessSecurityGroup
    Properties:
      GroupId:
        Ref: RDSAccessSecurityGroup
      IpProtocol: tcp
      FromPort:
        Ref: TcpPort
      ToPort:
        Ref: TcpPort
      SourceSecurityGroupId:
        Ref: RDSAccessSecurityGroup
  DbSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupDescription:
        Fn::Join:
        - ''
        - - 'RDS Subnet Group for '
          - Ref: AWS::StackName
      SubnetIds:
      - Ref: PrivateSubnet1
      - Ref: PrivateSubnet2
      - Ref: PrivateSubnet3
      Tags:
      - Key: Name
        Value:
          Ref: AWS::StackName
      - Key: Owner
        Value:
          Ref: Owner
  DbInstance:
    Type: AWS::RDS::DBInstance
    DeletionPolicy: Snapshot
    DependsOn:
    - DbSubnetGroup
    - RDSAccessSecurityGroup
    Properties:
      AllocatedStorage:
        Ref: AllocatedStorage
      AllowMajorVersionUpgrade: 'false'
      AutoMinorVersionUpgrade:
        Ref: AutoMinorVersionUpgrade
      BackupRetentionPeriod:
        Ref: BackupRetentionPeriod
      DBInstanceClass:
        Ref: InstanceType
      DBInstanceIdentifier:
        Ref: AWS::StackName
      DBSubnetGroupName:
        Ref: DbSubnetGroup
      Engine:
        Fn::FindInMap:
        - Settings
        - MySQL
        - Engine
      EngineVersion:
        Fn::FindInMap:
        - Settings
        - MySQL
        - Version
      MasterUsername:
        Ref: MasterUsername
      MasterUserPassword:
        Ref: MasterUserPassword
      MultiAZ:
        Ref: MultiAvailabilityZone
      Port:
        Ref: TcpPort
      PreferredBackupWindow:
        Ref: PreferredBackupWindow
      PreferredMaintenanceWindow:
        Ref: PreferredMaintenanceWindow
      PubliclyAccessible: 'false'
      StorageEncrypted: 'false'
      StorageType: gp2
      VPCSecurityGroups:
      - Ref: RDSAccessSecurityGroup
      Tags:
      - Key: Name
        Value:
          Ref: AWS::StackName
      - Key: Owner
        Value:
          Ref: Owner

Outputs:
  Owner:
    Description: Team or Individual that Owns this Formation.
    Value:
      Ref: Owner
  VPC:
    Description: VPC Used
    Value:
      Ref: VPC
  RDSHostname:
    Description: RDS Hostname
    Value:
      Fn::GetAtt:
      - DbInstance
      - Endpoint.Address
  RDSPort:
    Description: RDS Port
    Value:
      Fn::GetAtt:
      - DbInstance
      - Endpoint.Port
  DbSubnetGroup:
    Description: DB Subnet Group Created.
    Value:
      Ref: DbSubnetGroup
  RDSAccessSecurityGroup:
    Description: RDS Access Security Group Created.
    Value:
      Ref: RDSAccessSecurityGroup
  PrivateSubnet1:
    Description: Private Subnet 1 Deployment
    Value:
      Ref: PrivateSubnet1
  PrivateSubnet2:
    Description: Private Subnet 2 Deployment
    Value:
      Ref: PrivateSubnet2
  PrivateSubnet3:
    Description: Private Subnet 3 Deployment
    Value:
      Ref: PrivateSubnet3
  BackupRetentionPeriod:
    Description: Backup Retention Period in Days
    Value:
      Ref: BackupRetentionPeriod
  MultiAvailabilityZone:
    Description: Enable Multi Availability Zones?
    Value:
      Ref: MultiAvailabilityZone
  SnapshotOnDelete:
    Description: Create Snapshot on Delete?
    Value:
      Ref: SnapshotOnDelete
  PreferredBackupWindow:
    Description: Preferred Backup Window
    Value:
      Ref: PreferredBackupWindow
  PreferredMaintenanceWindow:
    Description: Preferred Maintenance Window
    Value:
      Ref: PreferredMaintenanceWindow
  AllocatedStorage:
    Description: Allocated Storage in GB
    Value:
      Ref: AllocatedStorage

Once you have the template with you on your local machine, go to the AWS console and click on “Services” from the top menu bar and search for “Cloudformation”.

<img alt="Cloudformation" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_11.56_.58_AM_.png61890f4c61348.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

You will see the main cloudformation dashboard as follows. Click on “Create Stack” button to create a stack to create an RDS MySql Instance.

<img alt="Stacks" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_11.57_.06_AM_.png61890f4caa46c.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

Click on “Upload a template file” radio button and select the template that you have saved from your local machine and click on “Next” button.

<img alt="Create Cloudformation Stack" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_11.57_.25_AM_.png61890f4cd80f8.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

Specify a name of your choice to the stack and fill in the required details and click on “Next” to proceed further.

<img alt="Specify Stack Details" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_11.57_.49_AM_.png61890f4d2c54b.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

<img alt="Master user password" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_11.58_.29_AM_.png61890f4d88092.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

You can provide the tags to Cloudformation Stack which can be applied to the RDS MySql Instance which will get created by the stack. Click on “Next” to proceed.

<img alt="Tags" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_11.58_.43_AM_.png61890f4dce390.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

Scroll down and click on “Create stack” to create the stack.

<img alt="Create Stack" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_11.58_.51_AM_.png61890f4e0a940.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

The creation will take some time. You can see the action being taken under events.

<img alt="RDS MySQL" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_12.02_.41_PM_.png61890f4e4aad1.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

To see the status of the RDS MySql instance being created, click on “Services” and search for “RDS”.

<img alt="RDS" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_12.03_.50_PM_.png61890f4eaf117.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

On the main dashboard, click on “DB Instances”.

<img alt="Create database" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_12.04_.19_PM_.png61890f4ee23b0.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

Here, you can see that the status of the instance is “Modifying”. This will take some time to get created and be ready for use.

<img alt="RDS Database list" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_12.04_.37_PM_.png61890f4f2bd69.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

In the Cloudformation Stack events, you can see that after some time, once the RDS MySql Instance gets created, the status is “CREATE_COMPLETE”

<img alt="RDS action log" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_12.20_.14_PM_1.png61890f4f618fb.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

In the RDS Console, now you can see that the status is “Available”.

<img alt="MySQL Database on AWS" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_12.20_.19_PM_1.png61890f4f9a8b1.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

To see more details about the RDS MySql Instance, click on the RDS MySql Instance –> Connectivity & Security.

To connect to the RDS MySql Instance, you can use the Endpoint provided by the instance.

<img alt="Database details" data-ezsrc="https://kirelos.com/wp-content/uploads/2021/11/echo/Screenshot_2020-03-22_at_12.21_.02_PM_1.png61890f4fbb355.jpg" ezimgfmt="rs rscb5 src ng ngcb5" height="469" loading="lazy" src="data:image/svg xml,” width=”750″>

Once the instance is no more needed, delete the Cloudformation Stack from the Cloudformation Main Dashboard to save on the cost.

Conclusion

In this article, we saw the steps to create an RDS MySql instance using Cloudformation Stack.