
Application Load Balancer
I. Create Security Group
1. Create ALB Security Group
- Name:
d-sg-SAA-alb - Description:
Allow http from internet - VPC:
default VPC - Inboud rule and Outbound rule như hình
- Tag (Key:
Name, Value:d-sg-SAA-alb)
2. Create Web server Security Group
- Name:
d-sg-SAA-web-server - Description:
Allow http from ALB - VPC:
default VPC - Inboud rule and Outbound rule như hình
- Tag (Key:
Name, Value:d-sg-SAA-web-server)
II. Create EC2
Để test Load balancing chúng ta sẽ tạo 2 EC2 ở 2 AZ khác nhau như bên dưới:
d-ec2-SAA-web-server-01
- Name:
d-ec2-SAA-web-server-01 - OS: Default (Amazon Linux 2023)
- Instance type: Default (t3.micro)
- Key pair: Create new keypair with name: d-key-SAA-common
- Network Setting:
- VPC: Default
- Subnet:
us-east-1a - Auto-assign public IP:
Enable - Select existing security group:
d-sg-SAA-web-server
- Advanced details (User data)
#!/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)"
d-ec2-SAA-web-server-02
- Name:
d-ec2-SAA-web-server-02 - OS: Default (Amazon Linux 2023)
- Instance type: Default (t3.micro)
- Key pair: Create new keypair with name: d-key-SAA-common
- Network Setting:
- VPC: Default
- Subnet:
us-east-1b - Auto-assign public IP:
Enable - Select existing security group:
d-sg-SAA-web-server
- Advanced details (User data)
#!/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)"
Lưu ý ở đây chúng ta không thể connect đến EC2, cũng không thể access http đến địa chỉ public của EC2 được. Vì chúng ra sẽ dùng ALB để access đến EC2, nhưng nếu các bạn muốn connect đến EC2 hoặc access http://{Public-IP} thì các bạn thêm Inboud Rule cho Security group là được
III. Create Taget Group
Vào EC2 Console -> Taget Group -> Nhấn Create taget group
- Choose a target type:
Instances - Target group name:
d-tg-SAA-web-server - Protocol:
HTTP - Port:
80 - VPC: Chọn default VPC
- Tag: Key:
NameValue:d-tg-SAA-web-server - Các setting khác để như default


- Nhấn Next
- Đăng ký EC2 vào Taget group:
- Tại đây chúng ta sẽ add 2 Instance đã tạo lúc nãy vào Tagets, Check chọn 2 Instance và Nhấn nút Include as pending below

- Review và Create taget group

IV. Create ELB
Vào EC2 Console -> Load Balancers -> Nhấn Create load balancer
- Chọn create Application Load Balancer
- Load balancer name:
d-alb-SAA-web-alb - Scheme:
Internet-facing - IP address type:
IPv4 - Network mapping
- VPC: Chọn
default VPC - Mappings: Chọn
us-east-1avàus-east-1b - Security groups:
d-sg-SAA-alb
- VPC: Chọn
- Listeners and routing
- Protocol:
HTTP - Port:
80 - Default action: Chọn Taget group
d-tg-SAA-web-server
- Protocol:

Sau khi Tạo ALB xong, bạn đợi 1 chút thì sẽ thấy Health status ở Taget group -> healthy
Check ALB
Vào giao diện Load Balancer -> copy DNS name

Access từ browser

Reload page vài lần để check cân bằng tải

Clean up
Để tiếp tục làm bài thực hành với EC2 Auto Scaling group, chúng ta sẽ giữ lại Taget Ggroup và ALB, chỉ Terminated 2 EC2.
Nếu dừng lại ở đây chúng ta sẽ thực hiện:
- Terminated 2 EC2:
d-ec2-SAA-web-server-01vàd-ec2-SAA-web-server-02 - Delete ALB:
d-alb-SAA-web-alb - Delete Taget Group:
d-tg-SAA-web-server - Delete SG:
d-sg-SAA-web-server - Delete SG:
d-sg-SAA-alb





