Ash-Docs
High Availability Architectures

Real-Time Elastic Scaling with ALB & Auto Scaling

Deploy a dynamic, self-healing, and elastic web tier on AWS. In this production lab, we configure an Application Load Balancer (ALB), an isolated Target Group, and an Auto Scaling Group (ASG) using Ubuntu 24.04/22.04 LTS instances running automated IMDSv2 metadata ingestion.


0 Required Prerequisites & Architecture Components

Verify that your AWS environment satisfies the architectural baseline before provisioning.

Multi-AZ VPC

2+ Public Subnets

Ubuntu LTS

24.04 or 22.04 AMI

IMDSv2

Session Tokens

Auto Scaling

Capacity 1 to 4

1 Security Architecture & Group Isolation

Follow the principle of defense-in-depth: the Load Balancer is exposed to public HTTP traffic, but the Auto Scaling backend instances accept requests exclusively from the ALB security group.

Security Group Configurations
Security Group Port Source Purpose
alb-sg 80 (HTTP) 0.0.0.0/0 Accept public incoming client traffic
ec2-instance-sg 80 (HTTP) alb-sg (Group ID) Strict ingress restriction to ALB forwarding only

Architecture Tip

Never open port 80 directly to 0.0.0.0/0 on backend EC2 instances. Restricting the source to alb-sg prevents clients from bypassing load balancing and security policies.

2 Provisioning the Target Group (TG)

The Target Group routes requests to the pool of healthy EC2 instances dynamically managed by Auto Scaling.

Target Group Parameter Checklist
  1. Navigate to EC2 Console > Target Groups > Create target group.
  2. Set Target type to Instances.
  3. Name the group: ubuntu-web-tg.
  4. Set Protocol to HTTP and Port to 80.
  5. Set Health check path to / with Protocol HTTP.
  6. Click Next and do not manually register targets—the Auto Scaling Group will attach and detach targets dynamically.

3 Configuring the Application Load Balancer (ALB)

Provision the internet-facing entry point across multiple Availability Zones for high availability.

  1. Navigate to EC2 Console > Load Balancers > Create load balancer.
  2. Select Application Load Balancer (ALB).
  3. Name: ubuntu-demo-alb.
  4. Scheme: Internet-facing | IP address type: IPv4.
  5. Network Mapping: Select your VPC and check at least 2 Availability Zones and their public subnets.
  6. Security Groups: Select alb-sg (remove the default group).
  7. Listeners and Routing: Listener HTTP:80 forward to ubuntu-web-tg.
  8. Click Create load balancer.

4 Launch Template & Converted Ubuntu User Data

Create the template blueprint used by Auto Scaling. It includes the converted Ubuntu bootstrap script that retrieves runtime metadata (Instance ID, Type, AZ) via IMDSv2 and renders the status dashboard[cite: 1].

Launch Template Configuration:

  • • Template Name: ubuntu-web-lt
  • • AMI: Ubuntu Server 24.04 LTS or 22.04 LTS (HVM, SSD Volume Type)
  • • Instance Type: t2.micro or t3.micro
  • • Security Group: ec2-instance-sg
  • • Advanced Details > Metadata Version: V2 only (token required)
