Внутреннее устройство Prometheus, pull vs push модель, типы метрик и временные ряды
«Понимание архитектуры экономит часы отладки»
Можно скопировать конфиг из туториала и запустить Prometheus. Но когда что-то пойдёт не так (а оно пойдёт), вы будете беспомощны.
Понимание того, как Prometheus собирает, хранит и обрабатывает метрики, даст вам:
Prometheus — это не один бинарник, а экосистема компонентов:
┌─────────────────────────────────────────────────────────────┐
│ Prometheus Server │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Scraper │ │ TSDB │ │ HTTP Server │ │
│ │ (сбор) │ │ (хранение) │ │ (запросы API) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Targets │ │ Disk │ │ Grafana │
│(экспортеры)│ │(данные) │ │ UI │
└──────────┘ └──────────┘ └──────────┘
Ядро системы. Один бинарник, который делает всё:
Важно: Prometheus — это single binary. Никаких отдельных сервисов для сбора, хранения и запросов. Это упрощает развёртывание и отладку.
Targets — это источники метрик, которые Prometheus опрашивает.
Обычно targets — это экспортёры: небольшие сервисы, которые отдают метрики в формате Prometheus.
Примеры экспортёров:
Каждый target отдаёт метрики на HTTP-эндпоинте (обычно /metrics):
# Пример ответа от target
$ curl http://localhost:9100/metrics
# HELP node_cpu_seconds_total Seconds the CPUs spent in each mode.
# TYPE node_cpu_seconds_total counter
node_cpu_seconds_total{cpu="0",mode="idle"} 123456.78
node_cpu_seconds_total{cpu="0",mode="user"} 23456.12Service Discovery (обнаружение сервисов) — механизм, который говорит Prometheus, какие цели опрашивать.
В простейшем случае — это статический список в конфиге:
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['localhost:9100', 'server2:9100']Но в динамической среде (Docker, Kubernetes) цели постоянно меняются. Тогда используют динамическое обнаружение:
TSDB — встроенная база данных временных рядов.
Ключевые особенности:
Структура хранения:
prometheus_data/
├── wal/ # Write Ahead Log (последние данные)
├── 01ABCDEF... # Блок за 1 час
├── 01GHIJKL... # Блок за следующий час
└── ...
WAL (Write Ahead Log) хранит последние 2-3 часа данных для быстрого доступа. Старые данные упаковываются в блоки (по 1 часу по умолчанию) и сжимаются.
Prometheus предоставляет HTTP API для:
/api/v1/query)/api/v1/query_range)/api/v1/targets, /api/v1/rules)/api/v1/admin/tsdb/snapshot — снятие снепшотов)Grafana и другие инструменты используют это API для получения данных.
Давайте проследим путь метрики от источника до запроса:
1. Сбор 2. Обработка 3. Хранение 4. Запрос
↓ ↓ ↓ ↓
Target → Prometheus → TSDB → PromQL → Результат
Prometheus по расписанию (по умолчанию каждые 15 секунд) делает HTTP-запрос к каждому target:
GET /metrics HTTP/1.1
Host: localhost:9100
Target отвечает текстом в формате Prometheus:
# HELP node_memory_MemTotal_bytes Memory information field MemTotal_bytes.
# TYPE node_memory_MemTotal_bytes gauge
node_memory_MemTotal_bytes 16777216000
Важно: формат текстовый, человекочитаемый. Это упрощает отладку — можно просто curl и посмотреть.
Prometheus парсит ответ и преобразует в внутренний формат:
Метрика: node_memory_MemTotal_bytes
Тип: gauge
Значение: 16777216000
Время: 2026-03-18T14:30:00Z
Лейблы: {instance="localhost:9100", job="node"}
Лейблы добавляются автоматически:
instance — адрес target (хост:порт)job — имя задачи из конфигурацииМожно добавлять свои лейблы через relabel_configs.
Метрика записывается в TSDB:
Важно: Prometheus хранит данные локально. Для долгосрочного хранения и глобального поиска нужны дополнительные инструменты (Thanos, Cortex, Mimir).
Пользователь пишет PromQL-запрос:
node_memory_MemTotal_bytes{instance="localhost:9100"}Prometheus:
Prometheus понимает четыре типа метрик. Понимание типов критично для правильных запросов.
Counter — метрика, которая только растёт (или сбрасывается в 0).
Примеры:
http_requests_total{method="GET", path="/api"} 12345
Важно: counter не может уменьшаться. Если он уменьшился (например, после перезапуска), Prometheus считает это reset и корректирует расчёты.
Когда использовать: для подсчёта событий за период времени.
Типичный запрос: «сколько запросов в секунду?»
rate(http_requests_total[5m]) # запросов в секунду за последние 5 минутGauge — метрика, которая может расти и уменьшаться.
Примеры:
node_memory_MemAvailable_bytes 8589934592
Когда использовать: для измерения текущего состояния.
Типичный запрос: «сколько памяти доступно сейчас?»
node_memory_MemAvailable_bytes # текущее значениеHistogram — распределение значений по «корзинам» (buckets).
Примеры:
http_request_duration_seconds_bucket{le="0.1"} 100 # 100 запросов <= 100ms
http_request_duration_seconds_bucket{le="0.25"} 150 # 150 запросов <= 250ms
http_request_duration_seconds_bucket{le="0.5"} 180 # 180 запросов <= 500ms
http_request_duration_seconds_bucket{le="+Inf"} 200 # всего 200 запросов
http_request_duration_seconds_sum 45.5 # сумма всех времён
http_request_duration_seconds_count 200 # количество запросов
Важно: histogram создаёт несколько метрик автоматически:
..._bucket — по одной на каждый bucket..._sum — сумма всех значений..._count — количество наблюденийКогда использовать: для анализа распределения (например, перцентили задержки).
Типичный запрос: «95-й перцентиль времени ответа?»
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))Summary — как histogram, но вычисляет перцентили на стороне клиента.
Примеры:
http_request_duration_seconds{quantile="0.5"} 0.1 # 50-й перцентиль = 100ms
http_request_duration_seconds{quantile="0.95"} 0.25 # 95-й перцентиль = 250ms
http_request_duration_seconds_sum 45.5
http_request_duration_seconds_count 200
Разница с histogram:
Когда использовать: реже, чем histogram. Summary нельзя агрегировать, что ограничивает гибкость запросов.
Prometheus группирует цели для удобства:
Job — логическая группа целей (например, «node», «api», «database»).
Instance — конкретный target внутри job (например, localhost:9100, server2:9100).
scrape_configs:
- job_name: 'node' # ← Job
static_configs:
- targets: # ← Instances
- 'localhost:9100'
- 'server2:9100'В метрики автоматически добавляются лейблы:
job="node"instance="localhost:9100"Это позволяет фильтровать:
{job="node"}{instance="localhost:9100"}Мы уже говорили, что Prometheus использует pull-модель. Давайте разберём последствия этого решения.
Решение для batch jobs: Pushgateway — отдельный сервис, который принимает метрики от кратковременных задач, а Prometheus забирает их оттуда.
В следующей теме мы развернём Prometheus и Grafana в Docker Compose. Вы увидите архитектуру в действии и сможете поиграть с реальной системой.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.