Create an application loadbalancer using terraform for AWS ec2

Nitesh Rijal
DevOps.dev
Published in
8 min readApr 7, 2023

--

Hello everyone, today in this blog in going to discuss about creating alb (application load balancer) in aws (Amazon web services) for this blog I am creating 2 ec2 (elastic compute cloud) instances that dynamically routes we also can have the custom key pair created locally.

What is alb?

An Application Load Balancer (ALB) is a type of load balancer provided by Amazon Web Services (AWS) that helps distribute incoming traffic to multiple targets, such as EC2 instances or containers, within an Amazon Virtual Private Cloud (VPC).

ALBs operate at the application layer (Layer 7) of the OSI model, meaning they can direct traffic based on specific rules, such as the content of the request, rather than just the IP address and port. This makes ALBs well-suited for handling HTTP and HTTPS traffic, as they can route requests to different backend services based on factors like the URL path, hostname, or query parameters.

In addition to providing traffic distribution, ALBs also offer features like content-based routing, SSL/TLS offloading, and health checking. These features can help ensure that traffic is sent to healthy targets and that requests are handled securely and efficiently.

Overall, ALBs are a powerful and flexible tool for managing application traffic within an AWS environment, and are an important component of many modern cloud-based architectures.

What is required to create an alb?

To create an Application Load Balancer (ALB) in AWS, the following components are required:

  1. VPC — An Amazon Virtual Private Cloud (VPC) is a virtual network that provides isolated sections within the AWS cloud. We need to create a VPC and subnets where your ALB and backend targets will reside.
  2. Security Groups — AWS Security Groups are virtual firewalls that control inbound and outbound traffic for your ALB and backend targets. We need to create security groups for your ALB and backend targets that allow the necessary traffic.
  3. Target Group — A Target Group is a logical group of backend targets, such as EC2 instances or containers, that the ALB forwards traffic to. We need to create a target group and register backend targets with it. Here we are creating for ec2 instances.
  4. Listener — A listener is a process that checks for connection requests from clients, using a specified protocol and port, and forwards them to the ALB. We need to create a listener on the ALB that listens for incoming traffic on a specific port and protocol, and routes it to the appropriate target group.
  5. SSL Certificate (Optional) — If we want to secure traffic between clients and the ALB using SSL/TLS encryption, you need to obtain and upload an SSL certificate to the ALB. (this is out of scope for this blog)

Once these components are in place, we can create an ALB using the AWS Management Console, AWS CLI, or Terraform. When creating the ALB, we’ll need to specify the VPC, subnets, security groups, target group, listener, and optionally SSL certificate that we’ve configured. Once created, the ALB will start routing traffic to our backend targets based on the rules we’ve defined.

What’s needed for this blog (prerequisites) ?

  1. AWS CLI :- installation link knowledge of aws cli and aws configure
  2. Terraform:- knowlegde of terrafrom and terraform in your system install link
  3. And of course IDE as your choice (vscode as of my preference)
  4. Last but not the least aws account

Let’s start building the project create the empty directory

mkdir terraformAlbProject

cd into the terraformAlbProject directory now let’s generate the custom key

ssh-keygen

on output enter

Generating public/private rsa key pair.
Enter file in which to save the key (/home/nitesh/.ssh/id_rsa): /home/nitesh/Documents/terraformAlbProject/mykeypair

Here /home/nitesh/Documents/terraformAlbProject/ is path to my project folder and mykeypair is the key name.

now create a main.tf file in the project directory

provider "aws" {
region = var.region
}

Here we are only providing region to deploy our ec2 and alb but need to fetch from the variables for that create file called variables.tf file for more about variables visit this link

variable "region" {}

Now we can directly define the aws region in the terminal prompt

Now let’s define vpc for our deployment for that create vpc.tf file

data "aws_vpc" "default" {
default = true
}

data "aws_subnet_ids" "subnet" {
vpc_id = data.aws_vpc.default.id
}resource “aws_key_pair” “key_pair” {}

Here we are using the data of default vpc and subnet more about using aws_vpc resources and data in this link.

now we create the security group here we are aollowing port 80 http for any of the ip and allowing all for outbound rule. Create securitygroup.tf file for more knowledge about creating security group in terraform visit this link