User Data Script (Ubuntu APT / Apache2)
#!/bin/bash
sudo apt-get update -y
sudo apt-get install -y apache2 git curl
export TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
export META_INST_ID=`curl http://169.254.169.254/latest/meta-data/instance-id -H "X-aws-ec2-metadata-token: $TOKEN"`
export META_INST_TYPE=`curl http://169.254.169.254/latest/meta-data/instance-type -H "X-aws-ec2-metadata-token: $TOKEN"`
export META_INST_AZ=`curl http://169.254.169.254/latest/meta-data/placement/availability-zone -H "X-aws-ec2-metadata-token: $TOKEN"`
cd /var/www/html
echo "<!DOCTYPE html>" > index.html
echo "<html lang=\"en\">" >> index.html
echo "<head>" >> index.html
echo "    <meta charset=\"UTF-8\">" >> index.html
echo "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">" >> index.html
echo "    <style>" >> index.html
echo "        @import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');" >> index.html
echo "        html {" >> index.html
echo "            position: relative;" >> index.html
echo "            overflow-x: hidden !important;" >> index.html
echo "        }" >> index.html
echo "        * {" >> index.html
echo "            box-sizing: border-box;" >> index.html
echo "        }" >> index.html
echo "        body {" >> index.html
echo "            font-family: 'Open Sans', sans-serif;" >> index.html
echo "            color: #324e63;" >> index.html
echo "        }" >> index.html
echo "        .wrapper {" >> index.html
echo "            width: 100%;" >> index.html
echo "            height: auto;" >> index.html
echo "            min-height: 90vh;" >> index.html
echo "            padding: 50px 20px;" >> index.html
echo "            padding-top: 100px;" >> index.html
echo "            display: flex;" >> index.html
echo "        }" >> index.html
echo "        .instance-card {" >> index.html
echo "            width: 100%;" >> index.html
echo "            min-height: 380px;" >> index.html
echo "            margin: auto;" >> index.html
echo "            box-shadow: 12px 12px 2px 1px rgba(13, 28, 39, 0.4);" >> index.html
echo "            background: #fff;" >> index.html
echo "            border-radius: 15px;" >> index.html
echo "            border-width: 1px;" >> index.html
echo "            max-width: 500px;" >> index.html
echo "            position: relative;" >> index.html
echo "            border: thin groove #9c83ff;" >> index.html
echo "        }" >> index.html
echo "        .instance-card__cnt {" >> index.html
echo "            margin-top: 35px;" >> index.html
echo "            text-align: center;" >> index.html
echo "            padding: 0 20px;" >> index.html
echo "            padding-bottom: 40px;" >> index.html
echo "            transition: all .3s;" >> index.html
echo "        }" >> index.html
echo "        .instance-card__name {" >> index.html
echo "            font-weight: 700;" >> index.html
echo "            font-size: 24px;" >> index.html
echo "            color: #6944ff;" >> index.html
echo "            margin-bottom: 15px;" >> index.html
echo "        }" >> index.html
echo "        .instance-card-inf__item {" >> index.html
echo "            padding: 10px 35px;" >> index.html
echo "            min-width: 150px;" >> index.html
echo "        }" >> index.html
echo "        .instance-card-inf__title {" >> index.html
echo "            font-weight: 700;" >> index.html
echo "            font-size: 27px;" >> index.html
echo "            color: #324e63;" >> index.html
echo "        }" >> index.html
echo "        .instance-card-inf__txt {" >> index.html
echo "            font-weight: 500;" >> index.html
echo "            margin-top: 7px;" >> index.html
echo "        }" >> index.html
echo "    </style>" >> index.html
echo "    <title>Amazon EC2 Status</title>" >> index.html
echo "</head>" >> index.html
echo "<body>" >> index.html
echo "    <div class=\"wrapper\">" >> index.html
echo "        <div class=\"instance-card\">" >> index.html
echo "            <div class=\"instance-card__cnt\">" >> index.html
echo "                <div class=\"instance-card__name\">Your EC2 Instance is running!</div>" >> index.html
echo "                <div class=\"instance-card-inf\">" >> index.html
echo "                    <div class=\"instance-card-inf__item\">" >> index.html
echo "                        <div class=\"instance-card-inf__txt\">Instance Id</div>" >> index.html
echo "                        <div class=\"instance-card-inf__title\">" $META_INST_ID "</div>" >> index.html
echo "                    </div>" >> index.html
echo "                    <div class=\"instance-card-inf__item\">" >> index.html
echo "                        <div class=\"instance-card-inf__txt\">Instance Type</div>" >> index.html
echo "                        <div class=\"instance-card-inf__title\">" $META_INST_TYPE "</div>" >> index.html
echo "                    </div>" >> index.html
echo "                    <div class=\"instance-card-inf__item\">" >> index.html
echo "                        <div class=\"instance-card-inf__txt\">Availability zone</div>" >> index.html
echo "                        <div class=\"instance-card-inf__title\">" $META_INST_AZ "</div>" >> index.html
echo "                    </div>" >> index.html
echo "                </div>" >> index.html
echo "            </div>" >> index.html
echo "        </div>" >> index.html
echo "</body>" >> index.html
echo "</html>" >> index.html
sudo systemctl enable apache2
sudo systemctl restart apache2

5 Auto Scaling Group (ASG) Deployment

Bind the Launch Template, the Target Group, and your scaling policies together.

Auto Scaling Group Parameters
  1. Navigate to EC2 Console > Auto Scaling Groups > Create Auto Scaling group.
  2. Name: ubuntu-web-asg. Select template: ubuntu-web-lt.
  3. Network: Select your VPC and at least two subnets across different Availability Zones.
  4. Load Balancing: Choose Attach to an existing load balancer and select ubuntu-web-tg.
  5. Health Checks: Enable both EC2 and Elastic Load Balancing (ELB) checks.
  6. Group Size: Set Desired: 2, Minimum: 1, Maximum: 4.
  7. Scaling Policy: Add a Target tracking scaling policy targeting 50% Average CPU Utilization.

6 Live Verification & Load Distribution

  1. Navigate to Target Groups > ubuntu-web-tg > Targets and confirm instances show Healthy.
  2. Navigate to Load Balancers > ubuntu-demo-alb and copy the DNS name.
  3. Open the DNS name in a web browser.
  4. Refresh the browser window repeatedly the Instance ID and Availability Zone will rotate as the ALB balances traffic across the fleet!

🎉 Elastic Infrastructure Deployed!

Your high-availability web cluster with automated load distribution is active and scalable.

Thanvir Assif

Created by Thanvir Assif

Cloud & DevOps Engineer | AWS Certified | Full Stack Developer. Helping professionals and enthusiasts master cloud deployments.

© 2026 Thanvir Assif. All rights reserved.