Prometheus стандарт де-факто для метрик в облачной инфраструктуре: сам опрашивает цели, хранит временные ряды у себя и умеет вычислять по ним правила и алерты. Актуальная мажорная версия третья (Prometheus 3.x).
Модель данных
Временной ряд определяется именем метрики и набором меток:
http_requests_total{job="api", instance="10.0.1.5:8080", method="GET", status="200"} 1027
Каждая уникальная комбинация меток это отдельный ряд. Сэмпл это пара (время, число с плавающей точкой).
Типы метрик
- Counter: только растёт (и сбрасывается при рестарте процесса). Запросы, ошибки, байты. Имя по соглашению с
_total. Само значение почти не интересно, смотрят скорость роста черезrate(). - Gauge: может расти и падать. Память, температура, длина очереди, число активных соединений.
- Histogram: распределение значений по бакетам. Даёт ряды
_bucket{le="..."}(накопительные: сколько наблюдений не большеle),_sumи_count. Перцентили считаются на стороне сервера черезhistogram_quantile, гистограммы можно складывать между экземплярами. - Summary: квантили считает сам клиент. Точнее для одного экземпляра, но квантили разных экземпляров нельзя корректно сложить. В большинстве случаев выбирают гистограмму.
В новых версиях есть нативные гистограммы с автоматическими бакетами; классические с явными бакетами по-прежнему встречаются чаще всего.
Формат экспозиции
Приложение отдаёт текст на /metrics:
# HELP http_requests_total Total HTTP requests.
# TYPE http_requests_total counter
http_requests_total{method="GET",status="200"} 1027
http_requests_total{method="POST",status="500"} 3
Также поддерживается OpenMetrics, а Prometheus 3 умеет принимать метрики по OTLP от OpenTelemetry.
Pull-модель
Prometheus сам ходит на /metrics целей раз в scrape_interval (по умолчанию 1 минута, на практике часто 15-30 секунд). Плюсы: Prometheus знает, жива ли цель (метрика up), цели не нужно знать про сервер мониторинга, легко опросить вручную curl. Для коротких batch-задач, которые не доживут до опроса, есть Pushgateway, но только для них: через Pushgateway теряется up, а метрики умерших задач висят вечно.
Где брать метрики
- Инструментирование кода: клиентские библиотеки Prometheus или OpenTelemetry.
- Экспортёры для того, что нельзя изменить:
node_exporter(метрики Linux-узла, порт 9100),postgres_exporter,redis_exporter,blackbox_exporter(проверки HTTP, TCP, ICMP и сертификатов снаружи),kube-state-metrics(состояние объектов Kubernetes), cAdvisor (контейнеры, встроен в kubelet).
Service discovery и relabeling
Цели находятся автоматически: kubernetes_sd_configs, облака, Consul, файлы. Relabeling переписывает метки целей до опроса (relabel_configs: оставить только поды с аннотацией, взять порт из аннотации, добавить метку team) и метрики после (metric_relabel_configs: выбросить ненужные ряды или метки). В Kubernetes обычно используют Prometheus Operator и объекты ServiceMonitor и PodMonitor.
Recording rules
Тяжёлые запросы заранее вычисляют правилом и сохраняют как новый ряд:
groups:
- name: api
rules:
- record: job:http_requests:rate5m
expr: sum by (job) (rate(http_requests_total[5m]))
Дашборды и алерты работают быстрее, а имена по соглашению уровень:метрика:операции.
Хранение
Локальная TSDB: свежие данные в памяти и WAL, каждые 2 часа сбрасываются в блок на диске, блоки уплотняются. Ретеншн по умолчанию 15 дней (--storage.tsdb.retention.time). Prometheus сознательно сделан одиночным узлом без кластеризации. Для долгого хранения, глобального взгляда и отказоустойчивости используют remote_write в Thanos, Grafana Mimir или VictoriaMetrics.
Высокая доступность: два одинаковых Prometheus опрашивают одни и те же цели, Alertmanager дедуплицирует их алерты, а Thanos или Mimir склеивают данные.
Кардинальность
Главный враг Prometheus. Память растёт с числом активных рядов. Источники взрыва: ID в метках (user_id, request_id, полный URL с параметрами), неограниченные значения (текст ошибки). Диагностика: страница TSDB Status показывает метрики и метки с наибольшим числом рядов; запрос topk(10, count by (__name__) ({__name__=~".+"})) тяжёлый, но тоже работает на небольших инсталляциях.
Частые ошибки
- Смотреть на сырое значение counter вместо
rate(). - Summary там, где нужно агрегировать по экземплярам.
- Pushgateway для долгоживущих сервисов.
- Полный путь с ID в метке
pathвместо шаблона маршрута/users/:id. - Один Prometheus без HA и бэкапа конфигов.
Что спросят на собесе
- Pull против push, зачем Pushgateway и когда он вреден.
- Четыре типа метрик, histogram против summary.
- Как Prometheus находит цели в Kubernetes.
- Что такое кардинальность и как её искать.
- Как хранить метрики год и сделать Prometheus отказоустойчивым.