Deploying a Highly Available Web App on AWS Using Terraform

Deploying a Highly Available Web App on AWS Using Terraform
In today's fast-paced digital world, ensuring our applications are always available and resilient is paramount. Manual infrastructure setup is prone to errors and can't keep up with rapid changes. This is where Infrastructure as Code (IaC) becomes indispensable. IaC, particularly with a tool like Terraform, allows us to define, provision, and manage our cloud resources using declarative configuration files, bringing consistency, version control, and automation to our infrastructure.
For Day 4 of the 30-Day Terraform Challenge, I dove deep into building configurable and then clustered web servers on Amazon Web Services (AWS) to lay the groundwork for a highly available application. This post details my journey and key learnings.
The Fundamental Blocks: How Terraform Works
Before diving into the deployments, it's essential to revisit Terraform's core components that made these deployments possible:
Providers: These are the plugins that enable Terraform to interact with cloud platforms like AWS. By configuring the
provider "aws"
block and specifying aregion
(e.g.,us-east-1
), we tell Terraform exactly where to manage our resources.Resources: These are the actual infrastructure objects that Terraform creates and manages. For our web application, key resources included
aws_instance
for our virtual servers andaws_security_group
to control network access.Data Sources: Data sources are crucial for dynamic configurations. They allow Terraform to fetch information about existing resources or external data. For instance, I used
data "aws_ami"
to dynamically retrieve the latest Amazon Linux 2023 AMI anddata "aws_vpc"
to identify my default Virtual Private Cloud (VPC), avoiding hardcoding these values.
Building Flexibility: The Configurable Web Server
My first task was to deploy a configurable web server. The goal here was to move beyond fixed configurations and introduce flexibility and reusability into my Terraform code.
The core concept introduced here was Terraform Variables. Instead of hardcoding values like instance_type
or the server's name
, I defined variable
blocks. This meant I could easily change these parameters by modifying a separate .tfvars
file or passing values at the command line, without touching the main configuration. For example, I used variables for:
aws_region
: To select the deployment region.instance_type
: To specify the EC2 instance size (e.g.,t2.micro
).server_name
: To tag the instance with a descriptive name.web_content
: Even the content of theindex.html
page served by Apache could be configured via a variable!
The user_data
script played a vital role in automating the server setup. This script, executed upon instance launch, handled installing Apache, starting the service, and placing the dynamic index.html
content defined by a variable.
(Here, you would ideally insert a code snippet of your configurable-web-server/main.tf
highlighting the variable
blocks and their usage, and a screenshot of your deployed single server.)
Scaling for Resilience: The Clustered Web Server
While a configurable server is a great start, a single server always represents a single point of failure. If that server goes down, your application is offline. To address this, the next step was to deploy a clustered web server, demonstrating a basic form of High Availability (HA).
The magic behind this was Terraform's count
meta-argument. By adding count = var.instance_count
to my aws_instance
resource, I instructed Terraform to create multiple identical instances based on the value of the instance_count
variable. This allowed me to effortlessly scale my web application by simply changing a number.
A powerful aspect of count
is the count.index
variable. This special variable provides a unique, zero-based index for each instance created by the count
argument. I leveraged count.index
to:
Give each server a unique
Name
tag (e.g.,Day4-ClusteredWebServer-1
,Day4-ClusteredWebServer-2
), making them easy to identify in the AWS Console.Dynamically change the
index.html
content for each server usingcount.index + 1
, so each server displayed its unique instance number (e.g., "Hello from Instance 1", "Hello from Instance 2").
All instances in the cluster shared the same aws_security_group
, ensuring consistent network access rules (allowing HTTP on port 80 and SSH on port 22).
(Here, you would insert a code snippet of your clustered-web-server/main.tf
highlighting the count
usage and count.index
, and a screenshot of your multiple deployed servers.)
Achieving Basic High Availability
By deploying a cluster of web servers, I established a foundational level of high availability. If one of the instances in the cluster were to fail, the other instances would remain operational, continuing to serve user requests. This redundancy significantly reduces the risk of application downtime compared to a single-server setup. While true enterprise-grade HA often involves more advanced components like load balancers, auto-scaling groups, and multi-Availability Zone deployments, this clustered setup is a critical first step in building resilient cloud infrastructure.
Key Learnings and Challenges
Day 4 was incredibly insightful, solidifying my understanding of core Terraform concepts:
Variables Mastery: I truly appreciated how variables transform static code into dynamic, reusable templates. This is a game-changer for managing complex infrastructures efficiently.
The Power of
count
: Discoveringcount
opened my eyes to how effortlessly Terraform can manage multiple identical resources, which is essential for scaling and HA.Debugging
user_data
: I faced some minor challenges ensuring myuser_data
scripts executed perfectly on instance launch, especially when incorporatingcount.index
. Careful review of instance logs and usingterraform plan
for dry runs were invaluable for troubleshooting.Documentation is Key: Continuously referring to the Terraform Documentation for specific resource arguments and meta-arguments like
count
was absolutely essential for successful implementation.
Conclusion
Day 4 of the Terraform challenge was a significant step forward in my IaC journey. I successfully deployed both a configurable and a clustered web server on AWS, gaining practical experience with variables and the count
meta-argument. These skills are fundamental to building flexible, scalable, and highly available cloud infrastructure. The ability to define and deploy infrastructure programmatically is not just efficient; it's a critical skill for any modern cloud professional. I'm excited to continue building on this foundation!
Subscribe to my newsletter
Read articles from ALLAN CHERUIYOT directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
