DEV Community

Cover image for Getting Started with AWS and Terraform: Setting Up Application Load Balancer (ALB) Across Multiple AZs Using Terraform
Chinmay Tonape
Chinmay Tonape

Posted on • Updated on

Getting Started with AWS and Terraform: Setting Up Application Load Balancer (ALB) Across Multiple AZs Using Terraform

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:

Architecture ALB across AZs

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"
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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

  }
}
Enter fullscreen mode Exit fullscreen mode

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)
}

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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",
]
Enter fullscreen mode Exit fullscreen mode

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.

Created ALB

Running EC2 instances across AZs

Refresh the page to observe how the ALB routes requests to the EC2 instances in its target group.

Routing 1

Routing 2

Routing 3

Routing 4

Cleanup

To avoid incurring unnecessary costs, remember to stop AWS components when they are no longer needed:

terraform destroy -auto-approve
Enter fullscreen mode Exit fullscreen mode

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)