
Application Load Balancer and EC2 Auto Scaling Group
Tiền đề
- Đã hoàn thành bài thực hành với Application Load Balancer
(Vì một số resource như Taget group, ALB, SG được tạo ở bài trước nên nếu muốn thực hành bài này, đầu tiên phải làm bài Application Load Balancer)
Create Auto Scaling group
Parametter Setting
- Auto Scaling group name:
d-asg-SAA-web-server - Create launch template:
- Template name:
d-lt-saa-web-server-template - Template version description:
web server - AMI:
Amazon Linux 2023 - Instance Type:
t3.micro - Keypair:
d-key-SAA-common - Security Group:
d-sg-SAA-web-server - Storage (volume): Encrypted
- KMS key: (default) aws/ebs
- User data:
- Template name:
#!/bin/bash
# =========================================================
# User Data - Cloud Mentor Pro
# Cai Apache (httpd) + render trang chao mung kem thong tin EC2
# Tu nhan dien AZ va doi mau giao dien theo AZ (demo ALB/ASG)
# Tuong thich: Amazon Linux 2023 (dnf) va Amazon Linux 2 (yum)
# LUU Y: Dung CHUNG 1 file nay cho ca 2 instance / ca 2 AZ.
# Script se tu chon mau dua tren AZ that su cua tung instance.
# =========================================================
exec > /var/log/user-data.log 2>&1
echo ">>> Bat dau chay user-data luc $(date)"
# ---- 1. Cai dat Apache ----
if command -v dnf >/dev/null 2>&1; then
dnf update -y
dnf install -y httpd
else
yum update -y
yum install -y httpd
fi
systemctl enable httpd
systemctl start httpd
# ---- 2. Lay thong tin instance qua IMDSv2 (bat buoc token) ----
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
meta() {
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
"http://169.254.169.254/latest/meta-data/$1"
}
HOSTNAME_VAL=$(meta local-hostname)
LOCAL_IP=$(meta local-ipv4)
PUBLIC_IP=$(meta public-ipv4)
AZ=$(meta placement/availability-zone)
INSTANCE_ID=$(meta instance-id)
if [ -z "$PUBLIC_IP" ]; then
PUBLIC_IP="(khong co Public IP)"
fi
# ---- 2b. Chon mau theo AZ (KHONG can sua tay cho tung instance) ----
# Ky tu cuoi cung cua AZ (a, b, c...) quyet dinh mau accent.
AZ_SUFFIX="${AZ: -1}"
case "$AZ_SUFFIX" in
a)
AZ_COLOR="#32EFB9" # teal
AZ_COLOR_DARK="#0F6E56"
AZ_LABEL_BG="rgba(50,239,185,.1)"
AZ_LABEL_BORDER="rgba(50,239,185,.3)"
;;
b)
AZ_COLOR="#8F87F0" # purple sang hon de doc duoc tren nen toi
AZ_COLOR_DARK="#3C3489"
AZ_LABEL_BG="rgba(143,135,240,.12)"
AZ_LABEL_BORDER="rgba(143,135,240,.35)"
;;
c)
AZ_COLOR="#F0997B" # coral
AZ_COLOR_DARK="#712B13"
AZ_LABEL_BG="rgba(240,153,123,.12)"
AZ_LABEL_BORDER="rgba(240,153,123,.35)"
;;
*)
AZ_COLOR="#B8B3DE" # xam-tim trung tinh, fallback
AZ_COLOR_DARK="#444441"
AZ_LABEL_BG="rgba(184,179,222,.1)"
AZ_LABEL_BORDER="rgba(184,179,222,.3)"
;;
esac
echo ">>> Hostname: $HOSTNAME_VAL | IP: $LOCAL_IP | AZ: $AZ | Mau: $AZ_COLOR | Instance: $INSTANCE_ID"
# ---- 3. Ghi de index.html voi thong tin thuc te + mau theo AZ ----
cat > /var/www/html/index.html << HTMLPAGE
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cloud Mentor Pro — EC2 Instance (${AZ})</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root{
--bg-dark:#151035;
--accent:${AZ_COLOR};
--accent-dark:${AZ_COLOR_DARK};
--accent-bg:${AZ_LABEL_BG};
--accent-border:${AZ_LABEL_BORDER};
--bg-light:#F6F5FB;
--text-dark:#17132E;
--text-muted:#6C6693;
--white:#FFFFFF;
}
*{margin:0;padding:0;box-sizing:border-box;}
body{font-family:'Inter',sans-serif;color:var(--text-dark);background:var(--bg-light);line-height:1.5;}
h1,h2{font-family:'Space Grotesk',sans-serif;}
a{text-decoration:none;}
.topbar{display:flex;justify-content:space-between;align-items:center;max-width:1080px;margin:0 auto;padding:28px 24px 0;}
.logo{display:flex;align-items:center;gap:10px;font-family:'Space Grotesk';font-weight:700;font-size:18px;color:var(--white);}
.logo-mark{width:34px;height:34px;border-radius:9px;background:var(--accent);display:flex;align-items:center;justify-content:center;font-size:16px;}
.badge-outline{font-size:12px;letter-spacing:.06em;color:var(--accent);border:1px solid var(--accent-border);padding:6px 14px;border-radius:99px;font-family:'JetBrains Mono',monospace;}
.hero{background:var(--bg-dark);padding-bottom:60px;}
.hero-content{max-width:720px;margin:0 auto;text-align:center;padding:64px 24px 0;}
.pill{display:inline-flex;align-items:center;gap:8px;background:var(--accent-bg);border:1px solid var(--accent-border);color:var(--accent);font-size:13px;font-family:'JetBrains Mono',monospace;padding:7px 16px;border-radius:99px;margin-bottom:28px;}
.pill-dot{width:7px;height:7px;border-radius:50%;background:var(--accent);box-shadow:0 0 8px var(--accent);}
.hero h1{font-size:56px;color:var(--white);font-weight:700;letter-spacing:-.02em;margin-bottom:18px;}
.hero .subtitle{font-size:18px;color:#B8B3DE;margin-bottom:36px;}
/* Badge AZ to, ro rang - muc dich chinh la de thay ngay khi ALB dao qua lai giua 2 AZ */
.az-badge{display:inline-block;background:var(--accent);color:var(--accent-dark);font-weight:700;font-size:22px;font-family:'JetBrains Mono',monospace;padding:14px 32px;border-radius:12px;letter-spacing:.02em;}
.cta{display:inline-block;background:var(--accent);color:var(--bg-dark);font-weight:600;font-size:15px;padding:14px 30px;border-radius:10px;margin-top:32px;}
.terminal-wrap{max-width:640px;margin:0 auto;padding:0 24px 80px;position:relative;z-index:2;}
.terminal-card{background:#0F0B2A;border-radius:14px;overflow:hidden;border:1px solid rgba(255,255,255,.06);}
.terminal-titlebar{display:flex;align-items:center;gap:8px;padding:13px 16px;background:#181235;border-bottom:1px solid rgba(255,255,255,.06);}
.dot{width:10px;height:10px;border-radius:50%;}
.dot.red{background:#FF5F57;}.dot.yellow{background:#FEBC2E;}.dot.green{background:#28C840;}
.terminal-filename{margin-left:8px;font-family:'JetBrains Mono';font-size:12px;color:#8B87B3;}
.terminal-body{padding:22px 24px 26px;font-family:'JetBrains Mono',monospace;font-size:13.5px;}
.t-line{color:#8B87B3;margin-bottom:4px;}
.t-line .prompt{color:var(--accent);margin-right:8px;}
.t-output{color:var(--white);margin:0 0 16px;padding-left:16px;word-break:break-all;}
.t-output:last-child{margin-bottom:0;}
footer{background:var(--bg-dark);padding:36px 24px;text-align:center;}
footer .logo{justify-content:center;margin-bottom:10px;}
footer p{font-size:13px;color:#8B87B3;}
@media (max-width:640px){
.hero h1{font-size:38px;}
.az-badge{font-size:16px;padding:10px 20px;}
}
</style>
</head>
<body>
<div class="hero">
<div class="topbar">
<div class="logo"><span class="logo-mark">☁</span> Cloud Mentor Pro</div>
<span class="badge-outline">AWS CERTIFIED TRAINING</span>
</div>
<div class="hero-content">
<span class="pill"><span class="pill-dot"></span> EC2 INSTANCE ĐANG HOẠT ĐỘNG</span>
<h1>Cloud Mentor Pro</h1>
<p class="subtitle">Lab: High Availability & Scalability</p>
<div class="az-badge">${AZ}</div>
</div>
</div>
<div class="terminal-wrap" id="info">
<div class="terminal-card">
<div class="terminal-titlebar">
<span class="dot red"></span><span class="dot yellow"></span><span class="dot green"></span>
<span class="terminal-filename">ec2-instance-metadata</span>
</div>
<div class="terminal-body">
<div class="t-line"><span class="prompt">\$</span>curl metadata/hostname</div>
<div class="t-output">${HOSTNAME_VAL}</div>
<div class="t-line"><span class="prompt">\$</span>curl metadata/local-ipv4</div>
<div class="t-output">${LOCAL_IP}</div>
<div class="t-line"><span class="prompt">\$</span>curl metadata/placement/availability-zone</div>
<div class="t-output">${AZ}</div>
<div class="t-line"><span class="prompt">\$</span>curl metadata/instance-id</div>
<div class="t-output">${INSTANCE_ID}</div>
</div>
</div>
</div>
<footer>
<div class="logo"><span class="logo-mark">☁</span> Cloud Mentor Pro</div>
<p>Được phục vụ bởi Apache trên Amazon EC2 · ${AZ}</p>
</footer>
</body>
</html>
HTMLPAGE
# ---- 4. Phan quyen va restart Apache ----
chown apache:apache /var/www/html/index.html 2>/dev/null || chown www-data:www-data /var/www/html/index.html 2>/dev/null
chmod 644 /var/www/html/index.html
systemctl restart httpd
echo ">>> Hoan tat luc $(date)"
- Network mapping:
- VPC:
Chọn default VPC - AZ: Chọn
us-east-1avàus-east-1b
- VPC:
- Load balancer
- Attach to an existing load balancer
- Chọn target group đã tạo
- Health check elb
- Desered:
1 - Scaling
- Min:
1 - Max:
3 - Automatic scaling - optional:
Target tracking scaling policy
- Min:
Create Auto Scaling group

Create launch template





Advanced details

Create ASG
Step1: Choose launch template

Step2: Choose instance launch options

Step 3: Integrate with other services - optional


Step 4: Configure group size and scaling - optional


Step 5: Add notifications - optional

Step 6: Add tags - optional

Step 7: Review and create ASG
Kết quả

Confirm TG (đợi đến khi EC2 khởi động hoàn toàn thì health check sẽ báo là Healthy)

Access DNS của ALB để check kết quả

Stress test
Sau khi có Target Tracking Policy, thì chỉ khi nào CPU vượt lên 50% thì ASG mới Scale out EC2. Chúng ta sẽ manual thực hiện stress test.
Để có thể Connect đến EC2 thông qua ssh, chúng ta cần modify SG của EC2
Edit SG: d-sg-SAA-web-server, Add Inbound rule
| Type | Protocol | Port range | Source |
|---|---|---|---|
| HTTP | TCP | 80 | Security group of ALB |
| SSH | TCP | 22 | 0.0.0.0/0 |
Connect to EC2 and run command:
sudo yum install stress -y
sudo stress -c 4
Chúng ta cần đợi 5 - 10p để ASG collect Metrics

Khi CPU vượt ngưỡng 50%, EC2 sẽ được tạo thêm theo như scaling policy

Confirm ALB đã có thể Load balancer giữa 2 Instance

Clean up
- Delete ASG:
d-asg-SAA-web-server - Delete Launch Template:
d-lt-saa-web-server-template - Delete ALB:
d-alb-SAA-web-alb - Delete Taget Group:
d-tg-SAA-web-server
Sau khi 2 EC2 đã ở trạng thái Terminated
- Delete Security Groups (lưu ý theo thứ tự)
- d-sg-SAA-web-server
- d-sg-SAA-alb

