Health Checks en Auto Scaling Groups: Cuándo cambiar de EC2 a ELB y por qué tu ASG termina instancias sanas
Tu Auto Scaling Group está terminando instancias que aparentemente funcionan bien — el proceso corre, el sistema operativo responde, pero el ASG las reemplaza de todas formas. Antes de cambiar el tipo de health check de 'EC2' a 'ELB', necesitas entender exactamente qué evalúa cada modo y qué consecuencias tiene ese cambio en producción.
TL;DR — Resumen rápido
| Aspecto | Health Check EC2 | Health Check ELB |
|---|---|---|
| ¿Qué evalúa? | Estado del hipervisor / instancia EC2 | Respuesta HTTP/TCP de la aplicación |
| Fuente de verdad | AWS EC2 status checks | Target Group health del Load Balancer |
| Instancia 'running' pero app caída | Considera la instancia sana | Considera la instancia no sana |
| Riesgo principal | Tráfico dirigido a instancias sin app | Terminaciones en cascada si el LB tiene mala configuración |
| Cuándo usarlo | Workloads sin LB, workers, batch | Aplicaciones web detrás de ALB/NLB |
Cómo funcionan los health checks en Auto Scaling Groups
El ASG necesita decidir si una instancia debe seguir en el grupo o ser reemplazada. Para eso consulta una fuente de estado — y esa fuente cambia completamente dependiendo del tipo configurado.
Con el tipo EC2, el ASG consulta los EC2 instance status checks del hipervisor. Una instancia está 'unhealthy' solo si el hardware subyacente falla, la instancia entra en estado stopped, terminated, o los system/instance checks reportan fallo. Si tu aplicación crashea pero el sistema operativo sigue corriendo, el ASG no lo sabe — la instancia aparece como sana.
Con el tipo ELB, el ASG delega la evaluación al Target Group asociado al Load Balancer. El ALB o NLB ejecuta sus propios health checks contra el endpoint configurado (por ejemplo, GET /health). Si la instancia falla esos checks, el Target Group la marca como unhealthy, y el ASG actúa sobre esa señal para terminarla y lanzar un reemplazo.
(system + instance)"] end subgraph ELBPath["Tipo: ELB"] ALB["Application Load Balancer"] TG["Target Group"] AppEndpoint["App: GET /health"] end ASG -->|"consulta estado"| HV HV --> EC2Check EC2Check -->|"running = sana"| ASG ASG -->|"consulta estado"| TG ALB -->|"health check periódico"| AppEndpoint AppEndpoint -->|"200 OK / fallo"| TG TG -->|"healthy / unhealthy"| ASG ASG -->|"unhealthy → terminar"| Terminate["Terminar instancia"]
- EC2 Health Check path: El ASG consulta directamente el estado del hipervisor EC2. Solo detecta fallos de infraestructura, no de aplicación.
- ELB Health Check path: El ALB ejecuta peticiones periódicas al endpoint de salud. Si falla el umbral configurado, el Target Group marca la instancia como unhealthy y el ASG recibe esa señal.
- Grace period: Durante el periodo de gracia, el ASG ignora los resultados del health check para dar tiempo al bootstrap de la instancia. Un grace period insuficiente es la causa más común de terminaciones prematuras.
Por qué el ASG termina instancias que parecen sanas — diagnóstico por capas
Antes de cambiar el tipo de health check, hay que confirmar en qué capa está fallando la evaluación. Cambiar de EC2 a ELB sin revisar la configuración del Target Group puede empeorar el problema.
Paso 1: Confirmar el estado real de la instancia en el ASG
El primer lugar donde mirar es la actividad del ASG. Los eventos de scaling muestran exactamente qué razón registró el sistema al terminar cada instancia — sin esto, cualquier hipótesis es especulación.
aws autoscaling describe-scaling-activities \
--auto-scaling-group-name nombre-de-tu-asg \
--region us-east-1 \
--query 'Activities[?StatusCode==`Failed` || contains(Description, `Terminating`)].[ActivityId,Description,Cause,StatusMessage]' \
--output table
Busca en el campo Cause si dice 'Instance failed ELB health checks' o 'Instance failed EC2 health checks'. Eso confirma qué capa está disparando la terminación.
Paso 2: Revisar el health check grace period
El grace period es el tiempo que el ASG espera después del lanzamiento antes de evaluar el estado de la instancia. Si tu aplicación tarda 3 minutos en arrancar y el grace period es 60 segundos, el ASG va a terminar instancias perfectamente funcionales durante el bootstrap — esto es el error más frecuente y el más silencioso.
aws autoscaling describe-auto-scaling-groups \
--auto-scaling-group-names nombre-de-tu-asg \
--region us-east-1 \
--query 'AutoScalingGroups[0].{HealthCheckType:HealthCheckType,GracePeriod:HealthCheckGracePeriod}' \
--output json
Si el grace period es menor que el tiempo real de arranque de tu aplicación, ese es el problema — no el tipo de health check. Ajústalo antes de cualquier otro cambio:
aws autoscaling update-auto-scaling-group \
--auto-scaling-group-name nombre-de-tu-asg \
--health-check-grace-period 300 \
--region us-east-1
Paso 3: Verificar el estado de las instancias en el Target Group
Si ya tienes configurado el tipo ELB, o estás evaluando si cambiarlo, necesitas ver exactamente qué estado reporta el Target Group para cada instancia. Una instancia puede estar running en EC2 y unhealthy en el Target Group simultáneamente.
aws elbv2 describe-target-health \
--target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/mi-target-group/1234567890abcdef \
--region us-east-1 \
--query 'TargetHealthDescriptions[*].{Instance:Target.Id,Port:Target.Port,State:TargetHealth.State,Reason:TargetHealth.Reason,Description:TargetHealth.Description}' \
--output table
Los valores de Reason más relevantes para diagnosticar son Target.FailedHealthChecks (la app no responde al health check), Target.NotRegistered (la instancia no está en el Target Group), y Target.Timeout (el endpoint responde demasiado lento).
Paso 4: Validar la configuración del health check en el Target Group
Un health check mal configurado en el Target Group es funcionalmente equivalente a no tener health check — o peor, puede marcar instancias sanas como fallidas. Verifica que el path, el puerto, y los umbrales sean correctos para tu aplicación.
aws elbv2 describe-target-groups \
--target-group-arns arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/mi-target-group/1234567890abcdef \
--region us-east-1 \
--query 'TargetGroups[0].{Path:HealthCheckPath,Port:HealthCheckPort,Protocol:HealthCheckProtocol,Interval:HealthCheckIntervalSeconds,Timeout:HealthCheckTimeoutSeconds,HealthyThreshold:HealthyThresholdCount,UnhealthyThreshold:UnhealthyThresholdCount}' \
--output json
Presta atención especial al UnhealthyThresholdCount: si está en 2 con un intervalo de 30 segundos, una instancia puede ser marcada como unhealthy en apenas 60 segundos después de un fallo transitorio.
Paso 5: Cambiar el tipo de health check del ASG
Solo ejecuta este paso si confirmaste que el problema es que el ASG no detecta fallos de aplicación (tipo EC2 activo, app caída, instancia no terminada). Si el problema era el grace period o la configuración del Target Group, este cambio no es necesario todavía.
aws autoscaling update-auto-scaling-group \
--auto-scaling-group-name nombre-de-tu-asg \
--health-check-type ELB \
--health-check-grace-period 300 \
--region us-east-1
Nota: este comando actualiza ambos parámetros simultáneamente. Cambiar a ELB sin ajustar el grace period al mismo tiempo es un error operacional común — las instancias nuevas serán evaluadas antes de que la app esté lista.
en scaling activities?"} Q2{"¿Grace period mayor
que tiempo de bootstrap?"} Q3{"¿Target Group reporta
instancias unhealthy?"} Q4{"¿Health check path
y puerto son correctos?"} FixGrace["Aumentar health-check-grace-period"] FixTG["Corregir configuración
del Target Group"] ChangeType["Cambiar ASG a tipo ELB
+ ajustar grace period"] Done(["Verificar con set-instance-health"]) Start --> Q1 Q1 -->|"EC2 health checks"| Q2 Q1 -->|"ELB health checks"| Q3 Q2 -->|"No"| FixGrace Q2 -->|"Sí — app cae sin detección"| ChangeType Q3 -->|"Sí"| Q4 Q3 -->|"No — revisar SuspendedProcesses"| Done Q4 -->|"No"| FixTG Q4 -->|"Sí — problema en la app"| Done FixGrace --> Done FixTG --> Done ChangeType --> Done
El error clásico: cambiar a ELB y disparar terminaciones en cascada
Aquí está el patrón que se repite en producción: el equipo cambia el tipo de health check a ELB para detectar fallos de aplicación. Inmediatamente, el ASG empieza a terminar instancias que antes parecían sanas. El pánico lleva a revertir el cambio, y el problema real nunca se resuelve.
Lo que realmente pasó: el health check del Target Group estaba apuntando a / en lugar de /health, y la aplicación devolvía un redirect 301 en ese path. El ALB interpretaba el 301 como fallo (el health check esperaba un 200). Con el tipo EC2, ese fallo era invisible. Al cambiar a ELB, el ASG finalmente vio lo que el Load Balancer ya sabía desde hace tiempo: ninguna instancia pasaba el health check.
La solución no era revertir a EC2 — era corregir el path del health check en el Target Group.
Cambiar el tipo de health check del ASG no modifica cómo el Load Balancer evalúa las instancias. Solo cambia si el ASG escucha esa evaluación para tomar decisiones de terminación.
Marcar manualmente una instancia como unhealthy para pruebas
Antes de confiar en que el nuevo tipo de health check funciona, conviene verificarlo de forma controlada. Puedes forzar el estado unhealthy en una instancia específica y confirmar que el ASG la termina y reemplaza correctamente.
aws autoscaling set-instance-health \
--instance-id i-1234567890abcdef0 \
--health-status Unhealthy \
--region us-east-1
El ASG debería terminar esa instancia y lanzar un reemplazo. Si no lo hace en un tiempo razonable, revisa si hay políticas de suspensión activas en el grupo:
aws autoscaling describe-auto-scaling-groups \
--auto-scaling-group-names nombre-de-tu-asg \
--region us-east-1 \
--query 'AutoScalingGroups[0].SuspendedProcesses' \
--output json
Si el proceso HealthCheck o Terminate aparece suspendido, el ASG no actuará sobre los estados unhealthy hasta que se reanuden:
aws autoscaling resume-processes \
--auto-scaling-group-name nombre-de-tu-asg \
--scaling-processes HealthCheck Terminate \
--region us-east-1
IAM mínimo necesario para ejecutar estos diagnósticos
🔽 Ver política IAM de diagnóstico (solo lectura + set-instance-health)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ASGDiagnosticReadOnly",
"Effect": "Allow",
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeScalingActivities",
"autoscaling:DescribeAutoScalingInstances"
],
"Resource": "*"
},
{
"Sid": "ELBTargetHealthRead",
"Effect": "Allow",
"Action": [
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:DescribeTargetGroups"
],
"Resource": "*"
},
{
"Sid": "ASGHealthCheckWrite",
"Effect": "Allow",
"Action": [
"autoscaling:SetInstanceHealth",
"autoscaling:UpdateAutoScalingGroup",
"autoscaling:ResumeProcesses"
],
"Resource": "arn:aws:autoscaling:us-east-1:123456789012:autoScalingGroup:*:autoScalingGroupName/nombre-de-tu-asg"
}
]
}
Las acciones Describe de AutoScaling y ELB requieren "Resource": "*" — no admiten restricción por ARN específico según la Service Authorization Reference de AWS.
Auto Scaling Group Health Checks: cuándo usar cada tipo
La decisión no es binaria entre 'EC2 es malo' y 'ELB es mejor'. Depende de la arquitectura real del workload.
| Escenario | Tipo recomendado | Razón |
|---|---|---|
| Aplicación web detrás de ALB/NLB | ELB | El LB ya evalúa la salud de la app — el ASG debe escuchar esa señal |
| Workers / procesadores de colas SQS | EC2 | No hay LB; la salud se mide por el proceso, no por HTTP |
| Instancias batch o de procesamiento | EC2 | No exponen endpoints HTTP; ELB no aplica |
| Microservicios con health endpoint propio | ELB | El endpoint /health refleja dependencias internas (DB, cache) |
| ASG sin Target Group asociado | EC2 | ELB requiere que el ASG esté asociado a un Target Group activo |
Próximos pasos y recursos
Si después de seguir este diagnóstico el ASG sigue terminando instancias de forma inesperada, el siguiente vector a investigar son las políticas de scaling reactivo — una alarma de CloudWatch mal calibrada puede estar disparando scale-in y terminando instancias independientemente del health check. Revisa también si tienes Instance Refresh activo, ya que ese proceso termina instancias de forma intencional como parte de una actualización de configuración.
- AWS Docs: Health checks for instances in an Auto Scaling group
- AWS Docs: Health checks for your target groups
- AWS Docs: Suspending and resuming scaling processes
Glosario de términos clave
| Término | Definición operacional |
|---|---|
| Health Check Grace Period | Tiempo en segundos que el ASG espera tras lanzar una instancia antes de evaluar su estado. Debe ser mayor que el tiempo de bootstrap de la aplicación. |
| EC2 Health Check | Evaluación basada en los status checks del hipervisor EC2. Solo detecta fallos de infraestructura, no de aplicación. |
| ELB Health Check (en ASG) | El ASG usa el estado reportado por el Target Group del Load Balancer para determinar si una instancia debe ser reemplazada. |
| Target Group Health | Estado de cada instancia registrada en un Target Group, determinado por las peticiones periódicas del ALB/NLB al endpoint configurado. |
| SuspendedProcesses | Procesos del ASG (como HealthCheck o Terminate) que han sido pausados manualmente o por operaciones como Instance Refresh, impidiendo acciones automáticas. |
Comentarios
Publicar un comentario