Мониторинг и наблюдаемость: Prometheus, Grafana, ELK — как настроить и что отслеживать в первую очередь

Мониторинг и наблюдаемость: Prometheus, Grafana, ELK — как настроить и что отслеживать в первую очередь

Проблема: вы запустили приложение в продакшен. Пользователи жалуются на медленную работу, но вы не знаете где именно проблема. База данных? Сеть? Какой-то из 15 микросервисов? Без мониторинга вы слепой пилот.

Решение: мониторинг и наблюдаемость. 67% компаний используют Prometheus в продакшене, 70% комбинируют Prometheus с Grafana. Для логов стандарт де-факто — стек ELK (Elasticsearch, Logstash, Kibana).

Цифры: команды с хорошей наблюдаемостью на 90% быстрее находят проблемы, среднее время восстановления падает с 45 до 25 минут.

В статье: разница между мониторингом и наблюдаемостью, как настроить Prometheus + Grafana, как настроить ELK, какие показатели отслеживать в первую очередь (четыре золотых сигнала), примеры запросов и панелей.

1. Мониторинг против наблюдаемости: в чём разница

Мониторинг — отслеживание заранее определённых показателей и оповещения когда что-то идёт не так.

Наблюдаемость — способность понять внутреннее состояние системы по её выходным данным (показатели, логи, трассировки).

Простая аналогия:

  • Мониторинг — панель приборов в машине. Показывает скорость, уровень топлива, предупреждения

  • Наблюдаемость — открыть капот и понять почему загорелась лампочка

АспектМониторингНаблюдаемость

Подход

Реактивный (реагирует после)Проактивный (предсказывает до)

Фокус

Известные показателиПонимание неизвестного

Вопрос

"Что сломалось?""Почему сломалось? Как исправить?"

Данные

Показатели, оповещенияПоказатели + логи + трассировки

Цель

Определить проблемуПонять первопричину

Системы

Хорошо для простых системНеобходимо для распределённых систем

Пример:

Мониторинг: "Оповещение! Использование процессора 95%"

Наблюдаемость: "Процессор нагружен потому что сервис оплаты отправляет 1000 повторных запросов к базе из-за тайм-аута соединения который вызван сетевой задержкой между серверами"

Три столпа наблюдаемости:

  1. Показатели (метрики): числовые измерения производительности во времени (загрузка процессора, использование памяти, запросы в секунду)

  2. Логи: детальные записи событий в приложениях (кто, что, когда)

  3. Трассировки: путь запроса через все микросервисы (откуда пришёл, куда пошёл, сколько времени в каждом сервисе)

Вывод: вам нужно и то и другое. Мониторинг говорит "что-то не так", наблюдаемость помогает понять "что именно и почему".

2. Что отслеживать в первую очередь: четыре золотых сигнала

Google в своей книге по инженерии надёжности сайтов описал четыре ключевых показателя которые нужно отслеживать в любой системе:

1. Задержка (Latency)

Время ответа на запрос. Важно: отдельно считайте задержку успешных и неудачных запросов.

Что смотреть:

  • 50-й перцентиль (медиана) — типичный пользовательский опыт

  • 95-й перцентиль — опыт более медленных 5% запросов

  • 99-й перцентиль — опыт самых медленных 1% запросов

Не используйте среднее значение! Среднее скрывает выбросы. Если 99% запросов 100мс, а 1% — 10 секунд, среднее покажет 199мс и вы не увидите проблему.

2. Трафик (Traffic)

Сколько нагрузки получает ваша система.

Примеры:

  • Веб-сервис: HTTP запросов в секунду

  • База данных: транзакций в секунду

  • Стриминг: гигабайт в секунду

3. Ошибки (Errors)

Процент неудачных запросов.

Типы ошибок:

  • Явные: HTTP 500, 503, исключения

  • Неявные: HTTP 200 но с некорректными данными

  • Политические: запрос успешен но нарушает соглашение об уровне обслуживания (ответ за 3 секунды вместо обещанных 300мс)

