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 для всего что ниже.
Результат полутора лет дороги от «интересно, но стрёмно» до продакшна: стек рабочий, команда с ним освоилась, клиенты получают алерты которые срабатывают когда надо и молчат когда не надо. Это и было целью.
- Prometheus 0.16: попробовали pull-модель мониторинга для Docker-контейнеров · 24 ноября 2015
- Prometheus + Alertmanager: первый опыт рядом с Zabbix · 13 июля 2016