Fix AWS ALB 503 Service Unavailable: Không có Target nào khỏe mạnh trong Target Group

intermediate☁️ AWS2026-03-21| AWS Application Load Balancer (ALB), EC2, ECS, Target Groups — tất cả regions

Error Message

503 Service Temporarily Unavailable - No healthy upstream
#alb#ec2#health-check#load-balancer#target-group

Lỗi Gặp Phải

ALB của bạn đang chạy. Các EC2 instance cũng đang hoạt động. Nhưng mọi request đều trả về:

503 Service Temporarily Unavailable - No healthy upstream

ALB không có target nào healthy trong Target Group. Mọi target đều đang fail health check, đang draining, hoặc không tồn tại. Không có nơi nào để gửi traffic đến.

Nguyên Nhân

ALB kiểm tra từng target theo chu kỳ cố định dựa trên cài đặt health check của bạn. Fail N lần liên tiếp, target sẽ bị đánh dấu unhealthy — không nhận traffic nữa. Các nguyên nhân thường gặp:

  • App server bị crash hoặc chưa khởi động
  • Health check path trả về mã không phải 2xx (app trả về 404 hoặc 500 tại /health)
  • Security group chặn ALB kết nối đến instance trên port health check
  • Port cấu hình sai trong Target Group (app lắng nghe cổng 8080, nhưng TG lại cấu hình cổng 80)
  • Instance vừa khởi động và chưa vượt qua ngưỡng healthy threshold
  • Target Group trống — không có instance nào được đăng ký

Bước 1: Kiểm Tra Trạng Thái Health của Target

Bắt đầu từ đây. AWS CLI sẽ cho bạn biết chính xác ALB đang đánh giá từng target như thế nào:

# Thay bằng ARN Target Group của bạn
aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:ap-northeast-1:123456789:targetgroup/my-tg/abc123

Ví dụ output:

{
  "TargetHealthDescriptions": [
    {
      "Target": { "Id": "i-0abc123def456", "Port": 80 },
      "TargetHealth": {
        "State": "unhealthy",
        "Reason": "Target.FailedHealthChecks",
        "Description": "Health checks failed with these codes: [502]"
      }
    }
  ]
}

Trường Reason là manh mối đầu tiên của bạn. Các giá trị thường gặp:

  • Target.FailedHealthChecks — app đang trả về mã status lỗi
  • Target.Timeout — không có phản hồi trong khoảng thời gian timeout
  • Target.NotRegistered — instance không có trong Target Group
  • Elb.InitialHealthChecking — đang khởi động, chờ thêm 30–60 giây
  • Target.DeregistrationInProgress — đang trong quá trình draining, hãy chờ

Bước 2: Kiểm Tra Security Group

Đây là thứ hay làm khổ người ta lúc 2 giờ sáng. ALB cần có đường đi thông suốt đến các instance trên port health check — và security group là rào cản phổ biến nhất.

# Lấy security group gắn với instance của bạn
aws ec2 describe-instances --instance-ids i-0abc123def456 \
  --query 'Reservations[].Instances[].SecurityGroups'

# Kiểm tra inbound rules của security group đó
aws ec2 describe-security-groups --group-ids sg-0123456789 \
  --query 'SecurityGroups[].IpPermissions'

Security group của instance phải cho phép inbound traffic từ security group của ALB trên port health check — TCP 80, 443, hoặc port mà app của bạn đang dùng. Nếu bạn chỉ thấy rule 0.0.0.0/0 hoặc không có rule nào tham chiếu đến ALB SG, thì đây là vấn đề rồi.

Sửa bằng CLI:

aws ec2 authorize-security-group-ingress \
  --group-id sg-INSTANCE_SG \
  --protocol tcp \
  --port 80 \
  --source-group sg-ALB_SG

Hoặc trên console: EC2 → Security Groups → SG của instance → Inbound rules → Add rule → Custom TCP, port 80, Source = ID security group của ALB.

Bước 3: Kiểm Tra Trực Tiếp Endpoint Health Check

SSH vào và curl đúng URL mà ALB đang probe:

ssh ec2-user@your-instance-ip

# Kiểm tra endpoint health check
curl -v http://localhost:80/health

# Nếu app chạy trên port khác
curl -v http://localhost:8080/health

