AWS CloudWatch monitoring alerty

CloudWatch Alarm się nie uruchamia: diagnoza i naprawa

Naprawa CloudWatch Alarm który się nie uruchamia: INSUFFICIENT_DATA z powodu brakujących metryk, złe okresy ewaluacji, brak uprawnień SNS i obsługa brakujących danych.

Jerzy Kopaczewski ·
Skonfigurowałeś CloudWatch Alarm na CPU >80%, ale mimo że instancja jest pod pełnym obciążeniem, alarm pokazuje INSUFFICIENT_DATA lub pozostaje w stanie OK. Albo alarm przechodzi w status ALARM, ale powiadomienie nigdy nie dociera na Slack/email. Ten runbook pokrywa oba scenariusze.

Jeśli rozważasz przejście z CloudWatch na bardziej zaawansowaną platformę observability, zobacz nasz przewodnik po migracji do Datadog. Aby zrozumieć model kosztów CloudWatch, zobacz artykuł o ukrytych kosztach Lambda i EBS.

Objaw

Alarm nie reaguje mimo spełnionych warunków:

# Sprawdź stan alarmu
aws cloudwatch describe-alarms \
  --alarm-names "my-cpu-alarm" \
  --query 'MetricAlarms[0].{State:StateValue,Reason:StateReason,Updated:StateUpdatedTimestamp}'

# Typowe odpowiedzi problematyczne:
# State: INSUFFICIENT_DATA
# Reason: "Unchecked: Initial alarm creation"
#
# lub:
# State: OK
# Reason: "Threshold Crossing: 1 datapoint [45.2] was not greater than the threshold (80.0)"
# (ale wiesz, że CPU jest na 95%)

# Sprawdź czy metryka w ogóle ma dane
aws cloudwatch get-metric-statistics \
  --namespace AWS/EC2 \
  --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-0123456789abcdef0 \
  --start-time $(date -u -v-1H +%Y-%m-%dT%H:%M:%S) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
  --period 300 --statistics Average

Przyczyna

Scenariusz 1: INSUFFICIENT_DATA

Alarm nie otrzymuje danych metryki. Przyczyny:

  • Detailed monitoring nie jest włączony - domyślnie EC2 raportuje metryki co 5 minut. Jeśli alarm ma okres 1 minuty, nie dostaje danych.
  • Zły namespace lub wymiar - literówka w InstanceId, zły Namespace
  • Instancja nie raportuje - agent CloudWatch nie działa, lub instancja jest w innym regionie
  • Custom metric nie jest wysyłana - aplikacja przestała publikować metrykę (crash, błąd w kodzie)

Scenariusz 2: Alarm w OK mimo przekroczenia progu

  • Okres ewaluacji vs wymagane punkty danych - alarm wymaga N z M punktów danych powyżej progu. Jeśli ustawiłeś 3 z 3, a dane przychodzą nieregularnie, warunek nigdy nie jest spełniony.
  • Statystyka Average vs Maximum - CPU wyskakuje do 95%, ale średnia w 5-minutowym oknie to 60%
  • Obsługa brakujących danych (treat missing data): missing - brakujące punkty danych traktowane jako “brak informacji”, nie jako naruszenie

Scenariusz 3: Alarm wyzwolony ale brak powiadomienia

  • SNS topic nie ma subskrypcji - topic istnieje, ale nikt nie potwierdził subskrypcji
  • Alarm action pusta - AlarmActions nie zawiera ARN topic
  • Uprawnienia SNS - topic z innego konta nie ma reguły (policy) pozwalającej na publikację
  • Budżet powiadomień - SMS/email ograniczane przez limity konta

Naprawa

A) INSUFFICIENT_DATA - napraw źródło danych

# 1. Sprawdź czy detailed monitoring jest włączony (dla period <5min)
aws ec2 describe-instances \
  --instance-ids i-0123456789abcdef0 \
  --query 'Reservations[0].Instances[0].Monitoring.State'
# "disabled" = metryki co 5 minut tylko

# Włącz detailed monitoring (metryki co 1 minutę)
aws ec2 monitor-instances --instance-ids i-0123456789abcdef0

# 2. Sprawdź wymiary alarmu vs rzeczywiste dane
aws cloudwatch describe-alarms --alarm-names "my-cpu-alarm" \
  --query 'MetricAlarms[0].Dimensions'
# Upewnij się, że InstanceId jest poprawny i nie ma literówek

