21 Days of AWS using Terraform – Day 8- Introduction to AWS RDS MySQL using Terraform

Welcome to Day 8 of 21 Days of AWS using Terraform. The topic for today is Introduction to AWS RDS MySQL using Terraform. With that we will be able to finish the last part of our two-tier architecture i.e MySQL DB is private subnets.

What is AWS RDS?

Amazon Relational Database Service (Amazon RDS) is a web service that makes it easier to set up, operate, and scale a relational database in the cloud. It provides cost-efficient, resizable capacity for an industry-standard relational database and manages common database administration tasks.

To create a database, go to Database section(AWS Console) and click on RDS

Click on Get Started Now

Then Select MySQL

On the next screen, choose Dev/Test -MySQL(or depend upon your requirement, as my use case is only for testing purpose)

On the next screen provide all the info

As this is for testing Purpose

  • DB instance class(db.t2.micro)
  • Skip MultiAZ deployment for the time being
  • Gave all the info like(DB instance identifier, Master username, Master password)

Fill all the details in the next screen

Mainly you need to fill

  • Database name(Don’t confuse it DB instance identifier)
  • Backup retention period(0 days, for the time being)

Then click on Launch DB instance

Wait for few mins 5–10min(or depend upon your instance type and size) and check Instance Status(It should be available)

Now lets try to create Read Replica out of this database

Ohho no Create read replica option is not highlighted for me and the reason for that

  • We don’t have a snapshot
  • We don’t have an automated backups

Read replica is always created from a snapshot or the latest backup

Let’s take a snapshot of this database

Once the snapshot creation is done, let’s try to convert this into multi-AZ. Go to Instance actions and click on Modify

These are the things you need to modify

  • Multi-AZ set to Yes
  • Under settings you need to enter the password again
  • I am enabling backup and set it to 1 day
  • On the final screen, you have the option

1: Apply during the next scheduled maintenance window

2: Apply immediately(This will cause a downtime)

To restore a database from the snapshot

and then on the next screen, give DB Instance Identifier or any other setting you want to modify while restoring

To Verify if Multi-AZ is enabled, Click on the particular DB

Now let’s try to create read-replica again, as you can see Create read replica tab is now enabled

The Important thing to remember we can create read replica in any other region

Under the Settings tab, give it a unique name

Now whatever we have done manually here, let’s try to terraformed it

provider "aws" {
  region = "us-west-2"

resource "aws_db_instance" "my-test-sql" {
  instance_class = "${var.db_instance}"
  engine = "mysql"
  engine_version = "5.7"
  multi_az = true
  storage_type = "gp2"
  allocated_storage = 20
  name = "mytestrds"
  username = "admin"
  password = "admin123"
  apply_immediately = "true"
  backup_retention_period = 10
  backup_window = "09:46-10:16"
  db_subnet_group_name = "${aws_db_subnet_group.my-rds-db-subnet.name}"
  vpc_security_group_ids = ["${aws_security_group.my-rds-sg.id}"]

resource "aws_db_subnet_group" "my-rds-db-subnet" {
  name = "my-rds-db-subnet"
  subnet_ids = ["${var.rds_subnet1}","${var.rds_subnet2}"]

resource "aws_security_group" "my-rds-sg" {
  name = "my-rds-sg"
  vpc_id = "${var.vpc_id}"

resource "aws_security_group_rule" "my-rds-sg-rule" {
  from_port = 3306
  protocol = "tcp"
  security_group_id = "${aws_security_group.my-rds-sg.id}"
  to_port = 3306
  type = "ingress"
  cidr_blocks = [""]

resource "aws_security_group_rule" "outbound_rule" {
  from_port = 0
  protocol = "-1"
  security_group_id = "${aws_security_group.my-rds-sg.id}"
  to_port = 0
  type = "egress"
  cidr_blocks = [""]
* allocated_storage: This is the amount in GB
storage_type: Type of storage we want to allocate(options avilable "standard" (magnetic), "gp2" (general purpose SSD), or "io1" (provisioned IOPS SSD)
engine: Database engine(for supported values check https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html) eg: Oracle, Amazon Aurora,Postgres
engine_version: engine version to use
instance_class: instance type for rds instance
name: The name of the database to create when the DB instance is created.
username: Username for the master DB user.
password: Password for the master DB user
db_subnet_group_name: DB instance will be created in the VPC associated with the DB subnet group. If unspecified, will be created in the default VPC
vpc_security_group_ids: List of VPC security groups to associate.
allows_major_version_upgrade: Indicates that major version upgrades are allowed. Changing this parameter does not result in an outage and the change is asynchronously applied as soon as possible.
auto_minor_version_upgrade:Indicates that minor engine upgrades will be applied automatically to the DB instance during the maintenance window. Defaults to true.
backup_retention_period: The days to retain backups for. Must be between 0 and 35. When creating a Read Replica the value must be greater than 0
The daily time range (in UTC) during which automated backups are created if they are enabled. Must not overlap with maintenance_window
The window to perform maintenance in. Syntax: "ddd:hh24:mi-ddd:hh24:mi".
multi_az: Specifies if the RDS instance is multi-AZ
skip_final_snapshot: Determines whether a final DB snapshot is created before the DB instance is deleted. If true is specified, no DBSnapshot is created. If false is specified, a DB snapshot is created before the DB instance is deleted, using the value from final_snapshot_identifier. Default is false

NOTE: Here we are storing mysql password in plan text, I will come up the blog shortly how to store this password in encrypted format.


variable "rds_subnet1" {}
variable "rds_subnet2" {}
variable "db_instance" {}
variable "vpc_id" {}
  • We need to do some changes in order to make this work, by outputting the value of private subnet in terraform vpc module which will act an input to rds aws_db_subnet_group
output "private_subnet1" {
  value = "${element(aws_subnet.private_subnet.*.id, 1 )}"

output "private_subnet2" {
  value = "${element(aws_subnet.private_subnet.*.id, 2 )}"
  • RDS Mysql Module will look like this
module "rds" {
  source      = "./rds"
  db_instance = "db.t2.micro"
  rds_subnet1 = "${module.vpc.private_subnet1}"
  rds_subnet2 = "${module.vpc.private_subnet2}"
  vpc_id      = "${module.vpc.vpc_id}"

GitHub Link


Looking forward for you guys to join this journey

In addition to that, I am going to host 5 meetups whose aim is to build the below architecture.

  • Meetup: https://www.meetup.com/100daysofdevops
  • Day1(Nov 10): Introduction to Terraform https://www.meetup.com/100daysofdevops/events/266192294/
  • Day 2(Nov 16): Building VPC using Terraform
  • Day 3(Nov 17): Creating EC2 Instance inside this VPC using Terraform
  • Day 4(Nov 23): Adding Application Load Balancer and Auto-Scaling to the EC2 instance created on Day 3
  • Day5(Nov 24): Add Backend MySQL Database and CloudWatch Alarm using Terraform

2 Replies to “21 Days of AWS using Terraform – Day 8- Introduction to AWS RDS MySQL using Terraform”

Comments are closed.