Step-by-Step Guide: Building a Highly Available Web Infrastructure on AWS Using Terraform

Md. Ashraf Bhuiya
4 min readAug 10, 2023

--

In today’s fast-paced digital world, having a highly available web infrastructure is crucial for delivering seamless user experiences. This guide will walk you through the process of setting up a robust and fault-tolerant web infrastructure on Amazon Web Services (AWS) using Terraform. We’ll cover each step, from creating a Virtual Private Cloud (VPC) to deploying EC2 instances behind a Load Balancer.

Prerequisites:

Before you begin, ensure you have the following prerequisites in place:

  1. AWS Account: Create an AWS account if you don’t have one.
  2. Terraform Installed: Install Terraform on your local machine.
  3. AWS CLI: Install and configure the AWS Command Line Interface (CLI).

Step 1: Set Up Your Project Directory:

Create a new directory for your project and navigate to it in your terminal.

mkdir web-infrastructure-terraform
cd web-infrastructure-terraform

Step 2: Create Terraform Configuration Files:

Inside your project directory, create a new file named main.tf. This is where you'll define your infrastructure using Terraform's HashiCorp Configuration Language (HCL).

Step 3: Create provider.tf for AWS Configuration:

Create a new file named provider.tf in your project directory to separate the provider configuration from the main Terraform file. This file will contain your AWS provider settings.

terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.11.0"
}
}
}

provider "aws" {
region = "us-east-1"
# Configuration options
}

Step 4: Create variables.tf for Managing Variables:

To enhance flexibility and maintainability, let’s create a variables.tf file to manage variables used throughout your Terraform configuration. This approach makes it easier to customize settings without modifying the main configuration directly. I will use one example here. If you want, you can utilize all the declarations provided here and then invoke them in the main.tf file.

variable "cidr" {
default = "10.0.0.0/16"

}

Step 5: Create a Virtual Private Cloud (VPC):

Define your VPC using the aws_vpc resource. From here on, everything will be placed in the main.tf file. I will be using VS Code for this. I will use a vs-code for this. Add the following code snippet:

resource "aws_vpc" "my_vpc" {
cidr_block = var.cidr # cidr we put into variable.tf fiel
}

Step 6: Attach an Internet Gateway:

resource "aws_internet_gateway" "my_igw" {
vpc_id = aws_vpc.my_vpc.id
}

Step 7: Create Public Subnets in Different Availability Zones:

For high availability, create public subnets in two different availability zones. Add the following code:

resource "aws_subnet" "public_subnet_az1" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
}

resource "aws_subnet" "public_subnet_az2" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1b"
}

Step 8: Launch EC2 Instances with UserData:

In this step, we’ll enhance the aws_instance a resource to launch EC2 instances with an Apache web server set up using UserData scripts.

  1. Deploy EC2 instances in the public subnets
resource "aws_instance" "web_instances" {
count = 2

ami = "ami-12345678" # Replace with your desired AMI
instance_type = "t2.micro"
subnet_id = count.index == 0 ? aws_subnet.public_subnet_az1.id : aws_subnet.public_subnet_az2.id
}

Including a separate userdata.sh script and calling it within the aws_instance block in main.tf is a best practice for keeping the UserData section clean and manageable. Here's how you can do it:

#!/bin/bash

# Update and install Apache
apt-get update
apt-get install -y apache2

# Start Apache service and enable on boot
systemctl start apache2
systemctl enable apache2

# Create a custom index.html file
echo "Hello from EC2 instance ${count.index}" > /var/www/html/index.html
  1. Update main.tf to Reference userdata.sh:

Modify the aws_instance resource block in your main.tf to reference the userdata.sh script. Here's an example snippet:

Step 9: Configure a Route Table for External Access:

Create a route table that routes traffic from the Internet Gateway to the public subnets. Add the following code:

resource "aws_route_table" "public_route_table" {
vpc_id = aws_vpc.my_vpc.id

route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.my_igw.id
}
}

Step 10: Set Up a Load Balancer:

Implement a Load Balancer to distribute incoming traffic across instances. Add the following code snippet:

resource "aws_lb" "my_lb" {
name = "my-load-balancer"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.lb_sg.id]
subnets = [aws_subnet.public_subnet_az1.id, aws_subnet.public_subnet_az2.id]
}

Step 11: Define Target Groups and Listeners:

Define Target Groups and Listeners to manage Load Balancer traffic. Add the following code:

resource "aws_lb_target_group" "my_target_group" {
name = "my-target-group"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.my_vpc.id
}

resource "aws_lb_listener" "my_listener" {
load_balancer_arn = aws_lb.my_lb.arn
port = 80
default_action {
target_group_arn = aws_lb_target_group.my_target_group.arn
type = "forward"
}
}

Step 12: Configure Health Checks:

Implement health checks to ensure Load Balancer directs traffic to healthy instances. Add the following code:

resource "aws_lb_target_group_attachment" "my_target_group_attachment" {
count = 2
target_group_arn = aws_lb_target_group.my_target_group.arn
target_id = aws_instance.web_instances[count.index].id
}

Step 13: Initialize and Apply Terraform Configuration:

In your terminal, run the following commands to initialize Terraform and apply your configuration:

terraform init
terraform apply

Congratulations! You’ve successfully built a highly available web infrastructure on AWS using Terraform. This infrastructure can handle traffic spikes and ensure the availability of your web applications. As you continue to enhance your applications, remember to follow best practices for security, scalability, and optimization.

By leveraging AWS services and the power of Terraform, you’ve embraced the world of infrastructure as code, allowing you to manage and evolve your infrastructure with ease.

--

--

Md. Ashraf Bhuiya
Md. Ashraf Bhuiya

No responses yet