How to Create an AWS RDS Database Instance Using Terraform
Tags: tutorial, terraform, aws, cloud
Published: 2023-05-20 15:52:50

As an Infrastructure-as-Code (IaC) tool, Terraform allows you to programmatically build, modify, and provision cloud infrastructure. AWS Relational Database Service (RDS) is a service that offers scalable and reliable database solutions for various platforms, such as MySQL, PostgreSQL, Oracle, and SQL Server. By using Terraform to create an AWS RDS database, you can automate the creation and management of database components right from your coding environment.

In this tutorial, you'll learn how to create an AWS RDS database using Terraform.

## Prerequisites
Before you start this tutorial, make sure you have the following tools installed and ready to use:

- **Terraform CLI** - To start using Terraform, you need to install it in your local environment.
You can easily do that by downloading and installing the binary package or compiling it from source. Visit the link below to follow the step-by-step installation process for your operating system: https://learn.hashicorp.com/tutorials/terraform/install-cli
- **AWS CLI** - After installing Terraform, it is equally important to install AWS CLI because that will enable us to communicate directly with your AWS environment from the terminal. After installing AWS CLI, run `aws configure` on your terminal. 
This will prompt you to provide your AWS access and secret keys for authentication. After entering it, you have successfully connected your command line to the AWS environment.

## Setting Up The project

For this tutorial, we'll set up a demo project folder on our local computer and then open the folder in a code editor.

You can manually create your project folder in your preferred code editor or from your command line.
Run the following command if you prefer the latter:

`mkdir terraform-rds-demo-db`


Navigate to the folder by running:
`cd terraform-rds-demo-db`


These commands will create a new folder named `terraform-rds-demo-db` and change our working directory to that folder.


## Creating The Terraform Files

Before defining our RDS instance resources, let's explore some of the terraform files we'll use.

In this tutorial, we'll use of 3 main files: `rds.tf` , `vars.tf`, and `providers.tf`.

- `rds.tf` - this folder will hold all the definitions of our RDS infrastructure. It will contain the template configuration for AWS to follow when creating our DB instance.
- `vars.tf` - This is a variable file. It will hold the access key, region, and secret key of our AWS environment, as well as other custom variables we might want to declare.
- `provider.tf` - this file will tell Terraform that we're using AWS as our infrastructure provider while supplying the necessary AWS credentials like access key, secret key, and region.

You can create the three files by running the following command in your project directory:
`touch rds.tf vars.tf provider.tf`

You can also create the files manually inside the project folder

## Creating The RDS Instance

After creating the required files, the next step is to populate each file with the appropriate configurations.

**1. Writing the DB instance configurations**

In the `rds.tf` file, put the following configuration;

```
resource "aws_db_instance" "default" {
# Allocate the storage for database instance.
  allocated_storage    = 10
# Define the database engine and engine_version
  engine               = var.engine
  engine_version       = var.engine_version
# Declare the instance class
  instance_class       = var.instance_class
  name                 = var.name
# User to connect the database instance 
  username             = var.username
# Password to connect the database instance 
  password             = var.password
  parameter_group_name = var.parameter_group_name
}
```



In the code above, the `resource` keyword allows us to tell Terraform which AWS resource we are about to create. Specifying the `aws_db_instance` resource creates all the necessary queries to include when making an API call to AWS to provision our RDS instance.

- The `allocate_storage` parameter allows us to specify the storage size of our database in GiB.
- The `engine` and `engine_version` parameters specify which type of database we choose to create. We will create a MySQL database in this tutorial. Other database engines you can choose from includes PostgreSQL, MariaDB, Oracle and SQL Server.
- The `instance_class` specifies the AWS hardware instance on which we want to run our database. We will use the AWS `t3.micro` instance class, accompanied by any name we want; "my-database" in this case.
- The `parameter_group_name` parameter defines the configuration of our database engine.

You should notice that all the values of the parameters so far in the `rds.tf` file are placeholder variables. We'll declare and define the values of the variables in the next steps.

**2. Declaring and assigning values to the variables**

In the `vars.tf` file, paste the following code:

```
variable "engine" {}
variable "engine_version" {}     
variable "instance_class" {}
variable "name"  {}       
variable "username" {}  
variable "password" {} 
variable "parameter_group_name" {}
```

This code will declare the variables we use in the `rds.tf` file.

To not hard-code our variables' values and avoid security compromise because of secret credentials like passwords and username, create a new file in the project directory and name it `terraform.tfvars` and paste the code below.

  

```
engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t3.micro"
  name                 = "mydb"
  username             = "user1"
  password             = "my_password"
  parameter_group_name = "default"
```


When Terraform creates our AWS RDS instance, the instance will be:

- MySQL version 5.7 database
- Running on a `t3.micro` engine
- Admin username of `user1` 
- Password of `my_password`

_Note:_ The `parameter_group_name` in our `terraform.tfvars` file has a value of `default`. So, we need to define the configuration for "default".
Include the code below in the `rds.tf` file:

```
resource "aws_db_parameter_group" "default" {
  name        = "${var.rds_instance_identifier}-param-group"
  description = "Terraform example parameter group for mysql5.6"
  family      = "mysql5.6"
  parameter {
    name  = "character_set_server"
    value = "utf8"
  }
  parameter {
    name  = "character_set_client"
    value = "utf8"
  }
}
```

