In our previous post, we delved into the utilization of the Application Load Balancer (ALB) to enhance the resilience and scalability of a web application by distributing traffic among multiple Availability Zones (AZs) housing EC2 instances.
Building upon that foundation, this post focuses on implementing auto scaling using Terraform to further optimize scalability and ensure the continuous availability of our web application.
Architecture Overview
Before diving into the implementation details, let's take a moment to understand the architecture we'll be working with:
Step 1: Creating the AMI from Existing Template
Auto scaling requires a pre-built Amazon Machine Image (AMI). To facilitate this, we will use a YAML template provided in an AWS workshop and use cloudformation to create AMI. Download the YAML Template here.
Create AMI from above EC2 Instance:
Step 2: Creating 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 3: Creating Linux EC2 Web Server Instances with Auto Scaling Group
Create a launch template using the AMI from Step 1.
####################################################
# Get AMI created earlier
####################################################
data "aws_ami" "amazon-linux-ami" {
most_recent = true
owners = ["self"]
filter {
name = "name"
values = ["CT_Auto_Scaling_Webhost"]
}
}
####################################################
# Create Launch Template Resource
####################################################
resource "aws_launch_template" "aws-launch-template" {
image_id = data.aws_ami.amazon-linux-ami.id
instance_type = var.instance_type
key_name = var.instance_key
vpc_security_group_ids = var.security_group_ec2
update_default_version = true
tag_specifications {
resource_type = "instance"
}
monitoring {
enabled = true
}
}
Create an auto scaling group with a scaling policy, specifically the TargetTrackingScaling with the metric ASGAverageCPUUtilization. Auto scaling will be triggered if ASGAverageCPUUtilization exceeds 20%.
####################################################
# Create auto scaling group
####################################################
resource "aws_autoscaling_group" "aws-autoscaling-group" {
# name = "${var.project_name}-ASG-Group"
vpc_zone_identifier = tolist(var.public_subnets)
desired_capacity = 1
max_size = 4
min_size = 1
launch_template {
id = aws_launch_template.aws-launch-template.id
version = aws_launch_template.aws-launch-template.latest_version
}
}
####################################################
# Create target tracking scaling policy for average CPU utilization
####################################################
resource "aws_autoscaling_policy" "avg_cpu_scaling_policy" {
name = "avg_cpu_scaling_policy"
policy_type = "TargetTrackingScaling"
autoscaling_group_name = aws_autoscaling_group.aws-autoscaling-group.name
target_tracking_configuration {
predefined_metric_specification {
predefined_metric_type = "ASGAverageCPUUtilization"
}
target_value = 20.0
}
estimated_instance_warmup = 180
}
Step 4: Creating an Application Load Balancer
Create an ALB with an attachment to auto scaling 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 = [var.public_subnets[0],var.public_subnets[1] ,var.public_subnets[2],var.public_subnets[3]]
subnets = tolist(var.public_subnets)
enable_deletion_protection = false
}
####################################################
# 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
}
}
####################################################
# attach auto scaling group to Application Load Balancer ALB
####################################################
resource "aws_autoscaling_attachment" "asg_attachment_alb" {
autoscaling_group_name = var.autoscaling_group_id
lb_target_group_arn = aws_lb_target_group.alb_target_group.arn
}
Steps to run Terraform
terraform init
terraform plan
terraform apply -auto-approve
Upon successful completion, Terraform will provide relevant outputs.
Apply complete! Resources: 21 added, 0 changed, 0 destroyed.
Outputs:
alb_dns_name = "tf-lb-20240115192631610100000006-1207062642.us-east-1.elb.amazonaws.com"
Testing the Auto Scaling
Use the ALB DNS name to access the website. As only a single instance is running initially, all requests will be directed to that instance.
Scale out: Induce CPU load to stress the CPU, triggering auto scaling to increase the number of instances.
Auto Scaling Group activity log to achieve maximum state:
Scale in: Reboot EC2 instance with high CPU utilization to trigger scaling in and achieve the desired value.
Instances terminated to achieve desired state:
Auto Scaling Group activity log to achieve desired state:
Cleanup:
Remember to stop AWS components to avoid large bills.
terraform destroy -auto-approve
Congratulations! You have successfully deployed and tested auto scaling for a web server application. In the upcoming module, we will explore Elastic Block Store (EBS) with multi-attach capabilities to further enhance the robustness of our architecture. Happy Coding!
Resources:
Github Link: https://github.com/chinmayto/terraform-aws-linux-webserver-ec2-alb-autoscaling
EC2 Auto Scaling: https://docs.aws.amazon.com/autoscaling/ec2/userguide/what-is-amazon-ec2-auto-scaling.html
Top comments (0)