Prometheus — мониторинг и алерты

Продолжительность: 19 уроков · Уровень: средний

Prometheus — система мониторинга с открытым кодом. Она собирает метрики с серверов и приложений по расписанию, хранит их и позволяет строить по ним запросы, правила алертов и графики. Вместе с Grafana это стандарт де-факто мониторинга в мире DevOps.

1. Как это работает

Pull-модель упрощает отказоустойчивость: если агент умер, это сразу видно по отсутствию данных (up = 0).

2. Установка

wget https://github.com/prometheus/prometheus/releases/download/v3.14.0/prometheus-3.14.0.linux-amd64.tar.gz
tar xzf prometheus-3.14.0.linux-amd64.tar.gz
cd prometheus-3.14.0.linux-amd64
./prometheus --config.file=prometheus.yml

UI доступен на http://localhost:9090.

Проще всего запускать через Docker: docker run -p 9090:9090 prom/prometheus.

3. Структура метрик

Метрика — это имя + метки + значение + временная метка:

node_cpu_seconds_total{mode="user", instance="server1:9100"} 12345.7

Типы метрик

ТипОписаниеПример
Counterтолько растёт (счётчик событий)requests_total
Gaugeможет падать и расти (значение)temperature_celsius
Histogramраспределение значений по корзинамrequest_duration_seconds
Summaryквантили на стороне приложенияlatency_summary

4. targets и scrape_configs

Список «целей» для сбора задаётся в prometheus.yml:

scrape_configs:
  - job_name: node
    metrics_path: /metrics
    static_configs:
      - targets: ["server1:9100", "server2:9100"]

  - job_name: app
    metrics_path: /actuator/prometheus
    static_configs:
      - targets: ["app-host:8080"]

5. Экспортеры

# node_exporter — метрики ОС
wget https://github.com/prometheus/node_exporter/releases/download/v1.12.1/node_exporter-1.12.1.linux-amd64.tar.gz
tar xzf node_exporter-1.12.1.linux-amd64.tar.gz
./node_exporter   # порт 9100

# blackbox_exporter — проверка доступности HTTP/TCP/ICMP

Готовые экспортеры

ЭкспортерЧто мониторит
node_exporterCPU, память, диск, сеть ОС
mysqld_exporterMySQL
postgres_exporterPostgreSQL
redis_exporterRedis
blackbox_exporterдоступность сервисов

6. PromQL — язык запросов

PromQL позволяет выбирать и агрегировать метрики:

up                              // по всем целям
node_memory_MemAvailable_bytes  // конкретная метрика
rate(http_requests_total[5m])   // скорость за последние 5 минут
sum(rate(http_requests_total[5m])) by (job)  // сумма по job

Частые операторы и функции

ВыражениеСмысл
rate(m[5m])скорость роста counter за окно
increase(m[1h])прирост за час
avg / sum / max / minагрегация
by (label) / without (label)группировка
{instance="x"}фильтр по метке

7. Правила и алерты

Правило — запрос, который проверяется по расписанию. Файл rules.yml подключается в конфиг:

rule_files:
  - rules.yml
groups:
  - name: node
    rules:
      - record: instance:node_cpu_usage
        expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

      - alert: NodeDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Нода {{ $labels.instance }} недоступна"

8. Alertmanager

Alertmanager принимает алерты и рассылает уведомления (email, Telegram, Slack):

route:
  receiver: team

receivers:
  - name: team
    email_configs:
      - to: ops@example.com
./alertmanager --config.file=alertmanager.yml

9. Хранение данных

По умолчанию данные сохраняются локально в ./data:

./prometheus \
  --config.file=prometheus.yml \
  --storage.tsdb.retention.time=30d \
  --storage.tsdb.retention.size=50GB
Локальное хранение — не бэкап. Для долгосрочного хранения используют remote write: Thanos, VictoriaMetrics или Cortex.

10. Интеграция с Kubernetes

Prometheus понимает service discovery: цели находятся не вручную, а из API кластера Kubernetes:

scrape_configs:
  - job_name: kubernetes-pods
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: "true"

11. Визуализация

Графики удобнее строить в Grafana, которая подключается к Prometheus как датасорс. Типовой стек мониторинга:

node_exporter + Prometheus + Grafana + Alertmanager

12. Экспорт метрик из своего приложения

Библиотеки клиентов для Python, Go, Java и др. отдают метрики по адресу /metrics:

# Python, библиотека prometheus_client
from prometheus_client import Counter, start_http_server

REQUESTS = Counter("http_requests_total", "Всего запросов")

def handler():
    REQUESTS.inc()

start_http_server(8000)   # /metrics на 8000

Названия метрик пиши по конвенции: суффикс _total для counter, _seconds для времени, юниты в имени.

http_requests_total{method="get", status="200"} 42
process_cpu_seconds_total 123.7
Для метрик, которые считаются редко, подойдёт textfile-коллектор node_exporter: скрипт пишет файл, экспортёр его читает.

13. Долгосрочное хранение: remote write

Локальный TSDB рассчитан на недели-месяцы. Для года данных используют remote-write в векторные хранилища:

remote_write:
  - url: http://thanos-receiver:19291/api/v1/receive
    queue_config:
      max_samples_per_send: 10000
Remote write не делает Prometheus общим: дашборды и правила продолжают жить на каждом экземпляре. Продумай метаданные и дедупликацию кластеров.

14. SLO и burn rate алерты

Вместо точечных границ по одной метрике считай SLO — целевую доступность сервиса за окно времени:

error_ratio = sum(rate(http_requests_total{status=~"5.."}[30m]))
            / sum(rate(http_requests_total[30m]))

Burn rate алерт: если ошибки за короткое окно превышают бюджет «сжигания» — это деградация, а не единичный блип.

Связывай алерты с playbook: ссылка на документ в annotations экономит минуты при инциденте.

15. Чек-лист продакшена

Начни с малого: node_exporter + базовые алерты, затем экспорт приложения, потом Thanos, если объёмы растут. Мониторинг строится итеративно.

Полный стек показан в курсах Grafana и Kubernetes: там дашборды и service discovery для подов.

16. Продвинутый PromQL: гистограммы и сравнение векторов

Настоящая ценность PromQL раскрывается при работе с гистограммами и бинарными операторами:

// 95-й перцентиль задержки из Histogram
histogram_quantile(0.95,
  sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

// отклонение от среднего по всем сервисам
node_cpu_usage - avg(node_cpu_usage)

// топ-3 по ошибкам
topk(3, sum(rate(http_errors_total[5m])) by (job))
histogram_quantile имеет смысл только для Bucket-переменной: применение к gauge-метрикам даёт мусорные значения.

17. Kubernetes: kube-prometheus и kube-state-metrics

Поверх service discovery из курса Kubernetes ставят готовый стек kube-prometheus: Operator, правила, dashboards и ServiceMonitors:

// ServiceMonitor может «прицелиться» на конкретный deployment
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata: { name: api-sm, namespace: production }
spec:
  selector:
    matchLabels: { app: api }
  endpoints:
    - port: metrics
      interval: 30s
Стартуй со стека kube-prometheus, а кастомные ServiceMonitors добавляй по мере роста — меньше ручной настройки, чем с чистым Prometheus.

18. Pushgateway и метрики batch-задач

Pull-модель не подходит для короткоживущих задач (cron, пайплайны): процесс закончился раньше, чем Prometheus успел его опросить. Для них — Pushgateway:

# после успешного прогона батча
cat batch_result.prom | curl --data-binary @- \
  http://pushgateway:9091/metrics/job/batch/stage/sync
# статус в PromQL
batch_last_success_time{job="cron_sync"} > time() - 3600   # алерт, если давно не было
Метрику «после прогона» всегда пиши как timestamp (last_success_time), а не как «сколько секунд прошёл» — так алерты стабильнее на дашбордах.

19. Отказоустойчивость и HA-стек

Один Prometheus — точка отказа. Классический HA-расклад — два независимых экземпляра + Thanos для чтения слитно:

Prometheus A ┐
              ├─> Thanos Query ─> Grafana
Prometheus B ┘
              └─> Thanos Store ─> S3 (долгий retention)
Физическое размещение двух экземпляров в одной зоне — мнимая защита. Разносить нужно по дата-центрам, иначе сбой зоны отрубит оба.

20. Self-мониторинг: метрики самого Prometheus

Prometheus собирает данные о себе на /metrics — добавь их в собственный dash-борд. Параметры, за которыми стоит следить:

# базовые метрики self-monitoring
prometheus_tsdb_head_series        # активные серии в TSDB
prometheus_tsdb_head_samples_appended_total  # скорость приёма samples
prometheus_remote_storage_pending_samples    # очередь remote write
Падение самого Prometheus незаметно изнутри: мониторинг мониторинга настраивай внешней системой — например, вторым инстансом (см. курс Thanos).

21. Relabeling: управление метками перед записью

Метки определяют кардинальность и удобство запросов. Два уровня перезаписи: target relabel (до сбора) и metric relabel (после сбора):

scrape_configs:
  - job_name: app
    relabel_configs:               # до scrape
      - source_labels: [__scheme__, __address__]
        target_label: endpoint
    metric_relabel_configs:        # после scrape
      - source_labels: [status]
        regex: 'ok|success'
        action: drop
Схема «уберут лишнее сейчас, добавят позже» — худшая практика. Записывай решение по меткам в README команды, чтобы расхождение стало видимым.

22. Alertmanager: группировка, ингибирование, тишины

Без группировки массовое падение отправляет десятки одинаковых уведомлений. Alertmanager объединяет алерты по правилам:

route:
  group_by: ['alertname', 'job']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
inhibit_rules:
  - source_matchers: ['severity=critical']
    target_matchers: ['severity=warning']
    equal: ['job']
Классический прогон: сломай сервис в staging и проверь, что приходит один групповой алерт, а не пять писем.

23. Кардинальность меток и оптимизация PromQL

Каждая комбинация значений меток — отдельная серия. Две метки по 100 значений — это 10 000 серий на одну метрику. Кардинальность — главный враг и TSDB, и скорости запросов:

ПриёмЭффект
не выносить в метки request_id, podсерии не раздуваются на миллионы
rate() + окна вместо total на большой глубинеменьше работы при чтении
recording rules для тяжёлых запросоврасчёт один раз, чтение — мгновенно
срез ненужных меток через metric_relabel_configsменьше серий в хранилище
агрегация только там, где нужнабез лишних операций в каждом запросе
# пример: считаем запросы только по нужным меткам
rate(api_requests_total{status=~"2[0-9][0-9]"}[5m])
Прежде чем добавить новую метку, спроси себя: «по ней будут делать group by?» Если нет — это alert-деталь, а не метка.

Что дальше

Подключи Prometheus к Grafana для красивых дашбордов, а логи собирай в ELK. Полный список курсов — на главной странице.

← Вернуться к курсам