Alertas com Alertmanager

1. Introdução ao Alertmanager no Ecossistema Kubernetes

O Alertmanager é o componente central de notificação no ecossistema de monitoramento baseado em Prometheus. Dentro de um cluster Kubernetes, ele atua como o cérebro que decide quando, como e para quem enviar alertas. O fluxo típico é: Prometheus avalia regras de alerta continuamente, quando uma condição é satisfeita, o alerta é disparado e enviado ao Alertmanager. Este, por sua vez, aplica lógicas de agrupamento, inibição e roteamento antes de entregar a notificação aos canais configurados.

No ambiente Kubernetes moderno, a integração é ainda mais fluida com o uso do Prometheus Operator e do helm chart kube-prometheus-stack, que já incluem o Alertmanager pré-configurado. Os principais conceitos que você precisa dominar são:

  • Silences: permitem suprimir alertas temporariamente durante manutenções planejadas
  • Inibição: regras que suprimem alertas de baixa severidade quando um alerta mais crítico está ativo
  • Agrupamento: consolida alertas similares em uma única notificação para reduzir ruído
  • Roteamento: direciona alertas para diferentes receivers baseado em rótulos e expressões

2. Instalação e Configuração Básica do Alertmanager

A instalação mais comum em Kubernetes é via helm chart kube-prometheus-stack. Crie um arquivo values.yaml com configurações personalizadas:

alertmanager:
  enabled: true
  config:
    global:
      resolve_timeout: 5m
      slack_api_url: 'https://hooks.slack.com/services/T000000/B000000/XXXXXXXXXX'
    route:
      group_by: ['namespace', 'severity']
      group_wait: 30s
      group_interval: 5m
      repeat_interval: 4h
      receiver: 'default-slack'
      routes:
        - match:
            severity: critical
          receiver: 'critical-slack'
          repeat_interval: 1h
    receivers:
      - name: 'default-slack'
        slack_configs:
          - channel: '#alerts-default'
            title: '{{ .GroupLabels.alertname }}'
            text: '{{ .CommonAnnotations.description }}'
      - name: 'critical-slack'
        slack_configs:
          - channel: '#alerts-critical'
            title: '🚨 ALERTA CRÍTICO: {{ .GroupLabels.alertname }}'
            text: '{{ .CommonAnnotations.description }}'
    inhibit_rules:
      - source_match:
          severity: critical
        target_match:
          severity: warning
        equal: ['namespace']

Para instalar:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack -f values.yaml --namespace monitoring

Para acessar a interface web do Alertmanager:

kubectl port-forward -n monitoring svc/monitoring-kube-prometheus-alertmanager 9093:9093

Acesse http://localhost:9093 para visualizar alertas, criar silences e verificar o status.

3. Definindo Regras de Alerta no Prometheus

As regras de alerta são escritas em PromQL e armazenadas em ConfigMaps no Kubernetes. Crie um arquivo alert-rules.yaml:

groups:
  - name: kubernetes-nodes
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU usage above 80% on {{ $labels.instance }}"
          description: "Instance {{ $labels.instance }} has CPU usage at {{ $value }}% for more than 5 minutes."

      - alert: CriticalCPUUsage
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 95
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "CRITICAL: CPU usage above 95% on {{ $labels.instance }}"
          description: "Instance {{ $labels.instance }} has CPU usage at {{ $value }}% for more than 2 minutes."

  - name: kubernetes-pods
    rules:
      - alert: PodCrashLoopBackOff
        expr: kube_pod_status_phase{phase="Pending"} > 0
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Pod {{ $labels.pod }} in CrashLoopBackOff"
          description: "Pod {{ $labels.pod }} in namespace {{ $labels.namespace }} is in CrashLoopBackOff state."

      - alert: HighMemoryUsage
        expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Memory usage above 85% on {{ $labels.instance }}"
          description: "Instance {{ $labels.instance }} has memory usage at {{ $value }}%."

Aplique as regras no cluster:

kubectl create configmap prometheus-rules --from-file=alert-rules.yaml -n monitoring
kubectl label configmap prometheus-rules prometheus=monitoring-kube-prometheus -n monitoring

O Prometheus Operator detectará automaticamente o novo ConfigMap e recarregará as regras sem necessidade de reinicialização.

4. Roteamento e Agrupamento Inteligente de Alertas

O roteamento hierárquico permite direcionar alertas específicos para canais diferentes. Exemplo de configuração avançada:

