Auto Scaling Group Health Check: Tại Sao Instance Bị Terminate Dù Đang Chạy Bình Thường?

Bạn nhìn vào console và thấy ASG liên tục terminate instance — nhưng instance đó rõ ràng đang chạy, SSH được, log không có lỗi. Đây là một trong những tình huống gây bối rối nhất khi vận hành Auto Scaling Group health check, và nguyên nhân thường không nằm ở chỗ bạn đang tìm.

TL;DR — Auto Scaling Group Health Check

Tình huốngHealth Check nên dùngLưu ý quan trọng
ASG không gắn Load BalancerEC2Chỉ kiểm tra trạng thái hypervisor
ASG gắn ALB/NLB, app có thể trả lỗiELBPhải enable ELB health check trên Target Group
Instance bị terminate dù EC2 status 'running'Kiểm tra Grace Period trướcGrace Period quá ngắn là nguyên nhân phổ biến nhất
Instance healthy trên TG nhưng ASG terminateXác nhận health check type đã set ELBDefault vẫn là EC2 dù có attach TG

Cơ Chế Hoạt Động Của ASG Health Check

ASG không tự kiểm tra ứng dụng của bạn. Nó chỉ hỏi nguồn dữ liệu bên ngoài: 'Instance này có healthy không?' rồi hành động dựa trên câu trả lời đó. Nguồn dữ liệu đó chính là health check type bạn cấu hình.

graph TD ASG["Auto Scaling Group"] HCType{"Health Check Type?"} EC2Check["EC2 Service Instance running? Status checks OK?"] ELBCheck["Target Group App responding? HTTP 200?"] CustomCheck["External System set-instance-health API"] Healthy["Instance: HEALTHY No action"] Unhealthy["Instance: UNHEALTHY Terminate + Replace"] ASG --> HCType HCType -- "EC2 (default)" --> EC2Check HCType -- "ELB" --> ELBCheck HCType -- "Custom" --> CustomCheck EC2Check -- "Pass" --> Healthy EC2Check -- "Fail" --> Unhealthy ELBCheck -- "Pass" --> Healthy ELBCheck -- "Fail" --> Unhealthy CustomCheck -- "Healthy" --> Healthy CustomCheck -- "Unhealthy" --> Unhealthy
  1. EC2 health check: ASG hỏi EC2 service — instance có ở trạng thái running và vượt qua system/instance status checks không? Đây là mức hypervisor, không biết gì về ứng dụng bên trong.
  2. ELB health check: ASG hỏi Target Group — load balancer có đang nhận response hợp lệ từ instance không? Đây mới là mức ứng dụng.
  3. Custom health check: Hệ thống bên ngoài (ví dụ: script monitoring) gọi API set-instance-health để đánh dấu instance là Unhealthy.

Khi ASG xác định một instance là unhealthy, nó sẽ terminate instance đó và launch instance thay thế — bất kể bạn thấy gì trên console EC2.

Giống như bảo vệ tòa nhà chỉ kiểm tra thẻ từ mà không kiểm tra mặt người — EC2 health check xác nhận 'máy đang bật' nhưng không biết 'ứng dụng có phục vụ được không'.

Tại Sao Instance 'Running' Vẫn Bị Terminate — Chẩn Đoán Từng Lớp

Bước 1: Xác nhận lý do terminate thực sự từ Activity History

Trước khi thay đổi bất cứ thứ gì, đọc activity history của ASG. Đây là nguồn sự thật duy nhất — nó ghi lại chính xác lý do ASG terminate instance. Nhiều người bỏ qua bước này và đi thẳng vào thay đổi cấu hình, dẫn đến fix sai vấn đề.

aws autoscaling describe-scaling-activities \
  --auto-scaling-group-name my-asg \
  --max-items 20 \
  --query 'Activities[?StatusCode==`Failed` || contains(Description, `Terminating`)].[ActivityId,Description,StatusMessage,StartTime]' \
  --output table

Tìm các dòng có nội dung như Instance failed ELB health check, Instance failed EC2 health check, hoặc Received instance health check result: Unhealthy. Nếu thấy custom health check — có hệ thống bên ngoài đang gọi set-instance-health.

Bước 2: Kiểm tra Health Check Grace Period

Đây là nguyên nhân phổ biến nhất bị bỏ qua. Grace period là khoảng thời gian ASG chờ sau khi instance launch trước khi bắt đầu kiểm tra health. Nếu grace period quá ngắn, ASG sẽ kiểm tra instance khi ứng dụng chưa kịp khởi động — instance bị đánh dấu unhealthy và terminate ngay lập tức.

aws autoscaling describe-auto-scaling-groups \
  --auto-scaling-group-names my-asg \
  --query 'AutoScalingGroups[0].{HealthCheckType:HealthCheckType,HealthCheckGracePeriod:HealthCheckGracePeriod}' \
  --output json

