Prometheus 1.7 в продакшне: тюнинг retention, compaction и federation для нескольких площадок
Полгода Prometheus в проде - разбираем retention, compaction, remote_write в InfluxDB и federation-топологию для мониторинга нескольких площадок.
Prometheus 1.7 (июнь 2017) с улучшенным storage и federation
В феврале мы описывали первый продакшн-запуск Prometheus 1.5. С тех пор прошло четыре месяца, Prometheus обновился до 1.7, и у нас накопился список вещей которые в тестовой среде незаметны, а в проде начинают давить через пару недель работы. Плюс появились клиенты с несколькими площадками, и нужна была federation-топология. Рассказываем что тюнили и к чему пришли.
Где жало первые недели
Дефолтный Prometheus работает с параметрами для «потыкать руками», а не для production-нагрузки. Первое что прилетело - диск.
На одном из managed-проектов с четырьмя хостами и парой десятков контейнеров Prometheus за три недели набрал под 30 ГБ на диске. При дефолтном retention в 15 дней это означало около 2 ГБ в сутки - больше чем ожидали при планировании объёма. Начали разбираться.
Первое - chunks_directory растёт быстро при scrape_interval 15s. Каждые 15 секунд по нескольким тысячам временных рядов - это значительный объём сырых данных до compaction. Подняли interval до 30 секунд там где точность в 15 секунд не критична, и объём сразу упал вдвое.
Второе - retention надо выставлять явно. -storage.local.retention по умолчанию 360h (15 дней), но компания забыла указать его явно в unit-файле, и когда systemd-unit переписывали - параметр потерялся. Prometheus молча переключился на дефолт. Теперь все параметры storage идут в явном виде в конфиге запуска, ничего не оставляем «как есть».
Третье - compaction работает, но не сразу. Prometheus 1.7 делает compaction фоново, и свежеинсталлированный экземпляр первые сутки-двое выглядит будто жрёт диск неадекватно. Это нормально: chunks ещё не сложены в blocks. После первого полного цикла compaction размер резко падает. Без понимания этого поведения первый рефлекс - «что-то сломалось, надо перезапускать», что только мешает.
remote_write в InfluxDB: зачем и как
У нескольких клиентов требование хранить метрики дольше месяца - для capacity planning и для SLA-отчётности. Prometheus с 30-дневным retention на это не рассчитан: диск растёт линейно, и за год это будет неуправляемо.
Решение - remote_write через Telegraf в InfluxDB, который умеет downsampling и хранит агрегированные данные долго. Telegraf принимает remote_write по HTTP и пишет в InfluxDB через line protocol. Конфиг в Prometheus 1.7 простой:
remote_write:
- url: "http://telegraf:9999/receive"
write_relabel_configs:
- source_labels: [__name__]
regex: "node_.*|container_.*"
action: keep
Пишем не всё, только системные метрики и контейнерные. Метрики самого Prometheus, Alertmanager и временные сервисные метрики в долгосрочное хранилище не льём - там нет смысла.
Главная засада с remote_write которую словили: если InfluxDB недоступен, Prometheus буферизует данные в памяти и на диске, но буфер ограничен. При длительном падении InfluxDB получаем «дыру» в долгосрочных данных без каких-либо алертов на эту ситуацию. Добавили алерт на prometheus_remote_storage_failed_samples_total - если счётчик растёт, надо разбираться.
В InfluxDB настроили два Retention Policy: один на 7 дней с полной детализацией (1 минута), второй на 365 дней с downsampling через Continuous Queries до 5-минутных агрегатов. Grafana умеет переключаться между ними по выбранному диапазону времени через разные datasource.
Federation для нескольких площадок
Когда у клиента два датацентра или продакшн-сеть плюс отдельный DMZ, встаёт вопрос как мониторить всё это из одного места. Prometheus federation - механизм где один «центральный» Prometheus scrape-ит /federate endpoint от «локальных» Prometheus-ов, получая нужные метрики.
Схема которую используем:
Площадка A Площадка B
Prometheus-A :9090 Prometheus-B :9090
node_exporter node_exporter
cAdvisor cAdvisor
| |
| federation scrape |
+----------+ +-------------+
| |
Prometheus-central
(на нашей стороне)
|
Alertmanager
Grafana
Центральный Prometheus не scrape-ит конечные цели напрямую - только /federate эндпоинт на каждом локальном. Это означает что при недоступности площадки A, центральный Prometheus теряет её метрики, но метрики площадки B продолжают приходить нормально.
Конфиг federation scrape в центральном Prometheus:
scrape_configs:
- job_name: 'federate-site-a'
scrape_interval: 30s
honor_labels: true
metrics_path: '/federate'
params:
'match[]':
- '{job=~"node-exporter|cadvisor"}'
- 'up'
static_configs:
- targets: ['prometheus-a.site-a.internal:9090']
labels:
site: 'site-a'
honor_labels: true - обязательный параметр. Без него центральный Prometheus перезапишет labels из локального своими значениями, и вы потеряете instance метки оригинальных целей.
Что важно понимать про federation: это не репликация и не failover. Если локальный Prometheus перезапустился и потерял данные за последний час, центральный тоже не будет знать об этом часе. Federation - это агрегация для высокоуровневого мониторинга, а не резервное копирование метрик.
На практике разделили что живёт где: детальные метрики (CPU по контейнерам, RAM, диск) - только на локальных Prometheus-ах с 30-дневным retention. В центральном - агрегированные метрики уровня «площадка», SLA-метрики и up статусы всех сервисов. Grafana смотрит на центральный для overview-дашбордов и на локальные для детального дебага.
Мелкие вещи которые заняли время
Несколько наблюдений которые не тянут на раздел, но реально отняли время на отладку.
-storage.local.memory-chunks и OOM. При большом числе временных рядов дефолтное значение приводит к нехватке памяти. Выставляем явно исходя из доступной RAM: примерно по 3072 чанка на каждый ГБ памяти выделенной Prometheus. Не точная формула, но рабочая отправная точка.
Alertmanager и federation. Алерты должны приходить только из одного Alertmanager, даже если у вас несколько Prometheus-ов. Иначе получаете дублирующиеся уведомления при любом алерте. Конфигурируем все Prometheus-ы (и локальные, и центральный) на один Alertmanager.
external_labels в конфиге. Добавляем в каждый локальный Prometheus метки site и env через global.external_labels. Это позволяет в Alertmanager и Grafana сразу видеть откуда пришёл алерт без разбора по IP адресам.
Prometheus 1.7 - рабочий инструмент, который требует осознанной настройки под реальную нагрузку. Дефолты покрывают только демо-стенд.