route:
  receiver: 'default'
  group_by: ['namespace', 'alertname']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    - match:
        severity: critical
        namespace: production
      receiver: 'pagerduty-prod'
      continue: true
    - match_re:
        namespace: '(staging|dev)'
      receiver: 'slack-dev'
      group_interval: 10m
    - match:
        alertname: 'PodCrashLoopBackOff'
      receiver: 'slack-ops'
      group_by: ['pod']

O agrupamento evita notificações repetitivas. Com group_by: ['namespace', 'alertname'], todos os alertas do mesmo namespace com o mesmo nome serão consolidados em uma única notificação. O group_wait determina quanto tempo o Alertmanager espera para agrupar alertas antes de enviar a primeira notificação, enquanto group_interval controla o intervalo entre notificações do mesmo grupo.

5. Notificações: Canais e Templates

Além do Slack, você pode configurar diversos receivers. Exemplo completo:

receivers:
  - name: 'email-admin'
    email_configs:
      - to: 'admin@empresa.com'
        from: 'alertmanager@empresa.com'
        smarthost: 'smtp.gmail.com:587'
        auth_username: 'alertmanager@empresa.com'
        auth_password: 'senha_app'
        require_tls: true

  - name: 'webhook-custom'
    webhook_configs:
      - url: 'http://webhook-service:5000/alerts'
        send_resolved: true

  - name: 'pagerduty-critical'
    pagerduty_configs:
      - routing_key: 'sua_chave_pagerduty'
        severity: 'critical'

Para personalizar as mensagens, crie um template custom.tmpl:

{{ define "slack.custom.title" }}
  [{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}
{{ end }}

{{ define "slack.custom.text" }}
  *Alerta:* {{ .CommonLabels.alertname }}
  *Severidade:* {{ .CommonLabels.severity }}
  *Namespace:* {{ .GroupLabels.namespace }}
  *Descrição:* {{ .CommonAnnotations.description }}
  *Grafana:* {{ .ExternalURL }}
{{ end }}

Referencie o template no receiver:

slack_configs:
  - channel: '#alerts'
    title: '{{ template "slack.custom.title" . }}'
    text: '{{ template "slack.custom.text" . }}'
    color: '{{ if eq .CommonLabels.severity "critical" }}danger{{ else }}warning{{ end }}'

6. Silenciamento e Inibição de Alertas

Para criar um silence via API REST durante uma manutenção programada:

curl -X POST http://localhost:9093/api/v2/silences \
  -H "Content-Type: application/json" \
  -d '{
    "matchers": [
      {"name": "namespace", "value": "production", "isRegex": false},
      {"name": "severity", "value": "warning", "isRegex": false}
    ],
    "startsAt": "2025-01-20T10:00:00Z",
    "endsAt": "2025-01-20T18:00:00Z",
    "createdBy": "admin",
    "comment": "Manutenção programada no namespace production"
  }'

Regras de inibição são poderosas para reduzir ruído. Exemplo avançado:

inhibit_rules:
  - source_match:
      alertname: 'NodeNotReady'
    target_match:
      severity: warning
    equal: ['instance']

  - source_match:
      severity: critical
    target_match:
      severity: warning
    equal: ['namespace', 'cluster']

Isso suprime todos os alertas de warning de um nó específico quando ele está NotReady, e também suprime warnings gerais quando um alerta crítico está ativo no mesmo namespace e cluster.

7. Boas Práticas e Troubleshooting

Teste suas regras localmente antes de aplicar:

# Validar regras de alerta
promtool check rules alert-rules.yaml

# Testar configuração do Alertmanager
amtool check-config alertmanager.yaml

# Simular envio de alerta
amtool alert add --alertmanager.url=http://localhost:9093 \
  --annotation=summary="Teste" \
  --label=severity=critical \
  --label=namespace=default \
  --start=2025-01-20T10:00:00Z \
  --end=2025-01-20T11:00:00Z \
  TestAlert

Monitore a saúde do próprio Alertmanager com métricas expostas em http://localhost:9093/metrics. Configure um "dead man's switch" (alerta Watchdog) que dispara se o Alertmanager parar de funcionar:

- alert: Watchdog
  expr: vector(1)
  labels:
    severity: none
  annotations:
    description: "This alert ensures Alertmanager is working. If missing, Alertmanager is down."

Estratégias para redução de ruído:

  • Use for nas regras para evitar alertas falsos por picos momentâneos
  • Configure repeat_interval adequado (4h para warnings, 1h para críticos)
  • Implemente escalonamento de severidade: warning → critical após 30 minutos
  • Utilize inibição para alertas correlacionados

Referências