Phản hồi phải trả về HTTP 200 — hoặc mã thành công nào bạn đã cấu hình trong Target Group. Nhận được 404? Sai đường dẫn. Nhận được 500? App đang bị lỗi. Request bị treo? App không lắng nghe trên port đó.

Xác nhận xem port nào đang thực sự lắng nghe:

ss -tlnp | grep LISTEN
# hoặc
netstat -tlnp

Bước 4: Kiểm Tra Cài Đặt Health Check Trong Target Group

Cấu hình health check sai là nguyên nhân khó phát hiện — đặc biệt khi ai đó chỉnh sửa TG mà không cập nhật lại app. Kiểm tra bằng CLI:

aws elbv2 describe-target-groups \
  --target-group-arns arn:aws:elasticloadbalancing:...

Đối chiếu các thông số này với hành vi thực tế của app:

  • Protocol: HTTP hoặc HTTPS — phải khớp với giao thức app đang phục vụ
  • Port: phải khớp với port app đang lắng nghe
  • Path: ví dụ /health hoặc /ping — phải trả về mã 2xx
  • Healthy threshold: số lần thành công liên tiếp để chuyển sang healthy (mặc định: 5)
  • Unhealthy threshold: số lần thất bại liên tiếp trước khi bị đánh dấu unhealthy (mặc định: 2)
  • Timeout: số giây ALB chờ phản hồi (mặc định: 5s)
  • Interval: tần suất probe (mặc định: 30s)

Khi tải cao, app đôi khi mất 6–8 giây để phản hồi health check. Nếu timeout là 5s, mọi probe đều timeout và target cứ ở trạng thái unhealthy. Hãy tăng timeout lên. Để phục hồi nhanh hơn, giảm interval xuống 10–15s và healthy threshold xuống 2.

aws elbv2 modify-target-group \
  --target-group-arn arn:aws:elasticloadbalancing:... \
  --health-check-path /health \
  --health-check-interval-seconds 15 \
  --healthy-threshold-count 2 \
  --unhealthy-threshold-count 3 \
  --health-check-timeout-seconds 10

Bước 5: Kiểm Tra Các Target Đã Đăng Ký

Đáng để xác nhận điều hiển nhiên — liệu có instance nào thực sự được đăng ký không?

aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:... \
  --query 'TargetHealthDescriptions[].Target'

Danh sách trống? Hãy đăng ký instance của bạn:

aws elbv2 register-targets \
  --target-group-arn arn:aws:elasticloadbalancing:... \
  --targets Id=i-0abc123def456,Port=80

Xác Nhận Đã Khắc Phục

Sau khi thực hiện thay đổi, hãy theo dõi liên tục trạng thái target health cho đến khi thấy nó chuyển sang healthy:

# Kiểm tra mỗi 10 giây
watch -n 10 'aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:... \
  --query "TargetHealthDescriptions[].TargetHealth"'

Ngay khi thấy "State": "healthy" với ít nhất một target, hãy test ALB:

curl -I https://your-alb-dns-name.ap-northeast-1.elb.amazonaws.com/
# Kết quả mong đợi: HTTP/1.1 200 OK

Mẹo Hữu Ích

  • ALB Access Logs: Bật trong thuộc tính ALB. Mỗi dòng log đều chứa mã phản hồi của target — vô cùng hữu ích khi bạn đang truy tìm lỗi 503 xuất hiện lẻ tẻ và biến mất trước khi kịp SSH vào.
  • CloudWatch alarms: Tạo alarm cho HealthyHostCount < 1 trong metric của Target Group. Bạn cần biết về vấn đề này trước khi người dùng phát hiện ra.
  • Auto Scaling Groups: Đảm bảo ASG được gắn đúng Target Group. Cũng cần kiểm tra rằng instance vượt qua health check trước khi hết thời gian warmup — warmup 300 giây với interval 30 giây nghĩa là 10 lần probe trước khi traffic được chuyển đến.
  • ECS services: Container phải expose đúng port và vượt qua container health check của chính nó trước. ALB sẽ không route đến task mà ECS đánh giá là unhealthy.
  • Rolling deploys: Nếu tất cả instance cũ cùng draining một lúc, bạn có thể gặp lỗi 503 trong thời gian ngắn. Hãy chia nhỏ các lần deploy hoặc đặt minimum healthy percentage là 100% để tránh tình huống này.

Related Error Notes