Terraform Mastery: Adding Databases to RDS Instances effortlessly

Dhanesh kumar
Railsfactory
Published in
3 min readMay 13, 2024

Introduction:

In this blog post, I will demonstrate a smooth and reliable process for scaling existing MySQL and PostgreSQL databases in AWS RDS using Terraform. Efficiently scaling databases while ensuring data integrity is crucial for modern businesses, and leveraging Terraform’s infrastructure as code capabilities enables us to achieve this seamlessly within the AWS environment. Let’s explore the step-by-step process of scaling databases with confidence and ease.

Overview:
This Terraform configuration extends an AWS RDS setup by adding additional databases for both MySQL and PostgreSQL engines. It ensures that the scaling process is smooth and does not disrupt ongoing database operations.

Steps:
Preparation:
Ensure the Terraform version is 1.0 or higher. Verify necessary providers are defined in providers.tf file.

terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "> 4.0"
}

random = {
source = "hashicorp/random"
version = "~> 3.0"
}

mysql = {
source = "TakatoHano/mysql"
}

postgresql = {
source = "cyrilgdn/postgresql"
version = "1.22.0"
}
}
}

For MySQL Database:

  • Define a random password resource for MySQL using random_password module in main.tf file.
  • I have used random_password to generate the MySQL Master password for login.
  • Configure additional MySQL database resources (mysql_database) as required, ensuring unique names as shown below.
resource "random_password" "MysqlMasterPassword" {
length = 16
special = true
override_special = "$%!)1"
}

resource "aws_db_instance" "MySQLDatabaseInstance" {
identifier = "rds-mysql-poc"
engine = "mysql"
engine_version = "8.0"
instance_class = "db.t3.micro"
allocated_storage = 30
storage_type = "gp3"
db_name = "rdspoc"
username = "rdspocadmin"
password = random_password.MysqlMasterPassword.result
port = 3306
parameter_group_name = "default.mysql8.0"
multi_az = false
auto_minor_version_upgrade = true
backup_window = "03:00-06:00"
backup_retention_period = 7
maintenance_window = "Sun:00:00-Sun:03:00"
deletion_protection = false
final_snapshot_identifier = "rds-poc-final-snapshot"
apply_immediately = true
db_subnet_group_name = "default-vpc-ID"
vpc_security_group_ids = ["sg-ID"]
publicly_accessible = true
}

provider "mysql" {
endpoint = "${aws_db_instance.MySQLDatabaseInstance.endpoint}"
username = "${aws_db_instance.MySQLDatabaseInstance.username}"
password = "${aws_db_instance.MySQLDatabaseInstance.password}"
}

resource "mysql_database" "app1" {
name = "db_01"
}

resource "mysql_database" "app2" {
name = "db_02"
}

For PostgreSQL Database:

  • Define a random password resource for PostgreSQL using random_password module in main.tf file.
  • Configure additional PostgreSQL database resources (postgresql_database) as necessary, ensuring unique names as shown below.
resource "random_password" "PgMasterPassword" {
length = 16
special = true
override_special = "$%!)1"
}

resource "aws_db_instance" "PostgresDatabaseInstance" {
identifier = "rds-pg-poc"
engine = "postgres"
engine_version = "16.1"
instance_class = "db.t3.micro"
allocated_storage = "30"
storage_type = "gp3"
apply_immediately = "true"
db_name = "rdspoc"
username = "rdspocadmin"
password = random_password.PgMasterPassword.result
port = "5432"
db_subnet_group_name = "default-vpc-ID"
vpc_security_group_ids = ["sg-ID"]
multi_az = "false"
auto_minor_version_upgrade = "true"
backup_window = "03:00-06:00"
backup_retention_period = "7"
maintenance_window = "Sun:00:00-Sun:03:00"
deletion_protection = "false"
performance_insights_enabled = "false"
final_snapshot_identifier = "rds-poc-final-snapshot"
parameter_group_name = "rds-pg-poc-db-paramter-group"
publicly_accessible = true
}

provider "postgresql" {
host = "${aws_db_instance.PostgresDatabaseInstance.address}"
username = "${aws_db_instance.PostgresDatabaseInstance.username}"
password = "${aws_db_instance.PostgresDatabaseInstance.password}"
port = "${aws_db_instance.PostgresDatabaseInstance.port}"
}

resource "postgresql_database" "app1" {
name = "db_01"
}

resource "postgresql_database" "app2" {
name = "db_02"
}

After making the above changes in the terraform config files execute the below commands:

  • Run the terraform plan and apply command.
  • Terraform applies changes, adding new databases to the existing RDS instances.

Now, let’s check and ensure:

  • Databases are successfully added without interrupting existing operations.
  • Verify data integrity in both existing and newly added databases.

Conclusion:

By utilizing Terraform’s infrastructure as code capabilities and AWS RDS, we have efficiently added new databases to the existing RDS instance without causing disruptions to ongoing operations. This demonstrates the scalability and reliability of our infrastructure, allowing us to adapt to evolving business needs seamlessly.

Testing Considerations:

It’s important to note that the provided code is tested with a publicly accessible RDS instance. If you wish to test with a private RDS instance, it’s recommended to set up a Jump host within the same VPC.

In my case, I utilized Jenkins in conjunction with Terraform to provision AWS resources, ensuring smooth deployment regardless of the instance’s accessibility settings. This approach ensures flexibility and security, enabling hassle-free scaling of databases in various network configurations.

I trust that this guide will prove invaluable in your journey of managing AWS RDS instances. Stay tuned for further insights and best practices as I continue to explore the realm of AWS database management

Thank you for reading.

--

--