4. Насыщенность (Saturation)

Насколько заполнены ресурсы системы.

Примеры:

  • Загрузка процессора: 80% от максимума

  • Использование памяти: 12ГБ из 16ГБ

  • Заполнение диска: 450ГБ из 500ГБ

  • Очередь запросов: 50 запросов в ожидании

Важно: большинство систем начинают деградировать до достижения 100%. Например, база данных может замедляться уже на 80% использования процессора.

Вариации: RED и USE

RED метод (для микросервисов и API):

  • Rate (Частота): запросов в секунду

  • Errors (Ошибки): число неудачных запросов

  • Duration (Длительность): время обработки запроса

USE метод (для инфраструктуры: серверы, диски):

  • Utilization (Утилизация): процент времени когда ресурс занят

  • Saturation (Насыщенность): объём работы которую ресурс не может обслужить

  • Errors (Ошибки): счётчик ошибок ресурса

3. Prometheus + Grafana: настройка и примеры

Что это

Prometheus: система мониторинга с открытым кодом для сбора и хранения показателей временных рядов. Разработана в SoundCloud в 2012, сейчас второй проект (после Kubernetes) принятый в Cloud Native Computing Foundation.

Grafana: платформа визуализации. Не хранит данные, а запрашивает их из источников (Prometheus, Elasticsearch, и др) и отрисовывает панели.

Почему это стандарт:

  • 75% внедрений Kubernetes используют Prometheus

  • 67% компаний используют Prometheus в продакшене

  • Prometheus 2.51 (апрель 2025) обрабатывает миллионы активных серий на обычных дисках

Быстрая установка через Docker

# docker-compose.yml
version: '3'
services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    ports:
      - "9090:9090"
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.retention.time=15d'
  
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  prometheus-data:
  grafana-data:

Конфигурация Prometheus

# prometheus.yml
global:
  scrape_interval: 15s  # Как часто собирать показатели
  evaluation_interval: 15s  # Как часто проверять правила

# Откуда собирать показатели
scrape_configs:
  # Мониторинг самого Prometheus
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # Мониторинг хоста (нужен node_exporter)
  - job_name: 'node'
    static_configs:
      - targets: ['node-exporter:9100']

  # Мониторинг вашего приложения
  - job_name: 'my-app'
    static_configs:
      - targets: ['my-app:8080']

Экспортеры (exporters)

Экспортеры — компоненты которые собирают показатели из систем которые сами их не отдают.

ЭкспортерДля чегоОсновные показатели

node_exporter

Сервера LinuxПроцессор, память, диск, сеть

windows_exporter

Сервера WindowsПроцессор, память, диск, сеть

mysqld_exporter

MySQL базыЗапросы, соединения, репликация

postgres_exporter

PostgreSQL базыСоединения, блокировки, размер

redis_exporter

RedisПамять, попадания, промахи

blackbox_exporter

Проверки доступностиHTTP, DNS, TCP, ICMP

Язык запросов PromQL

Примеры полезных запросов:

# Загрузка процессора (в процентах)
100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# Использование памяти (в процентах)
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100