**3. Specifying the provider**
As we explained earlier, the `providers.tf` file will contain the details of our cloud provider, including the availability region we will create our database instance.
Open the `providers.tf` file and pass the following code:

```
required_providers {
    aws = {
    source  = "hashicorp/aws"
    version = "~> 3.27"
    region = "us-east-2"
    }
```

**4. Creating the RDS instance on AWS**
After populating our configuration files with the appropriate declarations, parameters, and values, the next is to tell AWS to create our database with the specified attributes.

**First** we will run:

`terraform init`

This will initialize Terraform in our project directory and load all the necessary plugins for it to communicate with AWS from our command line. If things go well, you'll see a message like the image below on the CLI.

![Response from initializing Terraform](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fk9lwtsx61pnmdupum2w.png)

**Then**, we go through an optional confirmation step by running:
`terraform plan`
This command will show an overview of the actions Terraform will perform. It is advisable to go through this step because it can be beneficial in figuring out errors in your configuration files before moving on to creating the resources on AWS.

![Response from running terraform plan](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/swvikyd5a92aqztyqmtr.png)

**And finally**, to build our RDS instance on AWS, we run:
`terraform apply`
This command will display all the resources to be created and ask if you're ready to continue.
If you're ready, type: `yes`.

This will apply all the configurations we specified in our terraform files and create our RDS instance. Terraform might take a few minutes to do all the hard work of connecting the references from all of our files to create our database. 
After creating our RDS instance on AWS, terraform shows a success message on your command line.

_Note:_ You can confirm that your RDS instance is up and running by viewing it from your AWS management console.

## Creating RDS Instance in a VPC
Suppose you want to launch your RDS instances in a particular VPC and subnet group(s). In that case, you can create the VPC and subnet groups and then specify the configuration of your RDS in the subnet group.

To do this, we'll create a new file in our project directory and name it `db-subnet.tf`.

First, we create the VPC using the following code:

```
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}

```
Then we'll create 2 subnet groups, one from different availability zones.

This will create a subnet, `private-subnet1`, in the availability zone.

```
resource "aws_subnet" "private-subnet1" {
vpc_id = "${aws_vpc.main.id}"
cidr_block = "10.0.2.0/24"
availability_zone = "AZ-a of the Region"
}
```
This will create our second subnet, `private-subnet2`, in the availability zone you specify.

```
resource "aws_subnet" "private-subnet2" {
vpc_id = "${aws_vpc.main.id}"
cidr_block = "10.0.3.0/24"
availability_zone = "AZ-b of the region"
}
```

And finally, we create a subnet group containing the 2 subnets we created above:

```
resource "aws_db_subnet_group" "db-subnet" {
name = "DB subnet group"
subnet_ids = ["${aws_subnet.private-subnet1.id}", "${aws_subnet.private-subnet2.id}"]}
```

Also, we need to create a security group in the VPC to which our database subnets will belong:

```
resource "aws_security_group" "rds" {
  name        = "terraform_rds_security_group"
  description = "Terraform example RDS MySQL server"
  vpc_id      = "${aws_vpc.vpc.id}"
  # Keep the instance private by only allowing traffic from the web server.
  ingress {
    from_port       = 3306
    to_port         = 3306
    protocol        = "tcp"
    security_groups = ["${aws_security_group.default.id}"]
  }
  # Allow all outbound traffic.
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags {
    Name = "terraform-example-rds-security-group"
  }
}

```

After doing all that, we'll include a `db_subnet_group_name` parameter in the `aws_db_instance` declaration of our `rds.tf` file and reference the database subnet.

```
db_subnet_group_name = "${aws_db_subnet_group.db-subnet.name}"
```

Now we can run `terraform plan` to overview what changes we're about to make, and then `terraform apply` to execute it in our AWS environment.
This will effectively create a VPC and 2  subnets, and create our RDS instance in both subnets of our VPC.
### Creating an RDS Instance from an Existing Database
To create our RDS instance from an existing database snapshot, assume that we have a blank `rds.tf` file.

Paste the following code in the blank `rds.tf` file:

```
data "aws_db_snapshot" "db_snapshot" {
most_recent = true
db_instance_identifier = "testinstance"
}
```


The `most_recent` parameter checks for the latest database snapshot in the `testintance` instance, which we specified as the value of `db_instance_identifier`.

Now we will create a new resource in the `rds.tf` file and pass the snapshot identifier for Terraform to create our RDS from the snapshot

```
resource "aws_db_instance" "db_test" {
instance_class = "db.t2.small"
identifier = "newtestdb"
username = "test"
password = "Test@54132"
publicly_accessible = false
db_subnet_group_name = "${aws_db_subnet_group.db-subnet.name}"
snapshot_identifier = "${data.aws_db_snapshot.db_snapshot.id}"
vpc_security_group_ids = ["sg-00h62b79"]
skip_final_snapshot = true
}
```

After having all the necessary files and parameters in place, we can now run `terraform plan` and `terraform apply`, accordingly, and Terraform will create our new RDS database instance from the snapshot.

## Conclusion
Provisioning cloud infrastructure using an IaC tool like Terraform makes it easier to manage small and large infrastructures and avoid the bunch of clicking around involved in using a graphical interface. With this tutorial, you now know how to create an AWS RDS database for your projects using Terraform.