Using Terraform to Create EC2 and RDS Instances Inside a Custom VPC on AWS

Matt Little
Strategio

--

This is the architecture diagram of what we will be creating with Terraform

Background

Scenario: Your team has been working on a web application that uses a database. You have been tasked with setting up the VPC, EC2, and RDS instances using Terraform. Your team will be using EC2 instances to deploy the web application and MySQL RDS for the database.

Requirements

  • EC2 instances should be accessible anywhere on the internet via HTTP
  • Only you should be able to access the EC2 instances via SSH
  • RDS should be on a private subnet and inaccessible via the internet
  • Only the EC2 instances should be able to communicate with RDS

How will we accomplish these tasks?

  1. Create a VPC
  2. Create an Internet Gateway and attach it to the VPC
  3. Create 3 subnets: 1 public for EC2 and 2 private for RDS
  4. Create 2 route tables: 1 public and 1 private
  5. Create 2 security groups: 1 for EC2 and 1 for RDS
  6. Create the DB subnet group
  7. Create the MySQL RDS database
  8. Create the EC2 instance
  9. Verify that everything is set up correctly

Prerequisites

Declaring our Variables

First, we are going to put together the variables file for Terraform.

  • Let’s create a directory for our terraform project and cd into it
mkdir terraform-tutorial && cd terraform-tutorial
  • Create a file in the project directory called variables.tf
touch variables.tf
  • Open variables.tf in your editor and add the following:

Creating our Secrets File

Now that the variables have been declared, let's go ahead and set up our secrets file.

  • Create a file in the same directory called secrets.tfvars
  • Open the file in your editor and add the following information:

Creating our Main Config File

Now that we have defined both the variables and secrets, let’s start creating our config file.

  • Create a file in the same directory called main.tf
  • Open the file in your editor and add the following information:

Step One—Creating the VPC

Now it’s time to begin setting up our AWS environment. We are going to be working in the main.tf file for the majority of this tutorial.

  • Go ahead and add the following code to your main.tf file

Step Two — Creating the Internet Gateway

Now that the VPC resource has been created, it’s time to create the Internet Gateway and attach it to the VPC.

  • Go ahead and add the following code to your main.tf file

Step Three — Creating the Subnets

Time to create the subnets. In our case, we are going to need 1 public subnet and 2 private subnets.

Note: Since RDS requires 2 subnets for a database and our database is going to be in the private subnet, that is why we need 2 private subnets

The Public Subnet

The Private Subnets

Step Four — Creating the Route Tables

Now that the subnets have been created, we can go ahead and create the route tables. We are going to be creating a public and a private route table.

The Public Route Table

The Private Route Table

Step Five — Creating the Security Groups

Time to create the security groups! We are going to be creating a security group for the web application (EC2) and one for the database (RDS). Now, remember we need to meet the requirements that were set in the beginning. Here they are again:

  • EC2 instances should be accessible anywhere on the internet via HTTP
  • Only you should be able to access the EC2 instances via SSH
  • RDS should be on a private subnet and inaccessible via the internet
  • Only the EC2 instances should be able to communicate with RDS

The EC2 Security Group

The RDS Security Group

Step Six — Creating the DB Subnet Group

Now that the security groups are done, let’s move over to RDS. The first thing we need to do is create the DB subnet group.

Step Seven — Creating the MySQL RDS Database

After the DB subnet group has been created, we can now create the database. We will be using MySQL RDS for the database.

Step Eight — Creating the EC2 Instance

Now that everything else has been set up, we are ready to set up the EC2 instance. This is going to contain 3 parts:

  • Creating the key pair
  • Creating the EC2 instance
  • Creating an Elastic IP and attaching it to the EC2 instance
Tip: Use Elastic IP on EC2 instances where you need to have a static public IP address

Creating the Key Pair

We will be creating a new key pair in our terraform directory. Run the following command:

ssh-keygen -t rsa -b 4096 -m pem -f tutorial_kp && openssl rsa -in tutorial_kp -outform pem && chmod 400 tutorial_kp.pem

Now we will need to take this key and make it an AWS key pair. Open up the main.tf file and add the following code:

Creating the EC2 Instance

Now that the key pair has been created, we can go ahead and create the EC2 instance. We will be running our EC2 instance on Ubuntu 20.04. But before we create the EC2 instance, let’s create a data object that will hold the most recent versions of Ubuntu 20.04.

Now that the data object has been created, we can create the EC2 instance.

Creating the Elastic IP and attaching it to the EC2 instance

Now that the EC2 instance has been created, we can create the Elastic IP and attach it to the EC2 instance.

Outputs

Alright, ONE more thing before we finish up here. Let’s go ahead and create some outputs.

  • Create a file called outputs.tf and open it in your editor
  • Add the following to the outputs file:

Step Nine — Verification

Woo! Alright, now that our main config file and outputs are finished, let’s run our configuration and make sure everything works correctly. On the command line, run the following commands:

terraform initterraform apply -var-file="secrets.tfvars"

When prompted for a value, enter: yes

Tip: If you have any issues running terraform init, try running this command:terraform init -upgradeThis will install the latest module and provider versions.

It will take a few minutes for Terraform to apply the configuration. When it is done, you should see something similar to this:

Now let’s verify that we can SSH into the EC2 instance and that we can communicate with RDS from inside the EC2 instance. Make note of database_endpoint and database_port, we will need those once we are inside the EC2 instance.

ssh -i "tutorial_kp.pem" ubuntu@$(terraform output -raw web_public_dns)

If you have any issues connecting to the EC2 instance, try this command:

ssh -o 'IdentitiesOnly yes' -i "tutorial_kp.pem" ubuntu@$(terraform output -raw web_public_dns)

Once connected to the EC2 instance, let’s try connecting to the RDS instance. First, we will need to install the MySQL client. Run the following command:

sudo apt-get update -y && sudo apt install mysql-client -y

Once that MySQL client is installed, let’s try connecting to the RDS instance.

  • The <database-endpoint> is going to be your database_endpoint from the terraform output
  • The <database-port> is going to be your database_port from the terraform output
  • The <db-username> is going to be your DB username, which was the db_username that you created in your secrets
mysql -h <database-endpoint> -P <database-port> -u <db-username> -p

When prompted, enter the password of the DB user. This was the db_password you created in your secrets file. If successful, you should see the following:

We are connected to the MySQL RDS database. Let's see if our database was created. Run the following command in the MySQL terminal

show DATABASES;

Woohoo! The database that we declared in our variable settings.database.db_name is there!

To avoid any unnecessary charges in AWS, let’s use terraform to destroy everything that we have created. Enter the following command:

terraform destroy -var-file="secrets.tfvars"

When prompted, enter: yes

It will take a few minutes to destroy everything. When it is finished, you should see a success message.

If you had any issues throughout this tutorial, you can compare your code to the final code here: https://github.com/dispact/terraform-custom-vpc

Woohoo!

Congratulations! Through this tutorial, you learned how to use Terraform to configure AWS VPC, EC2, and RDS instances. If you have any questions, please leave a comment. Follow me for more content like this!!

--

--

Matt Little
Strategio

Self-taught Engineer with an interest in Software/DevOps Engineering