CloudWatch en AWS para EC2: alertas por consola y terminal con prueba real
Contexto
Configurar alarmas en AWS no es dificil. Lo dificil es validarlas de verdad y no dejar una falsa sensacion de cobertura.
Muchos equipos crean alarmas en CloudWatch, las conectan a SNS y dan por terminado el trabajo. El problema aparece despues: cuando llega el incidente, la alerta no salta por un detalle de configuracion, por un umbral mal calibrado o porque nunca se probo el flujo completo.
En este tutorial explico un patron simple y reutilizable para EC2:
- Crear un canal de notificacion con
SNS. - Crear alarmas en
CloudWatch(por consola y por CLI). - Validar con una prueba real de CPU.
- Dejar una base lista para replicar en otros entornos.
Todo el contenido esta anonimizado. Los nombres de recursos, IDs y correos son ejemplos genericos para que puedas adaptarlo a tu entorno.
Punto clave: una alarma sin prueba real es configuracion, no observabilidad operativa.
Enfoque propuesto
El enfoque que mejor me funciona para equipos y proyectos reales combina dos caminos:
- Consola AWS para aprender el flujo, validar campos y entender la evaluacion visual.
- CLI (AWS CLI) para repetir el proceso con precision y documentar comandos reutilizables.
En este post uso ambos de forma deliberada:
- Creo el canal
SNSy una primera alarma desde consola. - Creo el resto de alarmas por terminal.
- Hago una prueba de carga en la instancia para comprobar que la notificacion llega.
Arquitectura minima del flujo
La arquitectura es intencionadamente simple:
- EC2 emite metricas nativas (por ejemplo,
CPUUtilization). - CloudWatch Alarms evalua umbrales y cambia estado (
OK,ALARM,INSUFFICIENT_DATA). - SNS envia la notificacion por email.
Para una primera version de observabilidad operativa, este flujo cubre mucho mas de lo que parece si lo validas bien.
Implementacion paso a paso
1) Crear SNS topic y suscripcion email (Console)
Objetivo: tener un canal de notificacion simple y verificable antes de crear alarmas.
Pasos en AWS Console (resumen):
- Ir a
Amazon SNS. - Crear un topic
Standard. - Asignar un nombre generico (ejemplo:
dev-infra-alerts). - Crear una suscripcion
Email. - Confirmar la suscripcion desde el correo recibido.
- Ejecutar un
Publish messagede prueba.
Recomendacion:
- Empieza solo con email.
- Cuando el flujo este validado, anade Teams/Slack/Chatbot.
2) Crear alarma EC2 desde Console (primera alarma)
Para aprender el flujo visual, crea la primera alarma desde CloudWatch > Alarms.
Alarma 1: CPU warning
Ejemplo de configuracion:
- Metrica:
AWS/EC2 -> CPUUtilization - Estadistica:
Average - Periodo:
60ssi la instancia publica metricas cada 1 minuto (Detailed Monitoring)300ssi la instancia usaBasic Monitoring(CPU en bloques de 5 min)
- Umbral:
> 75 - Evaluacion:
5 de 5si usas60s1 de 1si usas300s
- Missing data:
not breaching(en UI suele aparecer como “Correctos (dentro del limite)”) - Accion: enviar a topic SNS
En la validacion real de este tutorial se uso
Basic Monitoring, por lo que la alarma se ajusto aperiod=300y1 de 1.
Nombre sugerido:
dev-ec2-bastion-cpu-warning
Etiquetas recomendadas:
Environment=devService=ec2Resource=bastionMetric=CPUUtilizationSeverity=warning
3) Crear alarmas EC2 desde terminal (CLI)
Una vez validado el flujo en consola, pasar a CLI te da dos ventajas:
- Trazabilidad del comando exacto.
- Repetibilidad entre entornos.
En este ejemplo usamos tres alarmas:
CPU warningCPU criticalStatusCheckFailed critical
Nota: uso nombres genericos e identificadores de ejemplo. Sustituye
INSTANCE_IDySNS_TOPIC_ARNpor los tuyos.
Variables (opcional, para no repetir)
REGION="eu-west-1"
INSTANCE_ID="i-xxxxxxxxxxxxxxxxx"
SNS_TOPIC_ARN="arn:aws:sns:eu-west-1:123456789012:dev-infra-alerts"
3.1 CPU warning (>75%) - configuracion final validada (Basic Monitoring 5m)
En una primera version puedes plantear 60s + 5/5, pero si la instancia publica CPU en Basic Monitoring (5 min), la configuracion real que valida correctamente es:
period = 300evaluation-periods = 1datapoints-to-alarm = 1
Esto mantiene el objetivo funcional: si la media del bloque de 5 minutos supera 75%, salta la alarma.
aws cloudwatch put-metric-alarm \
--region "$REGION" \
--alarm-name "dev-ec2-bastion-cpu-warning" \
--alarm-description "DEV bastion CPUUtilization warning >75% durante 5 min (basic monitoring 5m)" \
--namespace "AWS/EC2" \
--metric-name "CPUUtilization" \
--dimensions Name=InstanceId,Value="$INSTANCE_ID" \
--statistic Average \
--period 300 \
--evaluation-periods 1 \
--datapoints-to-alarm 1 \
--threshold 75 \
--comparison-operator GreaterThanThreshold \
--treat-missing-data notBreaching \
--alarm-actions "$SNS_TOPIC_ARN"
Comando de verificacion (muy recomendable):
aws cloudwatch describe-alarms \
--region "$REGION" \
--alarm-names "dev-ec2-bastion-cpu-warning" \
--query "MetricAlarms[0].{Name:AlarmName,State:StateValue,Period:Period,Eval:EvaluationPeriods,Datapoints:DatapointsToAlarm,Threshold:Threshold,Reason:StateReason}"
3.2 CPU critical (>85%) - configuracion final validada (Basic Monitoring 5m)
Para mantener el criterio de “10 minutos sostenidos” usando bloques de 5 minutos:
period = 300evaluation-periods = 2datapoints-to-alarm = 2
Esto equivale a 2 bloques consecutivos de 5 minutos por encima del umbral.
aws cloudwatch put-metric-alarm \
--region "$REGION" \
--alarm-name "dev-ec2-bastion-cpu-critical" \
--alarm-description "DEV bastion CPUUtilization critical >85% durante 10 min (basic monitoring 5m)" \
--namespace "AWS/EC2" \
--metric-name "CPUUtilization" \
--dimensions Name=InstanceId,Value="$INSTANCE_ID" \
--statistic Average \
--period 300 \
--evaluation-periods 2 \
--datapoints-to-alarm 2 \
--threshold 85 \
--comparison-operator GreaterThanThreshold \
--treat-missing-data notBreaching \
--alarm-actions "$SNS_TOPIC_ARN"
Comando de verificacion:
aws cloudwatch describe-alarms \
--region "$REGION" \
--alarm-names "dev-ec2-bastion-cpu-critical" \
--query "MetricAlarms[0].{Name:AlarmName,State:StateValue,Period:Period,Eval:EvaluationPeriods,Datapoints:DatapointsToAlarm,Threshold:Threshold,Reason:StateReason}"
3.3 StatusCheckFailed critical (>0, 1/1)
aws cloudwatch put-metric-alarm \
--region "$REGION" \
--alarm-name "dev-ec2-bastion-statuscheckfailed-critical" \
--alarm-description "DEV bastion StatusCheckFailed critical >0" \
--namespace "AWS/EC2" \
--metric-name "StatusCheckFailed" \
--dimensions Name=InstanceId,Value="$INSTANCE_ID" \
--statistic Maximum \
--period 60 \
--evaluation-periods 1 \
--datapoints-to-alarm 1 \
--threshold 0 \
--comparison-operator GreaterThanThreshold \
--treat-missing-data notBreaching \
--alarm-actions "$SNS_TOPIC_ARN"
4) Etiquetar alarmas por CLI (recomendado)
put-metric-alarm no siempre es la mejor opcion para tags en todos los flujos, asi que una practica robusta es etiquetar despues con tag-resource.
ACCOUNT_ID="123456789012"
ALARM_NAME="dev-ec2-bastion-cpu-critical"
ALARM_ARN="arn:aws:cloudwatch:${REGION}:${ACCOUNT_ID}:alarm:${ALARM_NAME}"
aws cloudwatch tag-resource \
--region "$REGION" \
--resource-arn "$ALARM_ARN" \
--tags \
Key=Environment,Value=dev \
Key=Service,Value=ec2 \
Key=Resource,Value=bastion \
Key=Metric,Value=CPUUtilization \
Key=Severity,Value=critical
5) Verificar configuracion y acciones (CLI)
Antes de hacer pruebas, verifica que la alarma existe y que realmente tiene accion SNS.
aws cloudwatch describe-alarms \
--region "$REGION" \
--alarm-names "dev-ec2-bastion-cpu-critical" \
--query "MetricAlarms[0].{Name:AlarmName,State:StateValue,Actions:AlarmActions,Period:Period,Eval:EvaluationPeriods,Datapoints:DatapointsToAlarm,Threshold:Threshold}"
Tambien puedes revisar tags:
aws cloudwatch list-tags-for-resource \
--region "$REGION" \
--resource-arn "$ALARM_ARN"
Validacion con stress test (CPU)
La parte importante del tutorial no es solo crear alarmas, sino comprobar que saltan.
Opcion simple sin instalar herramientas: yes
Si no tienes stress-ng, puedes generar carga CPU con procesos yes.
Ejemplo (instancia de 8 vCPU):
for i in $(seq 1 6); do yes > /dev/null & done
Si se queda justo en el umbral, sube a 7:
for i in $(seq 1 7); do yes > /dev/null & done
Para parar la carga:
pkill yes
Como validar el disparo
- Mantener la carga el tiempo suficiente para la evaluacion (segun tu configuracion real: por ejemplo
1 de 1bloque de300sparawarning,2 de 2bloques paracriticalen Basic Monitoring). - Revisar el estado en
CloudWatch Alarms. - Confirmar el email recibido desde
SNS. - Documentar hora de inicio, hora de disparo y hora de vuelta a
OK.
Monitorizar el estado de las alarmas desde terminal (muy util durante la prueba)
Mientras ejecutas la carga, este comando te permite ver en tiempo real si warning y critical cambian de estado:
WARNING_ALARM_NAME="dev-ec2-bastion-cpu-warning"
CRITICAL_ALARM_NAME="dev-ec2-bastion-cpu-critical"
aws cloudwatch describe-alarms \
--region "$REGION" \
--alarm-names "$CRITICAL_ALARM_NAME" "$WARNING_ALARM_NAME" \
--query "MetricAlarms[].{Name:AlarmName,State:StateValue,Updated:StateUpdatedTimestamp}" \
--output table
Ejemplo de salida cuando la alarma warning ya ha saltado y critical sigue en OK:
-------------------------------------------------------------------------------
| DescribeAlarms |
+-------------------------------+--------+------------------------------------+
| Name | State | Updated |
+-------------------------------+--------+------------------------------------+
| dev-ec2-host-cpu-critical | OK | 2026-02-23T14:03:53.405000+00:00 |
| dev-ec2-host-cpu-warning | ALARM | 2026-02-23T15:17:11.184000+00:00 |
+-------------------------------+--------+------------------------------------+
Este tipo de salida es muy util para documentar pruebas y construir evidencias tecnicas en runbooks o issues.
Error comun (y muy real): el umbral visual “parece” cumplido
Si la alarma usa GreaterThanThreshold (>) y la grafica se queda visualmente en 75, puede que no dispare.
Motivo:
- CloudWatch evalua el valor real del datapoint, no el redondeo visual.
75.0no es mayor que75.
Solucion:
- subir un poco la carga para quedar claramente por encima del umbral.
Ajuste real muy frecuente: Basic Monitoring vs Detailed Monitoring
Un caso muy comun en AWS es este:
- Tu alarma esta pensada para
1 min - Pero la instancia publica CPU cada
5 min(Basic Monitoring)
En ese caso, puedes adaptar temporalmente la alarma para validar el flujo sin activar Detailed Monitoring:
warning:period=300,1/1critical:period=300,2/2
Todo lo demas se mantiene igual (umbral, metrica, accion SNS, treat-missing-data).
Y la alarma de StatusCheckFailed, como se prueba?
No recomiendo forzar un fallo real de instancia para validar esta alarma en un entorno que quieras mantener estable.
Una alternativa segura es una prueba sintetica del estado de la alarma:
aws cloudwatch set-alarm-state \
--region "$REGION" \
--alarm-name "dev-ec2-bastion-statuscheckfailed-critical" \
--state-value ALARM \
--state-reason "Synthetic test for notification path"
Esto no simula un fallo real de EC2, pero si valida:
- cambio de estado
- accion SNS
- recepcion de la notificacion
Buenas practicas y riesgos
- Usa naming consistente por entorno/servicio/recurso/severidad desde el primer dia.
- Configura y prueba primero SNS/email antes de crear alarmas.
- Verifica acciones y tags por CLI antes del stress test.
- No fuerces fallos reales para probar
StatusCheckFailedsi no tienes una ventana controlada. - Recuerda que
>no es lo mismo que>=; CloudWatch evalua el valor exacto. - Documenta cada prueba con timestamps y resultado para poder replicarla en otros entornos.
Resultado esperado
Con este flujo tienes una base operativa muy util para EC2:
- canal de notificacion validado (
SNS -> Email) - alarmas de CPU y salud de instancia creadas
- pruebas reales para verificar que las alertas funcionan
- comandos CLI listos para replicar en
stagingyprod
A partir de aqui puedes ampliar cobertura a:
CPUCreditBalance(si usas instancias burstablet*)- memoria y disco con
CloudWatch Agent - otros servicios como
RDS,ElastiCacheyALB
Siguiente paso
En una siguiente iteracion, el paso natural es pasar estas alarmas a Terraform para versionarlas y desplegarlas por entorno con menos deriva.
Antes de llegar a Terraform, mi recomendacion es cerrar primero la validacion operativa en no productivo:
- Probar
warningycriticalcon carga controlada. - Validar notificaciones end-to-end.
- Documentar evidencias y ajustes (por ejemplo,
Basic MonitoringvsDetailed Monitoring). - Replicar el patron en el siguiente entorno objetivo de tu pipeline (por ejemplo
stagingy despuesprod, o el orden que aplique en tu organizacion).
¿Aplicamos esta idea en tu contexto?
Si quieres convertir este enfoque en un plan accionable para tu equipo, puedo ayudarte a definir prioridades, riesgos y siguiente iteración.