# 3. Jeśli to custom metric - sprawdź czy aplikacja ją publikuje
aws cloudwatch list-metrics \
  --namespace "MyApp" \
  --metric-name "RequestLatency"
# Pusty wynik = metryka nie jest wysyłana

B) Napraw evaluation period i statystykę

# Zmień alarm aby używał Maximum zamiast Average (dla spike detection)
aws cloudwatch put-metric-alarm \
  --alarm-name "my-cpu-alarm" \
  --metric-name CPUUtilization \
  --namespace AWS/EC2 \
  --statistic Maximum \
  --period 60 \
  --evaluation-periods 3 \
  --datapoints-to-alarm 2 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --dimensions Name=InstanceId,Value=i-0123456789abcdef0 \
  --alarm-actions arn:aws:sns:eu-central-1:123456789012:ops-alerts \
  --treat-missing-data breaching
  # ^^ breaching = brakujące dane traktowane jako naruszenie progu
  # Alternatywy: missing (ignoruj), notBreaching (traktuj jako OK), ignore

Kluczowe parametry:

  • --period 60 - okno w sekundach (musi być >= częstotliwość raportowania metryki)
  • --evaluation-periods 3 - ile ostatnich okresów sprawdzać
  • --datapoints-to-alarm 2 - ile z evaluation-periods musi naruszyć próg (M z N)
  • --treat-missing-data breaching - krytyczne dla custom metrics, które mogą przestać przychodzić

C) Napraw powiadomienia (SNS)

# 1. Sprawdź czy alarm ma skonfigurowane actions
aws cloudwatch describe-alarms --alarm-names "my-cpu-alarm" \
  --query 'MetricAlarms[0].AlarmActions'
# Powinno zwrócić ARN SNS topic. Jeśli puste - dodaj.

# 2. Sprawdź subskrypcje topic
aws sns list-subscriptions-by-topic \
  --topic-arn arn:aws:sns:eu-central-1:123456789012:ops-alerts
# Każda subskrypcja musi mieć SubscriptionArn (nie "PendingConfirmation")

# 3. Jeśli topic z innego konta - dodaj policy
aws sns set-topic-attributes \
  --topic-arn arn:aws:sns:eu-central-1:123456789012:ops-alerts \
  --attribute-name Policy \
  --attribute-value '{
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "cloudwatch.amazonaws.com"},
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:eu-central-1:123456789012:ops-alerts"
    }]
  }'

# 4. Wymuś test powiadomienia
aws cloudwatch set-alarm-state \
  --alarm-name "my-cpu-alarm" \
  --state-value ALARM \
  --state-reason "Manual test"
# Sprawdź czy powiadomienie dotarło. Reset do OK po teście:
aws cloudwatch set-alarm-state \
  --alarm-name "my-cpu-alarm" \
  --state-value OK \
  --state-reason "Reset after test"

Weryfikacja

# Sprawdź aktualny stan alarmu
aws cloudwatch describe-alarms --alarm-names "my-cpu-alarm" \
  --query 'MetricAlarms[0].{State:StateValue,Reason:StateReason}'

# Sprawdź historię przejść stanów
aws cloudwatch describe-alarm-history \
  --alarm-name "my-cpu-alarm" \
  --history-item-type StateUpdate \
  --max-records 5

# Wymuś przekroczenie progu (stress test)
# Na instancji EC2:
stress-ng --cpu 4 --timeout 300s
# Alarm powinien przejść w ALARM w ciągu evaluation-periods * period sekund

Jeśli alarm przechodzi w status ALARM w odpowiedzi na rzeczywiste obciążenie i powiadomienie dociera do odbiorców, problem rozwiązany.

CloudWatch Alarmy najczęściej zawodzą z trzech powodów: brakujące dane (zły okres lub wyłączony detailed monitoring), zbyt restrykcyjny warunek (3/3 datapoints z Average), lub zerwany łańcuch powiadomień (SNS bez subskrypcji). Parametr `treat-missing-data` (obsługa brakujących danych) jest krytyczny dla custom metrics - domyślne "missing" oznacza, że alarm nie reaguje gdy aplikacja przestanie wysyłać dane.
Jerzy Kopaczewski

Alerting nie działa jak powinien?

Umów bezpłatną 30-minutową rozmowę. Przejrzymy konfigurację monitoringu i naprawimy martwe alerty.