Deploying a Highly Available Web App on AWS Using Terraform

ALLAN CHERUIYOTALLAN CHERUIYOT
5 min read

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 a region (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 and aws_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 and data "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 the index.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 using count.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: Discovering count 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 my user_data scripts executed perfectly on instance launch, especially when incorporating count.index. Careful review of instance logs and using terraform 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!

0
Subscribe to my newsletter

Read articles from ALLAN CHERUIYOT directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ALLAN CHERUIYOT
ALLAN CHERUIYOT