Creating a Reliable Two-Tier Architecture with Terraform
Written on
Chapter 1: Introduction to Two-Tier Architecture
In this guide, I will demonstrate how to establish a robust two-tier architecture utilizing Terraform. The setup will include three public subnets, three private subnets, a Bastion Host located in one of the public subnets, an Auto Scaling Group for the Web Server (situated within the private subnets), and an internet-facing Application Load Balancer that directs traffic to the Web Server Auto Scaling Group. The infrastructure will be deployed using Terraform Cloud as a Continuous Integration/Continuous Deployment (CI/CD) tool.
Before diving in, it’s essential to note that there are several prerequisites for this project, including an AWS account and a Terraform Cloud account, among others. While I won't list every requirement here, I encourage those following along to familiarize themselves with the necessary tools. If you're here to expand your knowledge or simply for a good read, I hope you find this helpful!
To begin, I'll create (not build) all the necessary modules and files that I anticipate needing. Below is an overview of my file structure.
Next, I will set up my VPC by including a random integer in the main.tf file of my networking module. While a random integer isn't strictly necessary, it may prove useful later on. To keep track of your work, it’s advisable to add the module and file name at the top of each file.
In the same networking module, I will also add the VPC CIDR as a variable in the variables.tf file. To call on the networking module (child module) from the root module (parent module), I will need to specify it as the source file and include the VPC CIDR block in the main.tf file of the root module.
To verify that everything is set up correctly, I will run terraform init to initialize it, terraform validate to check for code validity, and terraform plan to ensure a plan is generated for the VPC. Everything seems to be in order!
Now, let's proceed with terraform apply. Great! The VPC has been successfully created. I will quickly check my console to confirm that the VPC was added correctly. Success! The VPC was created with the random integer 45.
After executing terraform plan, I can see all the resources set to be created. Excellent!
Now, I will navigate to Terraform Cloud to establish a new workspace, opting for the version control workflow. After selecting my workflow, I will connect to my VPC via my GitHub account and choose my repository to create my workspace.
Once the workspace is created, I was prompted to configure Terraform variables, which was unexpected. I decided to skip this step and address it later if necessary. I will need to set my environment variables, so I will select "configure variables" and make sure to check the sensitive box for my AWS Access Key ID and Secret Access Key.
With all my variables set up, my workspace should now be prepared. Next, I’ll initiate a new run by selecting actions, then "start new run," followed by "plan only," as I want to review the plan before applying it.
I encountered a few errors, including some undeclared variables and an issue with configuring my Terraform AWS Provider. After some troubleshooting, I discovered that workspace variables need to be in all caps. I resolved that issue and ran the plan again, though a couple of warnings remain.
I suspect these warnings are due to not checking the HCL box when creating two non-sensitive variables. However, after making that adjustment, I managed to eliminate one of the warnings. With a bit of persistence, I decided to remove the confirm destroy variable, as I don't require confirmation when ready to destroy resources—though this might not be advisable in a production scenario. Despite the warnings, the plan indicates that all 33 resources will be created.
Everything is looking promising now! I’ll run plan and apply. Once the plan is completed, I will confirm and apply it.
And… another error! One of the things I appreciate about Terraform is its clear error messages. I found an underscore in the name of my load balancer, which is invalid. I will need to correct this in my configuration files. The error points to the main.tf file of my load balancing module on line 16.
After making the necessary changes and pushing them to GitHub, I’m ready to try again. I had to repeat the previous steps and unlock the workspace to proceed. Now, I’ll confirm and apply once more. Success! The last three resources have been created.
Now, I will inspect my AWS console to see the newly created resources. I can confirm the presence of three public and three private subnets, the Load Balancer, and the Auto Scaling groups.
To ensure everything is functioning correctly, I’ll check if I can access the internet using my application load balancer’s DNS name. And indeed, I can! Refreshing will cycle through IP addresses, though I couldn't access it using EC2 IP addresses. Fantastic!
Currently, I have three EC2 instances running: one for my Bastion host and two for my database. Let’s see what happens if I adjust the desired capacity of my database in the compute module from 2 to 3 and push it to GitHub.
This change will automatically trigger a new plan. That’s the beauty of automation in Terraform and CI/CD! After viewing the details, I can confirm and apply again. The only modification shown is the addition of one EC2 instance.
I will now discard the run and proceed to destroy all resources. To do this, I navigate to settings and select destruction and deletion, then queue and destroy plan. I will need to unlock the workspace before proceeding with destruction. The prompts guide me through this process.
It appears I’m set to destroy all 33 resources that were created. After reviewing the details, I can finalize this process. After a few more steps, everything has been successfully destroyed.
Boom! That's how you construct a two-tier architecture using Terraform. Although this took several hours (being my first attempt), the creation of modules will allow me to replicate this process and implement small changes for future projects.
That's the advantage of using Terraform. It's perfectly suited for automation—make a minor change in your configuration files, push it to GitHub, and the modifications are queued for approval in Terraform Cloud.
In the near future, I plan to incorporate an S3 remote backend into this setup. Stay tuned!
Thank you for reading. I hope you found this informative.
Jason Wood
@jwood9799
Chapter 2: Video Demonstrations
Here are two useful videos that further illustrate the process of deploying a two-tier architecture on AWS using Terraform.
The first video provides an overview of deploying a two-tier application on AWS with Terraform, covering essential concepts and steps involved.
The second video dives deeper into deploying a two-tier architecture in AWS using Terraform, showcasing practical implementation details.