# Свободное место на диске (в процентах)
100 - ((node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100)

# Запросы в секунду
rate(http_requests_total[5m])

# Процент ошибок
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100

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

# 99-й перцентиль задержки
histogram_quantile(0.99, 
  rate(http_request_duration_seconds_bucket[5m])
)

Подключение Grafana к Prometheus

  1. Откройте Grafana: http://localhost:3000

  2. Войдите (логин: admin, пароль: admin)

  3. Меню → Configuration → Data Sources → Add data source

  4. Выберите Prometheus

  5. URL: http://prometheus:9090

  6. Save & Test

Готовые панели

На grafana.com/grafana/dashboards тысячи готовых панелей.

Популярные:

  • ID 1860: Node Exporter Full (детальные показатели сервера)

  • ID 3662: Prometheus 2.0 Stats (статистика самого Prometheus)

  • ID 7249: Kubernetes Cluster Monitoring

  • ID 9628: PostgreSQL Database

Импорт панели:

  1. Grafana → Dashboards → Import

  2. Введите ID панели (например 1860)

  3. Load → выберите источник Prometheus → Import

Настройка оповещений в Grafana

# Пример: оповещение если загрузка процессора > 80%

Alerting → Alert rules → Create alert rule

Query A:
100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

Condition:
WHEN last() OF query(A) IS ABOVE 80

Evaluate: every 1m for 5m  # Проверять каждую минуту, срабатывать если 5 минут подряд

Notifications:
- Email
- Slack
- Telegram
- PagerDuty

4. ELK Stack: логи и их анализ

Что такое ELK

ELK — аббревиатура трёх компонентов:

  • Elasticsearch: поисковая и аналитическая база данных. Хранит и индексирует логи

  • Logstash: конвейер обработки данных. Собирает логи из разных источников, обрабатывает, отправляет в Elasticsearch

  • Kibana: веб-интерфейс для визуализации. Строит графики и панели по данным из Elasticsearch

+ Beats: лёгкие сборщики данных (Filebeat для файлов, Metricbeat для показателей, и т.д.)

Современная альтернатива Logstash: многие заменяют Logstash на Fluentd или Fluent Bit — они легче и быстрее.

Почему ELK для логов

В распределённой системе логи разбросаны по десяткам серверов. Нужно централизованное хранилище где можно:

  • Искать по всем логам сразу

  • Фильтровать по уровню (info, warning, error)

  • Смотреть контекст вокруг ошибки

  • Строить графики по частоте ошибок

  • Находить корреляции между событиями

Установка через Docker

# docker-compose.yml для ELK
version: '3'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
    volumes:
      - elasticsearch-data:/usr/share/elasticsearch/data

  kibana:
    image: docker.elastic.co/kibana/kibana:8.11.0
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch

  logstash:
    image: docker.elastic.co/logstash/logstash:8.11.0
    ports:
      - "5044:5044"
    volumes:
      - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
    depends_on:
      - elasticsearch

volumes:
  elasticsearch-data:

Конфигурация Logstash

# logstash.conf
input {
  # Принимать логи через Beats
  beats {
    port => 5044
  }
  
  # Или через TCP
  tcp {
    port => 5000
    codec => json
  }
}

filter {
  # Парсинг JSON логов
  if [message] =~ /^\{/ {
    json {
      source => "message"
    }
  }
  
  # Парсинг даты
  date {
    match => ["timestamp", "ISO8601"]
  }
  
  # Добавление геолокации по IP
  geoip {
    source => "client_ip"
  }
}

output {
  # Отправка в Elasticsearch
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "logs-%{+YYYY.MM.dd}"
  }
  
  # Дублирование в консоль для отладки
  stdout {
    codec => rubydebug
  }
}

Структурированные логи в приложении

Вместо обычного текста отправляйте JSON:

# Плохо (неструктурированный лог)
logger.info("User logged in")

# Хорошо (структурированный лог)
logger.info({
  "event": "user_login",
  "user_id": 12345,
  "ip": "192.168.1.1",
  "timestamp": "2026-02-02T10:30:00Z",
  "level": "info"
})

Почему структурированные логи:

  • Легко фильтровать по полям

  • Не нужны регулярные выражения для парсинга

  • Быстрее индексация в Elasticsearch

  • Можно строить агрегации (сколько логинов за час)

Настройка Kibana

  1. Откройте Kibana: http://localhost:5601

  2. Management → Stack Management → Index Patterns

  3. Create index pattern → введите logs-*

  4. Выберите поле времени: @timestamp

  5. Create index pattern

Полезные запросы в Kibana

# Все ошибки за последний час
level:error

# Ошибки конкретного сервиса
level:error AND service_name:"payment-service"

# HTTP 500 ошибки
http.status_code:500

# Медленные запросы (больше 1 секунды)
response_time:>1000

# Ошибки конкретного пользователя
user_id:12345 AND level:error

# Комбинация фильтров
service_name:"auth-service" AND (level:error OR level:critical)

Визуализации в Kibana

Что создать:

  1. Метрика: общее количество ошибок за период

  2. Круговая диаграмма: распределение логов по уровням (info 80%, warning 15%, error 5%)

  3. Линейный график: количество ошибок во времени

  4. Таблица топ-10: какие сервисы генерируют больше всего ошибок

  5. Тепловая карта: ошибки по времени суток и дням недели

5. Что мониторить в первую очередь: чек-лист по приоритетам

Приоритет 1: Критичные показатели (без них система слепая)

Для веб-приложений:

  • ☐ Запросы в секунду

  • ☐ Задержка ответа (50-й, 95-й, 99-й перцентили)

  • ☐ Процент ошибок (4xx, 5xx)

  • ☐ Доступность сервиса (uptime)

Для инфраструктуры:

  • ☐ Загрузка процессора

  • ☐ Использование памяти

  • ☐ Свободное место на диске

  • ☐ Сетевой трафик (входящий/исходящий)

Для баз данных:

  • ☐ Количество подключений

  • ☐ Время выполнения запросов

  • ☐ Медленные запросы (больше 1 секунды)

  • ☐ Размер базы данных

  • ☐ Статус репликации

Приоритет 2: Бизнес-показатели (влияют на деньги)

  • ☐ Регистрации пользователей в час

  • ☐ Успешных оплат в минуту

  • ☐ Конверсия оформления заказа

  • ☐ Время до первого взаимодействия пользователя

  • ☐ Процент брошенных корзин

Приоритет 3: Показатели опыта пользователя

  • ☐ Время загрузки страницы (Real User Monitoring)

  • ☐ Время до интерактивности

  • ☐ Ошибки JavaScript на клиенте

  • ☐ Процент успешных действий пользователя

Приоритет 4: Детальные показатели (для глубокой диагностики)

  • ☐ Попадания в кеш / промахи

  • ☐ Размер очереди сообщений

  • ☐ Число открытых файловых дескрипторов

  • ☐ Сборка мусора (garbage collection)

  • ☐ Размер пула соединений к базе

6. Настройка оповещений: что и когда оповещать

Проблема шумных оповещений

Если оповещения срабатывают каждые 5 минут, команда начинает их игнорировать. Правило: оповещение должно означать "кто-то должен действовать прямо сейчас".

Уровни серьёзности

УровеньКогдаДействиеКанал

Критичный

Сервис недоступен, данные теряютсяНемедленное вмешательствоПейджер, звонок

Высокий

Деградация производительности, многие пользователи затронутыДействие в течение 15 минутSlack, SMS

Средний

Проблема затрагивает часть пользователейДействие в рабочее времяEmail, Slack

Низкий

Потенциальная проблема в будущемЗапланировать исправлениеТикет, email

Примеры хороших оповещений

# Критичный: сервис недоступен
Оповещение: Сервис платежей недоступен
Условие: rate(http_requests_total{job="payment-service"}[5m]) == 0
Длительность: 2 минуты
Действие: Немедленно проверить, откатить последний деплой если нужно

# Высокий: высокий процент ошибок
Оповещение: Высокий процент ошибок 5xx
Условие: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
Длительность: 5 минут
Действие: Проверить логи, найти причину

# Средний: медленные ответы
Оповещение: Задержка 99-го перцентиля выше SLA
Условие: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1.0
Длительность: 10 минут
Действие: Профилировать приложение, оптимизировать запросы

# Низкий: диск заполняется
Оповещение: Диск заполнится через 4 часа
Условие: predict_linear(node_filesystem_free_bytes[1h], 4*3600) < 0
Длительность: 30 минут
Действие: Очистить логи, увеличить диск

Правила оповещений

  1. Оповещайте о симптомах, а не о причинах: "API медленный" (симптом) лучше чем "Загрузка процессора 80%" (причина)

  2. Используйте время ожидания: не оповещайте при первом превышении порога, подождите 5 минут чтобы исключить краткосрочные всплески

  3. Группируйте похожие оповещения: не отправляйте 50 оповещений если падает целый датацентр, отправьте одно "Датацентр US-EAST недоступен"

  4. Добавляйте контекст: оповещение должно содержать ссылку на панель, runbook, график

  5. Регулярно пересматривайте: если оповещение срабатывает но никто не действует — удалите его

7. Лучшие практики: как не утонуть в данных

1. Начинайте с четырёх золотых сигналов

Не пытайтесь мониторить всё сразу. Начните с задержки, трафика, ошибок, насыщенности. Это даст вам 80% понимания состояния системы.

2. Используйте метки (labels) правильно

Плохо: создавать отдельную метрику для каждого пользователя:

user_123_requests_total
user_456_requests_total

Хорошо: одна метрика с метками:

requests_total{user_id="123"}
requests_total{user_id="456"}

Правило: используйте метки для измерений с низкой кардинальностью (десятки значений, не миллионы). Не создавайте метку для ID пользователя если у вас миллион пользователей.

3. Настройте хранение данных

  • Высокое разрешение (15 секунд): храните 1-3 дня

  • Среднее разрешение (1 минута): храните 7-15 дней

  • Низкое разрешение (5 минут): храните 90 дней

  • Долгосрочное хранение: используйте Thanos или Cortex для агрегации и хранения в объектном хранилище (дешёво)

4. Создавайте панели для инцидентов, не для красоты

Лучшие панели помогают во время проблем, а не просто красиво выглядят.

Структура панели для инцидентов:

  1. Обзорная панель вверху: общее состояние системы, активные оповещения, ключевые показатели

  2. Секции по сервисам: каждый критичный сервис — своя строка с показателями

  3. Ссылки на ресурсы: runbook, инструкции, процедуры эскалации

  4. Корреляции: ошибки приложения + недавние изменения инфраструктуры

5. Автоматизируйте там где возможно

Используйте инфраструктуру как код:

  • Конфигурация Prometheus — в Git

  • Панели Grafana — экспорт в JSON, хранение в Git

  • Правила оповещений — версионирование

  • Развёртывание — через Terraform, Ansible, Helm

6. Логи: храните недолго, индексируйте выборочно

Полнотекстовая индексация всех логов дорогая.

Стратегия:

  • Info логи: храните 3-7 дней, индексируйте только временные метки и поля

  • Warning/Error логи: храните 30 дней, полная индексация

  • Аудит логи: храните 1-2 года, архивируйте в объектное хранилище

Альтернатива ELK: Grafana Loki индексирует только метки, а не весь текст логов. Это дешевле на порядок и быстрее для большинства задач.

8. Частые ошибки

Ошибка 1: Мониторить всё подряд

Команды пытаются собирать тысячи показателей "на всякий случай". Результат: огромные затраты на хранение, панели бесполезны во время инцидента.

Как избежать: начните с четырёх золотых сигналов. Добавляйте новые показатели только когда они помогли бы решить реальный инцидент.

Ошибка 2: Использовать среднее значение вместо перцентилей

Среднее скрывает выбросы. Если 99% запросов отвечают за 100мс, а 1% за 30 секунд, среднее покажет 400мс и вы не увидите что 1% пользователей страдает.

Как избежать: всегда смотрите на перцентили: 50-й (медиана), 95-й, 99-й.

Ошибка 3: Оповещения без действия

Оповещение "Загрузка процессора 80%" срабатывает, команда смотрит, ничего не делает, оповещение исчезает само.

Как избежать: каждое оповещение должно требовать действия. Если не требует — удалите оповещение или повысьте порог.

Ошибка 4: Нет runbook для оповещений

Срабатывает оповещение в 3 часа ночи, дежурный не знает что делать.

Как избежать: для каждого оповещения создайте runbook с шагами диагностики и исправления.

Ошибка 5: Логи без структуры

Неструктурированные текстовые логи невозможно эффективно анализировать.

Как избежать: используйте структурированные логи (JSON), включайте поля: timestamp, level, service_name, request_id.

Ошибка 6: Не корреляция данных

Показатели в Prometheus, логи в ELK, трассировки в Jaeger — всё раздельно.

Как избежать: используйте единый идентификатор запроса (trace_id) во всех системах. Добавляйте ссылки между системами (из панели Grafana на логи в Kibana).

9. Чек-лист запуска мониторинга

Месяц 1: Базовый мониторинг

  1. ☐ Установить Prometheus + Grafana

  2. ☐ Установить node_exporter на все сервера

  3. ☐ Настроить сбор показателей инфраструктуры (процессор, память, диск)

  4. ☐ Импортировать готовую панель Node Exporter Full (ID 1860)

  5. ☐ Настроить первое оповещение (например, диск заполнен на 90%)

Месяц 2: Мониторинг приложений

  1. ☐ Добавить в приложение экспорт показателей (эндпоинт /metrics)

  2. ☐ Начать собирать четыре золотых сигнала (задержка, трафик, ошибки, насыщенность)

  3. ☐ Создать панель для каждого критичного сервиса

  4. ☐ Настроить оповещения для высокого процента ошибок

Месяц 3: Централизованные логи

  1. ☐ Установить ELK Stack

  2. ☐ Настроить Filebeat на серверах для отправки логов

  3. ☐ Переключить приложения на структурированные логи (JSON)

  4. ☐ Создать панели в Kibana для ошибок по сервисам

  5. ☐ Настроить оповещение на всплески ошибок в логах

Месяц 4+: Углубление

  1. ☐ Добавить мониторинг баз данных (mysqld_exporter, postgres_exporter)

  2. ☐ Настроить распределённую трассировку (Jaeger или Tempo)

  3. ☐ Корреляция показателей, логов и трассировок через trace_id

  4. ☐ Создать runbook для каждого оповещения

  5. ☐ Настроить долгосрочное хранение (Thanos для показателей)

  6. ☐ Регулярный пересмотр оповещений (удаление шумных)

10. Стоимость мониторинга

Самостоятельное развёртывание (открытый код)

Затраты:

  • Сервера: ~$200-500/месяц (зависит от объёма данных)

  • Хранилище: ~$50-200/месяц

  • Время инженеров: 20-40 часов/месяц на настройку и поддержку

  • Итого: $250-700/месяц + время команды

Управляемые решения

СервисСтоимостьЧто включено

Grafana Cloud

От $0 (50ГБ логов, 10К серий бесплатно)Prometheus + Loki + Tempo + Grafana

Datadog

От $15/хост/месяцВсё включено + APM

New Relic

От $0 (100ГБ + 1 пользователь)Показатели, логи, трассировки

Elastic Cloud

От $95/месяцУправляемый ELK Stack

Окупаемость

Один серьёзный инцидент может стоить $50,000-500,000 (простой + потеря выручки + репутация).

Хороший мониторинг:

  • Обнаруживает проблемы на 60% быстрее

  • Сокращает время восстановления с 45 до 25 минут

  • Предотвращает 30-40% инцидентов (проактивное обнаружение)

Если мониторинг предотвратит 2 крупных инцидента в год, он окупится в 50-500 раз.

Вывод: начните с бесплатных инструментов открытого кода (Prometheus + Grafana + ELK). Когда команда вырастет или нужен меньше операционных хлопот — рассмотрите управляемые решения.

А лучшие вакансии для DevOps ищите на hirehi.ru