In a previous post, we discussed how to create CloudWatch alarms and receive alarm emails through SNS topics.
This post will guide you through the process of setting up an Application Load Balancer (ALB) in front of a website distributed across multiple Availability Zones (AZs) using Terraform.
Application Load Balancer operates at the application layer (Layer 7) of the OSI model. It is best suited for routing HTTP/HTTPS traffic. It supports content-based routing and host-based routing and allows for routing decisions based on content and application behavior.
Architecture Overview
Before diving into the implementation details, let's briefly review the architecture we'll be working with:
Variables used in this section:
variable "aws_region" {
type = string
description = "AWS region to use for resources."
default = "us-east-1"
}
variable "aws_azs" {
type = list(string)
description = "AWS Availability Zones"
default = ["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d"]
}
variable "enable_dns_hostnames" {
type = bool
description = "Enable DNS hostnames in VPC"
default = true
}
variable "vpc_cidr_block" {
type = string
description = "Base CIDR Block for VPC"
default = "10.0.0.0/16"
}
variable "vpc_public_subnets_cidr_block" {
type = list(string)
description = "CIDR Block for Public Subnets in VPC"
default = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24", "10.0.104.0/24"]
}
variable "instance_type" {
type = string
description = "Type for EC2 Instance"
default = "t2.micro"
}
variable "instance_key" {
default = "MyKeyPair"
}
Step 1: Creating the VPC and Network Components
Create VPC with IGW, 4 public subnets in separate AZs and route table with association. Please refer to my github repo in resources section below.
Step 2: Creating 4 Linux EC2 Web Server Instances in Separate AZs
Create 4 AWS EC2 web servers in public subnets across 4 AZs. Please refer to my github repo in resources section below.
Step 3: Creating an Application Load Balancer
Create an ALB using its separate security group:
####################################################
# create application load balancer
####################################################
resource "aws_lb" "aws-application_load_balancer" {
internal = false
load_balancer_type = "application"
security_groups = [var.security_group_alb[0]]
subnets = tolist(var.public_subnets)
enable_deletion_protection = false
}
Add an inbound rule to EC2 security group to allow traffic from ALB security group
####################################################
# Add an inbound rule to EC2 security group to allow traffic from ALB security group
####################################################
resource "aws_security_group_rule" "ASG-sg-to-alb-sg-ingress" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
security_group_id = aws_security_group.sg.id
source_security_group_id = aws_security_group.aws-sg-load-balancer.id
}
Create target group for ALB with a listener on port 80
####################################################
# create target group for ALB
####################################################
resource "aws_lb_target_group" "alb_target_group" {
target_type = "instance"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
health_check {
enabled = true
interval = 300
path = "/"
timeout = 60
matcher = 200
healthy_threshold = 5
unhealthy_threshold = 5
}
lifecycle {
create_before_destroy = true
}
}
####################################################
# create a listener on port 80 with redirect action
####################################################
resource "aws_lb_listener" "alb_http_listener" {
load_balancer_arn = aws_lb.aws-application_load_balancer.id
port = 80
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.alb_target_group.id
}
}
Finally attach target group with instances:
####################################################
# Target Group Attachment with Instance
####################################################
resource "aws_alb_target_group_attachment" "tgattachment" {
count = length(var.instance_ids)
target_group_arn = aws_lb_target_group.alb_target_group.arn
target_id = element(var.instance_ids, count.index)
}
Steps to run Terraform
Now we will see how to run the above created terraform infrastructure automation
terraform init
terraform plan
terraform apply -auto-approve
Upon successful completion of the Terraform apply, you'll see essential outputs containing information about the created resources.
Apply complete! Resources: 25 added, 0 changed, 0 destroyed.
Outputs:
alb_dns_name = "tf-lb-20231130193349621000000004-1500099737.us-east-1.elb.amazonaws.com"
ec2_instance_ids = [
"i-05eb93181588e2b83",
"i-09431707f204e99ad",
"i-067704933b1bc4b3b",
"i-07bc08112198ff133",
]
Testing the ALB
After the Terraform apply, you can test the functionality of the ALB. Use the ALB's DNS name to access the website.
Refresh the page to observe how the ALB routes requests to the EC2 instances in its target group.
Cleanup
To avoid incurring unnecessary costs, remember to stop AWS components when they are no longer needed:
terraform destroy -auto-approve
Congratulations! You've successfully deployed an Application Load Balancer (ALB) in front of four Web Server EC2 instances across multiple Availability Zones.
In the next module, we'll explore enhancing the setup by incorporating EC2 auto scaling with ALB to further optimize the scalability and availability of our application. Happy Coding!
Resources:
Github Link: https://github.com/chinmayto/terraform-aws-linux-webserver-ec2-alb
ALB: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html
Top comments (0)