Nếu HealthCheckGracePeriod0 hoặc một giá trị nhỏ hơn thời gian khởi động thực tế của ứng dụng, đây chính là vấn đề. Cập nhật grace period để đủ thời gian cho ứng dụng warm up:

aws autoscaling update-auto-scaling-group \
  --auto-scaling-group-name my-asg \
  --health-check-grace-period 300

Bước 3: Kiểm tra Health Check Type hiện tại

Nếu grace period đã hợp lý mà vẫn bị terminate, kiểm tra health check type. Một điểm quan trọng: ASG mặc định dùng EC2 health check kể cả khi bạn đã attach Target Group. Việc attach TG không tự động chuyển health check type sang ELB.

aws autoscaling describe-auto-scaling-groups \
  --auto-scaling-group-names my-asg \
  --query 'AutoScalingGroups[0].{HealthCheckType:HealthCheckType,HealthCheckGracePeriod:HealthCheckGracePeriod,TargetGroupARNs:TargetGroupARNs}' \
  --output json

Bước 4: Kiểm tra trạng thái instance trên Target Group

Nếu health check type là ELB mà instance vẫn bị terminate, vấn đề nằm ở Target Group health check — ứng dụng không trả về response mà TG mong đợi. Kiểm tra trực tiếp trạng thái instance trên TG để thấy lý do cụ thể.

aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/my-tg/1234567890abcdef \
  --query 'TargetHealthDescriptions[*].{Id:Target.Id,Port:Target.Port,State:TargetHealth.State,Reason:TargetHealth.Reason,Description:TargetHealth.Description}' \
  --output table

Cột Reason sẽ cho biết: Target.FailedHealthChecks (app không trả response), Target.NotRegistered (instance chưa register vào TG), hoặc Elb.InternalError. Đây là lớp chẩn đoán mà nhiều người bỏ qua khi chỉ nhìn vào ASG console.

Bước 5: Xác minh cấu hình health check trên Target Group

Target Group có cấu hình health check riêng — path, port, protocol, threshold, timeout. Nếu path trả về HTTP 404 hoặc app chạy trên port khác với port health check, TG sẽ đánh dấu instance unhealthy. ASG với ELB health check sẽ terminate instance đó.

aws elbv2 describe-target-groups \
  --target-group-arns arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/my-tg/1234567890abcdef \
  --query 'TargetGroups[0].{Protocol:HealthCheckProtocol,Port:HealthCheckPort,Path:HealthCheckPath,Interval:HealthCheckIntervalSeconds,Timeout:HealthCheckTimeoutSeconds,HealthyThreshold:HealthyThresholdCount,UnhealthyThreshold:UnhealthyThresholdCount,Matcher:Matcher}' \
  --output json
flowchart TD Start(["Instance bị terminate dù EC2 running"]) Step1["Bước 1: Đọc Activity History describe-scaling-activities"] CheckReason{"Lý do terminate?"} GracePeriod["Bước 2: Kiểm tra Health Check Grace Period"] GraceOK{"Grace Period đủ dài?"} FixGrace["Tăng grace-period cho đủ thời gian app khởi động"] CheckType["Bước 3: Kiểm tra Health Check Type"] TypeELB{"Type là ELB?"] SwitchELB["Cân nhắc chuyển sang ELB nếu có Load Balancer"] CheckTG["Bước 4: Kiểm tra Target Group Health"] TGHealthy{"Instance healthy trên TG?"] CheckTGConfig["Bước 5: Kiểm tra TG health check config (path, port, threshold)"] AppIssue["Vấn đề ứng dụng Kiểm tra app log, rollback"] Resolved(["Vấn đề đã xác định"]) Start --> Step1 Step1 --> CheckReason CheckReason -- "Grace period / khởi động" --> GracePeriod CheckReason -- "ELB health check failed" --> CheckTG CheckReason -- "EC2 health check failed" --> CheckType GracePeriod --> GraceOK GraceOK -- "Không" --> FixGrace GraceOK -- "Có" --> CheckType FixGrace --> Resolved CheckType --> TypeELB TypeELB -- "Không (EC2)" --> SwitchELB TypeELB -- "Có" --> CheckTG SwitchELB --> Resolved CheckTG --> TGHealthy TGHealthy -- "Không" --> CheckTGConfig TGHealthy -- "Có" --> Resolved CheckTGConfig -- "Config sai" --> Resolved CheckTGConfig -- "Config đúng" --> AppIssue AppIssue --> Resolved

Khi Nào Nên Chuyển Sang ELB Health Check?

Câu hỏi thực sự không phải là 'EC2 hay ELB tốt hơn' mà là 'bạn muốn ASG phản ứng với điều gì?'

  • Dùng EC2 health check khi ASG không có load balancer, hoặc khi bạn chỉ cần đảm bảo máy ảo đang chạy (batch processing, worker không expose HTTP).
  • Dùng ELB health check khi ứng dụng serve traffic qua ALB/NLB và bạn muốn ASG tự động thay thế instance khi app không phản hồi được — dù EC2 instance vẫn ở trạng thái running.

