DEV Community

Cover image for Getting Started with AWS and Terraform: Optimizing Web Application Scalability with Auto Scaling and Terraform
Chinmay Tonape
Chinmay Tonape

Posted on • Edited on

Getting Started with AWS and Terraform: Optimizing Web Application Scalability with Auto Scaling and Terraform

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:

EC2 Auto Scaling Architecture

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 CloudFormation Stack

Execute CloudFormation Stack

Running EC2 Instance

Create AMI from above EC2 Instance:

AMI Created

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

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

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

Steps to run Terraform

terraform init terraform plan terraform apply -auto-approve 
Enter fullscreen mode Exit fullscreen mode

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

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.

Desired EC2 Instances

Desired EC2 - Web page

Scale out: Induce CPU load to stress the CPU, triggering auto scaling to increase the number of instances.

Stress CPU

Scaled out instances

2nd EC2

3rd EC2

4th EC2

Auto Scaling Group activity log to achieve maximum state:

ASG Scale out log

Scale in: Reboot EC2 instance with high CPU utilization to trigger scaling in and achieve the desired value.

Reboot Induced EC2

Instances terminated to achieve desired state:
Scaling out

Only EC2

Auto Scaling Group activity log to achieve desired state:

ASG Scale in log

Cleanup:

Remember to stop AWS components to avoid large bills.

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

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)