Một EC2 instance chạy được, nhưng khi nó chết giữa đêm và traffic gấp 3 ngày Black Friday, bạn cần ASG + ALB. Incident $120K DDoS: ASG không set max capacity, attacker spin up 360 m5.24xlarge trong 72 giờ.
ASG + ALB là cặp bài trùng: ALB phân phối traffic, ASG đảm bảo đúng số lượng instance healthy.
flowchart LR
User["User"] --> ALB["ALB<br/>HTTPS listener"]
ALB --> TG["Target Group<br/>health check /health"]
TG --> ASG["ASG<br/>min=2 · desired=3 · max=10"]
ASG --> I1["i-001 (healthy)"]
ASG --> I2["i-002 (healthy)"]
ASG --> I3["i-003 (healthy)"]
CW["CloudWatch: CPU > 60%"] -->|"scale-out +1"| ASG
ASG: 3 con số quyết định chi phí
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name myapp-asg \
--launch-template LaunchTemplateName=myapp-template,Version='$Latest' \
--vpc-zone-identifier "subnet-a,subnet-b,subnet-c" \
--min-size 2 --max-size 10 --desired-capacity 3 \
--health-check-type ELB --health-check-grace-period 300 \
--target-group-arns $TG_ARN
| Parameter | Ý nghĩa | Sai lầm |
|---|---|---|
min-size | Số instance tối thiểu | Set = 0 → app offline khi scale-in |
max-size | Giới hạn chi phí | Set quá cao/không set → $120K bill |
desired-capacity | Số instance mục tiêu | Set thấp → không handle được spike |
Target tracking (recommended)
aws autoscaling put-scaling-policy --auto-scaling-group-name myapp-asg \
--policy-name cpu60 --policy-type TargetTrackingScaling \
--target-tracking-configuration '{
"PredefinedMetricSpecification": {"PredefinedMetricType": "ASGAverageCPUUtilization"},
"TargetValue": 60,
"ScaleInCooldown": 300, "ScaleOutCooldown": 60
}'
Target CPU 50-60%, không phải 80%. 80% không đủ buffer cho spike — instance mới cần 2-5 phút launch.
ALB: routing layer 7
aws elbv2 create-load-balancer --name myapp-alb --scheme internet-facing --type application \
--subnets subnet-public-a subnet-public-b --security-groups sg-alb
aws elbv2 create-listener --load-balancer-arn $ALB_ARN --protocol HTTPS --port 443 \
--certificates CertificateArn=$ACM_ARN \
--default-actions Type=forward,TargetGroupArn=$TG_ARN
# Path-based routing
aws elbv2 create-rule --listener-arn $LISTENER_ARN --priority 10 \
--conditions Field=path-pattern,Values='/api/*' \
--actions Type=forward,TargetGroupArn=$BACKEND_TG
Health check đúng: kiểm tra dependency
app.get("/health", async (req, res) => {
const checks = {
db: await db
.raw("SELECT 1")
.then(() => "ok")
.catch(() => "fail"),
redis: await redis
.ping()
.then(() => "ok")
.catch(() => "fail"),
uptime: process.uptime(),
};
const healthy = Object.values(checks).every((v) => v === "ok");
res.status(healthy ? 200 : 503).json(checks);
});
Mình từng thấy team set max-size quá cao và nhận bill $120K. ASG max capacity là firewall chi phí, set thấp hơn khả năng tài chính.
- Target tracking CPU 50-60% — buffer cho spike, instance mới cần 2-5 phút
- Health check kiểm tra dependency (DB, Redis) — không chỉ return 200
- ALB rules path-based + host-based — routing linh hoạt
Bài sau: Phần 10: Lambda cơ bản — serverless từ dòng code đầu tiên