Chuyển health check type sang ELB:

aws autoscaling update-auto-scaling-group \
  --auto-scaling-group-name my-asg \
  --health-check-type ELB \
  --health-check-grace-period 300

Lưu ý: Sau khi chuyển sang ELB health check, nếu Target Group health check path của bạn không được cấu hình đúng, ASG sẽ liên tục terminate instance. Luôn xác minh TG health check hoạt động đúng (Bước 4 và 5) trước khi chuyển.

Trường Hợp Thực Tế — Misdiagnosis Điển Hình

Một deployment mới push lên, ASG bắt đầu terminate instance liên tục. Nhìn vào EC2 console: tất cả instance đều running, status checks xanh. Kết luận đầu tiên: 'Health check type sai, phải đổi sang ELB.'

Nhưng sau khi chạy describe-scaling-activities, activity log ghi rõ: Instance failed ELB health check. Health check type đã là ELB từ trước. Vấn đề không phải ở health check type.

Chạy describe-target-health: tất cả instance trả về State: unhealthy, Reason: Target.FailedHealthChecks. SSH vào instance, curl thủ công endpoint health check: HTTP 502. Ứng dụng mới deploy có bug khiến health check endpoint crash. Instance EC2 hoàn toàn bình thường — chỉ có ứng dụng bên trong bị lỗi.

Fix thực sự: rollback deployment, không phải thay đổi health check type. Nếu đã đổi sang EC2 health check 'để tạm thời fix', ASG sẽ ngừng terminate — nhưng traffic vẫn được route đến instance đang trả 502 cho end user.

ELB health check không phải nguyên nhân gây terminate — nó đang làm đúng việc của mình. Terminate instance trả 502 là hành vi đúng.

Cấu Hình IAM Tối Thiểu Để Chẩn Đoán

Nếu bạn cần cấp quyền cho một role chẩn đoán ASG và ELB health check mà không cần quyền modify:

🔽 Click để xem IAM Policy chẩn đoán (read-only)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ASGDiagnostics",
      "Effect": "Allow",
      "Action": [
        "autoscaling:DescribeAutoScalingGroups",
        "autoscaling:DescribeScalingActivities",
        "autoscaling:DescribeAutoScalingInstances"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ELBDiagnostics",
      "Effect": "Allow",
      "Action": [
        "elasticloadbalancing:DescribeTargetHealth",
        "elasticloadbalancing:DescribeTargetGroups",
        "elasticloadbalancing:DescribeTargetGroupAttributes"
      ],
      "Resource": "*"
    }
  ]
}

Các action Describe* của autoscaling và elasticloadbalancing yêu cầu Resource: "*" vì chúng không hỗ trợ resource-level restriction theo AWS Service Authorization Reference.

Wrap-Up — Auto Scaling Group Health Check Và Bước Tiếp Theo

Khi ASG terminate instance 'đang chạy bình thường', quy trình chẩn đoán đúng là: đọc activity history trước, kiểm tra grace period, sau đó mới xem xét health check type. Việc chuyển từ EC2 sang ELB health check chỉ có ý nghĩa khi bạn muốn ASG phản ứng với trạng thái ứng dụng — và chỉ an toàn khi TG health check đã được cấu hình và xác minh đúng.

Tài liệu tham khảo chính thức:

Glossary — Thuật Ngữ Chính

Thuật ngữGiải thích
Health Check Grace PeriodKhoảng thời gian (giây) ASG chờ sau khi instance launch trước khi bắt đầu kiểm tra health. Trong thời gian này, instance không bị terminate dù health check thất bại.
EC2 Health CheckASG kiểm tra trạng thái instance ở mức hypervisor: instance phải ở trạng thái running và vượt qua EC2 status checks.
ELB Health CheckASG sử dụng kết quả health check từ Target Group để xác định instance có healthy không. Phản ánh trạng thái ứng dụng thực tế.
Target Group Health CheckCấu hình trên Target Group xác định cách ALB/NLB kiểm tra ứng dụng: protocol, path, port, threshold, timeout.
set-instance-healthAPI của ASG cho phép hệ thống bên ngoài đánh dấu một instance là Healthy hoặc Unhealthy, kích hoạt hành động của ASG.

Related Posts

Nhận xét

Bài đăng phổ biến từ blog này

EC2 Không Có Internet Trong Custom VPC: Cách Gắn Internet Gateway và Cập Nhật Route Table

RDS Multi-AZ: Lợi Ích Thực Sự Là Gì và Khi Nào Nên Bật?

Lỗi CORS trên API Gateway: Cách bật CORS và Lambda phải trả về header gì