Introduction
In today's cloud-based infrastructure, managing databases efficiently and securely is crucial for the performance and scalability of applications. Amazon RDS offers a reliable and scalable database service that simplifies the setup, operation, and scaling of relational databases in the AWS cloud. Additionally, using Terraform—a popular Infrastructure as Code (IaC) tool—allows us to automate the provisioning of RDS instances and their read replicas, ensuring consistent and reproducible deployments.
What is Amazon RDS?
Amazon RDS is a fully managed relational database service provided by AWS that simplifies the setup, operation, and scaling of relational databases in the cloud. With Amazon RDS, you can choose from several database engines such as MySQL, PostgreSQL, Oracle, SQL Server, and more, and leverage features like automated backups, scaling capabilities, and security controls.
What is a Read Replica?
A read replica in Amazon RDS is a copy of the primary database instance that allows you to offload read traffic from the primary instance, thereby improving read scalability and availability. Read replicas are asynchronous and can be used for read-heavy workloads without impacting the performance of the primary instance.
Terraform Configuration Example
Let's take a look at a basic example of how to create an Amazon RDS instance and a read replica using Terraform:
In the main.tf
file
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-west-1" ## Specify your desired AWS region
}
resource "aws_db_instance" "primary" {
// RDS primary instance configuration
engine = var.db_engine
engine_version = var.db_engine_version
username = var.db_username
password = var.db_password
allocated_storage = 30
storage_encrypted = true
db_name = "cool"
storage_type = "gp3"
instance_class = var.db_instance_type
port = 5432
publicly_accessible = false
identifier = var.db_name
multi_az = false
skip_final_snapshot = true
backup_retention_period = 7
timeouts {
create = "3h"
delete = "3h"
update = "3h"
}
}
resource "aws_db_instance" "read_replica" {
// RDS read replica configuration
identifier = "${var.db_name}-read-replica"
replicate_source_db = aws_db_instance.primary.identifier
storage_type = "gp2"
instance_class = var.db_instance_type
storage_encrypted = true
multi_az = false
auto_minor_version_upgrade = false
skip_final_snapshot = true
port = 5432
publicly_accessible = false
timeouts {
create = "3h"
delete = "3h"
update = "3h"
}
}
output "primary_endpoint" {
value = aws_db_instance.primary.endpoint
}
output "read_replica_endpoint" {
value = aws_db_instance.read_replica.endpoint
}
Let us Break down the things :
The aws_db_instance
resource block defines the primary RDS instance configuration.
engine
: Specifies the database engine (e.g.,postgres
).engine_version
: Specifies the version of the database engine.username
andpassword
: Credentials for accessing the database.allocated_storage
: Storage allocated to the instance in GB.storage_encrypted
: Indicates whether storage is encrypted.db_name
: Name of the database to be created on the instance.storage_type
: Storage type for the instance (e.g.,gp3
).instance_class
: Instance type for the RDS instance (e.g.,db.t3.medium
).port
: Port on which the database accepts connections.publicly_accessible
: Specifies if the database is accessible from the public internet.identifier
: Unique identifier for the RDS instance/RDS Replicamulti_az
: Specifies whether the instance is deployed in multiple Availability Zones for high availability.skip_final_snapshot
: Indicates whether a final DB snapshot is created before the instance is deleted.backup_retention_period
: Number of days to retain automated backups.timeouts
: Specifies the maximum duration for create, delete, and update operations.replicate_source_db
: Specifies the identifier of the primary RDS instance to replicate from.primary_endpoint
: Output that exposes the endpoint of the primary RDS instance.read_replica_endpoint
: Output that exposes the endpoint of the read replica.
In terraform.tfvars
, we can mention the variable values below :
db_name = "test"
db_engine = "postgres"
db_engine_version = "16.1"
db_username = "test"
db_password = "******" ## give your desired passsword always store the creds in AWS Secret manager :)
db_instance_type = "db.t3.micro"
In variable.tf
file,
variable "db_name" {
}
variable "db_engine" {
}
variable "db_engine_version" {
}
variable "db_instance_type" {
}
variable "db_username" {
}
variable "db_password" {
}
// Add more variables as needed for customization
Now we can make the Infrastructure ready using terraform commands:
before that always run terraform init
(make sure you got the provider installed ) and terraform fmt
for formatting the tf files, terraform validate
to validate the infra.
terraform plan
+ tags_all = (known after apply)
+ timezone = (known after apply)
+ username = (known after apply)
+ vpc_security_group_ids = (known after apply)
+ timeouts {
+ create = "3h"
+ delete = "3h"
+ update = "3h"
}
}
Plan: 2 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ primary_endpoint = (known after apply)
+ read_replica_endpoint = (known after apply)
By using the terraform graph
command we can get the graph.png below
terraform graph -type=plan | dot -Tpng >graph.png
Now it is to apply the terraform plan using terraform apply
the command:
Plan: 2 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ primary_endpoint = (known after apply)
+ read_replica_endpoint = (known after apply)
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_db_instance.primary: Creating...
aws_db_instance.primary: Still creating... [10s elapsed]
aws_db_instance.primary: Still creating... [20s elapsed]
.
.
.
aws_db_instance.primary: Still creating... [7m40s elapsed]
aws_db_instance.primary: Creation complete after 7m48s [id=db-6J3WGCPX6G72P4BI7KHFI3LXUI]
aws_db_instance.read_replica: Creating...
aws_db_instance.read_replica: Still creating... [10s elapsed]
aws_db_instance.read_replica: Still creating... [20s elapsed]
.
.
.
aws_db_instance.read_replica: Still creating... [8m10s elapsed]
aws_db_instance.read_replica: Still creating... [8m20s elapsed]
aws_db_instance.read_replica: Creation complete after 8m28s [id=db-AW2HHUF7BZPFE3VQND7GCUYHP4]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
primary_endpoint = "test.cziqo46ie914.us-west-1.rds.amazonaws.com:5432"
read_replica_endpoint = "test-read-replica.cziqo46ie914.us-west-1.rds.amazonaws.com:5432"
Now check the AWS Console
For the instance configuration, we mentioned in the main.tf:
That's all, Happy Learning :)