ADG Оставить заявку
Блог Данные и аналитика 5 мин чтения

Prometheus 1.5 в продакшне: node-exporter, cAdvisor и первые alert-правила

Полтора года от знакомства до продакшна: Prometheus 1.5, Alertmanager 0.6 и Grafana 4.x для контейнерной инфраструктуры - архитектура и первые уроки.

Контекст момента

Prometheus 1.5/1.6 и Alertmanager 0.6 достигли уровня зрелости, при котором стек становится пригодным для production-мониторинга контейнерной инфраструктуры

Полтора года назад мы впервые посмотрели на Prometheus и написали «в продакшн пока не идём». Летом 2016-го поставили рядом с Zabbix на реальных контейнерах - тоже без права на единоличный мониторинг. Февраль 2017-го: Prometheus 1.5 и Alertmanager 0.6 живут в продакшне для нескольких managed-проектов с контейнерной инфраструктурой, Zabbix смотрит за железом и сетью.

Расскажем как устроена стека и что в ней неожиданно оказалось важным.

Почему именно сейчас

Движение было постепенным. Не один большой переход, а накопление уверенности. Три вещи сошлись к концу 2016-го.

Первое - Alertmanager 0.6 переписали. Версии 0.3-0.4 были нестабильными по-настоящему: при перезапуске терялось состояние, дедупликация срабатывала непредсказуемо. Начиная с 0.5-0.6 это починили, и Alertmanager стал вести себя как инструмент, которому можно доверять оповещения в три часа ночи.

Второе - накопился опыт с PromQL. После нескольких месяцев в роли «второго монитора» у нас появилась библиотека запросов, которые реально используем. Без этого запускать Prometheus как единственный источник алертов было бы безответственно.

Третье - Grafana 4.x. Версия 4 принесла встроенный алертинг прямо из дашбордов, но мы его не используем - слишком ограниченный по сравнению с Alertmanager. Зато сами дашборды стали стабильнее: templating через переменные работает предсказуемо, и один дашборд с переменной $instance покрывает все хосты.

Как выглядит архитектура

Схема для типичного проекта на три-пять хостов с Docker-контейнерами:

┌─────────────────────────────────────────────┐
│  каждый Docker-хост                          │
│  node_exporter :9100  cAdvisor :8080         │
└──────────────────┬──────────────────────────┘
                   │ scrape (pull)
             ┌─────▼──────┐
             │ Prometheus  │  :9090
             │ 1.5/1.6     │
             └──────┬──────┘
          rules     │ alerts
             ┌──────▼──────┐      ┌─────────┐
             │ Alertmanager│─────►│  Slack  │
             │ 0.6         │      └─────────┘
             └─────────────┘
             ┌──────────────┐
             │  Grafana 4.x │◄── dashboards
             └──────────────┘

node_exporter отдаёт системные метрики хоста: CPU, память, диск, сеть, load average. cAdvisor - метрики каждого контейнера с labels по имени образа и именем контейнера. Оба запущены как контейнеры через systemd-unit с --restart=always, что проще чем пакеты в каждом дистрибутиве.

Prometheus собирает всё это с интервалом 15 секунд. На проекте с четырьмя хостами и тридцатью контейнерами это около 8-10 тысяч временных рядов - Prometheus переваривает без напряжения.

Alert-правила: что взяли в первую очередь

Начали с минимума. Правило которое ничего не делает в 99% случаев - лучше правила которое шумит каждые полчаса.

Первые три группы которые действительно прижились:

Доступность узлов. Если Prometheus не смог сделать scrape за последние две минуты - это instance down. Звучит банально, но именно этот алерт сработал первым на реальный инцидент: упал контейнер с node_exporter из-за неправильного монтирования /proc.

- alert: InstanceDown
  expr: up == 0
  for: 2m
  labels:
    severity: critical
  annotations:
    description: "{{ $labels.instance }} не отвечает больше 2 минут"

Память контейнеров. Тут пришлось повозиться. Метрика container_memory_usage_bytes включает page cache, и если смотреть на неё напрямую - алерты срабатывают на всё подряд. Правильная метрика для «реальной» памяти - container_memory_rss. Порог подбирали под каждый проект, жёсткого стандарта нет.

Свободное место на дисках. Классика, но с нюансом: на Docker-хостах /var/lib/docker растёт отдельно от корневого раздела. Добавили отдельное правило для этого mountpoint.

Что пошло не так

Первые недели показали несколько вещей, которые в тестовой среде не проявлялись.

for в правилах - обязателен. Без задержки перед срабатыванием алерт на CPU выше 80% превращается в шторм при любом деплое. Поставили for: 5m - и количество ложных срабатываний упало до нуля.

Группировка в Alertmanager. По умолчанию Alertmanager группирует по alertname. Если одновременно упали три хоста - в Slack приходит три отдельных сообщения про InstanceDown. Добавили group_by: [alertname, job] и group_wait: 30s - теперь это одно сообщение.

Retention по умолчанию 15 дней. Для некоторых клиентов этого мало: хотят видеть тренды за месяц. Prometheus хранит данные локально, remote_storage мы пока не подключали - просто выставили -storage.local.retention=30d и убедились что под это место есть.

cAdvisor и системные контейнеры. cAdvisor честно мониторит все контейнеры включая себя, node_exporter и Prometheus. На графиках это создаёт лишний шум. Добавили label_drop в конфиг scrape для контейнеров из пространства monitoring, и дашборды стали чище.

Что сейчас с Zabbix

Zabbix никуда не делся. Он смотрит за физическим железом (где есть SNMP и IPMI), сетевым оборудованием, Windows-хостами. Prometheus не умеет в SNMP из коробки, и тащить туда snmp_exporter ради трёх коммутаторов пока не хочется.

Полного замещения нет и не планируется прямо сейчас. Два монитора на разные слои инфраструктуры - это не дублирование, это разделение по зонам ответственности. Prometheus для контейнерного слоя, Zabbix для всего что ниже.

Результат полутора лет дороги от «интересно, но стрёмно» до продакшна: стек рабочий, команда с ним освоилась, клиенты получают алерты которые срабатывают когда надо и молчат когда не надо. Это и было целью.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.