Алерты без агрегации в PromQL

PromQL-запрос с высокой кардинальностью плодит тысячи алертов на один инцидент.

Антипаттерн

Писать PromQL-выражение так, чтобы оно возвращало серию на каждый мелкий объект (партиция, pod, container, target), хотя сама проблема общая для всего узла или кластера.

Возьмём, например, алерт на недореплицированные партиции в Kafka:

- alert: UnderReplicatedPartition
  expr: kafka_topic_partition_under_replicated_partition > 0
  for: 10s
  labels:
    severity: warning
  annotations:
    summary: 'Topic has under-replicated partitions'
    description: 'Topic {{ $labels.topic }} has {{ $value }} under-replicated partition {{ $labels.partition }}'

Пока всё спокойно, срабатываний немного. Но если у брокера начнутся проблемы например с SAN-хранилищем, то в Prometheus загорится по алерту на каждую партицию каждого топика, то есть сотни или тысячи на брокер. AlertManager с группировкой по alertname и severity соберёт их в одну группу и будет переотправлять её огромным списком alerts: [...] при каждом изменении и по repeat_interval. Тело больше 1 МиБ Incident Garden не принимает и такой батч потеряется целиком.

Как надо

Свернуть кардинальность в PromQL до уровня, на котором действует дежурный. Для Kafka это брокер:

- alert: UnderReplicatedPartition
  expr: sum(kafka_topic_partition_under_replicated_partition) by (instance) > 0
  for: 10s
  labels:
    severity: warning
  annotations:
    summary: 'Kafka under-replicated partitions'
    description: 'Kafka instance {{ $labels.instance }} has {{ $value }} under-replicated partition'

Подробнее про кардинальность читайте в статье Cardinality is key.

Теперь сбой SAN даёт одно срабатывание на брокер, а не тысячи.

На этой странице