resource "aws_security_group" "web-server" {
name = "web-server"
description = "Allow incoming Http Conncections"

ingress {
from_port =80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

Now let we create ec2 instance in terraform for that create instance.tf file

resource "aws_key_pair" "key_pair" {
key_name = "mykeypair"
public_key = "${file("mykeypair.pub")}"

}

resource "aws_instance" "web-server" {
ami = "ami-06e46074ae430fba6"
instance_type = "t2.micro"
count = 2
key_name= aws_key_pair.key_pair.key_name
security_groups = ["${aws_security_group.web-server.name}"]
user_data = <<-EOF
#!/bin/bash
sudo su
yum update -y
yum install httpd -y
systemctl start httpd
systemctl enable httpd
echo "<h1>loading from $(hostname -f)..</h1>" > /var/www/html/index.html
EOF
tags = {
name ="instance_alb-${count.index}"
}
}

Here in resource “aws_key_pair” “key_pair” {} we are defining our custom key file that we have created before we have given key_name as “mykeypair” and putting the value of public key referencing the file put in the same directory

Now in resource “aws_instance” “web-server” {} we are defining the name ami-id note the this ami_id may vary according the the aws region here we are deploying t2.micro instance type assigning the above key pair to key pair and assigning security groups that we have just created for refrencing we can see the terrafrom docs. in instance count=2 which is two instances that we are going to deploy and in user_data we are updating the instance and installing the httpd server and putting the ip in /var/www/html/index.html file.

Now let’s create the alb for that make the alb file called alb.tf in same directory

# target group
resource "aws_lb_target_group" "target-group" {
name = "nit-tg"
port = 80
protocol = "HTTP"
target_type = "instance"
vpc_id = data.aws_vpc.default.id

health_check {
enabled = true
interval = 10
path = "/"
port = "traffic-port"
protocol = "HTTP"
timeout = 5
healthy_threshold = 2
unhealthy_threshold = 2
}
}

# creating ALB
resource "aws_lb" "application-lb" {
name = "nit-alb"
internal = false
load_balancer_type = "application"
subnets = data.aws_subnet_ids.subnet.ids
security_groups = [aws_security_group.web-server.id]
ip_address_type = "ipv4"

tags = {
name = "nit-alb"
}
}

resource "aws_lb_listener" "alb-listener" {
load_balancer_arn = aws_lb.application-lb.arn
port = 80
protocol = "HTTP"

default_action {
type = "forward"
target_group_arn = aws_lb_target_group.target-group.arn
}
}

resource "aws_lb_target_group_attachment" "ec2_attach" {
count = length(aws_instance.web-server)
target_group_arn = aws_lb_target_group.target-group.arn
target_id = aws_instance.web-server[count.index].id
}

Here in target group we are making the target for http port 80 and our instances attaching with the vpc id and checking the health of the instances .

The health_check block defines the health check settings for the target group. The load balancer periodically checks the health of the registered targets using these settings, and only sends traffic to the healthy targets.

Here is what each of these parameters mean:

  • enabled: specifies whether health checks are enabled or disabled. Set to true to enable health checks.
  • interval: specifies the interval, in seconds, between health checks.
  • path: specifies the ping path that the load balancer uses for health checks.
  • port: specifies the port number that the load balancer uses for health checks. Set to "traffic-port" to use the same port as the incoming traffic.
  • protocol: specifies the protocol that the load balancer uses for health checks, such as HTTP or HTTPS.
  • timeout: specifies the amount of time, in seconds, during which no response means a failed health check.
  • healthy_threshold: specifies the number of consecutive successful health checks required to consider a target healthy.
  • unhealthy_threshold: specifies the number of consecutive failed health checks required to consider a target unhealthy.

Let’s break down the code for resource “aws_lb” “application-lb”{} :

  • The first line specifies the resource type and name of the ALB. The name in this case is “nit-alb”.
  • The internal parameter is set to false, meaning the load balancer will be internet-facing.
  • The load_balancer_type parameter is set to "application", indicating that the load balancer will be used to distribute traffic to application servers.
  • The subnets parameter specifies the list of subnets that the load balancer will be deployed in. This list is obtained from the data.aws_subnet_ids.subnet.ids data source.
  • The security_groups parameter specifies the list of security groups associated with the load balancer. In this case, only the security group with the ID aws_security_group.web-server.id is associated with the load balancer.
  • The ip_address_type parameter is set to "ipv4", indicating that the load balancer will use IPv4 addresses.
  • Finally, a tag is added to the load balancer with a key of “name” and a value of “nit-alb”.

When this code is executed, it will create an ALB with the specified settings in the AWS account. The load balancer will be associated with the specified subnets and security group, and will be given a tag with the specified key-value pair.

The aws_lb_listener resource block is creating a new listener for an existing Application Load Balancer. The load_balancer_arn argument specifies the ARN (Amazon Resource Name) of the Application Load Balancer to attach the listener to. The port argument specifies the port that the listener should listen on, which in this case is port 80. The protocol argument specifies the protocol that the listener should use, which in this case is HTTP.

The default_action block specifies what should happen when traffic arrives at the listener. In this case, the type is set to "forward", which means that traffic should be forwarded to the target group specified in the target_group_arn argument. The target_group_arn argument specifies the ARN of the target group that the listener should forward traffic to.

Overall, this code is creating an AWS Application Load Balancer listener that will listen on port 80 and forward incoming traffic to a specified target group.

For `resource “aws_lb_target_group_attachment” “ec2_attach” {}`

Here’s a breakdown of how the code works:

  1. resource "aws_lb_target_group_attachment" "ec2_attach": This creates a new resource of type aws_lb_target_group_attachment with the name ec2_attach.
  2. count = length(aws_instance.web-server): This line sets the count parameter of the resource to the length of the aws_instance.web-server list. This means that one target group attachment resource will be created for each EC2 instance in the list.
  3. target_group_arn = aws_lb_target_group.target-group.arn: This sets the target_group_arn parameter to the ARN of the target group that the instances will be attached to. The aws_lb_target_group resource needs to be defined elsewhere in the Terraform code.
  4. target_id = aws_instance.web-server[count.index].id: This sets the target_id parameter to the ID of the EC2 instance at the current index in the aws_instance.web-server list. The count.index expression refers to the current iteration of the count loop. So, for example, if count is 3, this will set target_id to the ID of the third EC2 instance in the aws_instance.web-server list.

Overall, this code creates a target group attachment resource for each EC2 instance in a list, attaching the instances to a specific target group in AWS.

Also we have created output.tf file

output "elb-dns-name" {
value = aws_lb.application-lb.dns_name
}

This will output our loadbalancer dns address in the console

Now we go to terminal and type

terraform init
# after this
terraform plan
# after this
terraform apply

The deploy is successful you can check by go to the output link and you can also stop one instance and check it if it’s working or not.

Thank you guys here’s my github repo

--

--