Prometheus и Alertmanager: пошаговое построение алертинга для инфраструктуры | AdminWiki

Prometheus и Alertmanager: пошаговое построение алертинга для инфраструктуры

24 июля 2026 10 мин. чтения
Содержание статьи

Система мониторинга без оповещений - это приборная панель, на которую никто не смотрит до тех пор, пока не стало слишком поздно. Связка Prometheus и Alertmanager решает эту проблему: первый собирает метрики и вычисляет аномалии, второй доставляет уведомления нужным людям в нужное время. В этом руководстве мы пройдём полный цикл - от запуска контейнеров до получения алерта в Telegram и на email. Вы получите готовые конфигурации для контроля ошибок Nginx, загрузки CPU, нехватки RAM и состояния Docker-контейнеров.

Материал построен на практике. Каждое правило алертинга проверено в реальной среде, каждый фрагмент конфигурации можно скопировать и адаптировать. Если вам нужна база по умному алертингу и борьбе с шумом, загляните в руководство по настройке умных уведомлений и эскалационных цепочек. А если вы только начинаете, статья «Настройка алертинга с нуля: от метрики до уведомления в Telegram и Slack» даст фундамент.

Архитектура мониторинга: как Prometheus и Alertmanager работают вместе

Prometheus отвечает за сбор, хранение метрик и оценку правил алертинга. Он опрашивает экспортеры (Node Exporter, cAdvisor, nginx-prometheus-exporter), получает числовые показатели и сравнивает их с порогами из файла правил. Когда условие выполняется, Prometheus генерирует алерт и отправляет его в Alertmanager.

Alertmanager не собирает метрики и не вычисляет условия. Его задача - получить алерт, дедуплицировать, сгруппировать с похожими, подавить менее важные и доставить по нужному маршруту. Маршрутизация идёт по меткам: можно отправить критические алерты в Telegram и на email, а предупреждения - только в почту.

Цепочка выглядит так: экспортеры → Prometheus (сбор + правила) → Alertmanager (группировка + маршрутизация) → каналы (Telegram, email). Каждый компонент выполняет строго свою функцию. Prometheus не умеет группировать уведомления, Alertmanager не умеет вычислять rate(). Они дополняют друг друга.

Подготовка окружения: установка и базовая настройка Prometheus и Alertmanager

Для быстрого старта используем Docker Compose. Этот подход не привязан к конкретному дистрибутиву и версии пакетов - контейнеры изолируют зависимости. Если вам нужна облачная инфраструктура для развёртывания, Timeweb Cloud предоставляет VDS и Kubernetes с гибким масштабированием.

Создайте файл docker-compose.yml:

version: '3.8'
services:
  prometheus:
    image: prom/prometheus:v2.51.0
    container_name: prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - ./alert.rules.yml:/etc/prometheus/alert.rules.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    ports:
      - "9090:9090"
    restart: unless-stopped

  alertmanager:
    image: prom/alertmanager:v0.27.0
    container_name: alertmanager
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
    ports:
      - "9093:9093"
    restart: unless-stopped

  node-exporter:
    image: prom/node-exporter:v1.8.0
    container_name: node-exporter
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--path.rootfs=/rootfs'
    ports:
      - "9100:9100"
    restart: unless-stopped

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.49.1
    container_name: cadvisor
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    ports:
      - "8080:8080"
    restart: unless-stopped

volumes:
  prometheus_data:

Базовый prometheus.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['alertmanager:9093']

rule_files:
  - '/etc/prometheus/alert.rules.yml'

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node'
    static_configs:
      - targets: ['node-exporter:9100']

  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

  - job_name: 'nginx'
    static_configs:
      - targets: ['nginx-exporter:9113']

Минимальный alertmanager.yml:

route:
  receiver: 'default'
  group_by: ['alertname']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h

receivers:
  - name: 'default'

После запуска docker compose up -d проверьте веб-интерфейсы: Prometheus на порту 9090, Alertmanager на порту 9093. Убедитесь, что в Prometheus → Status → Targets все цели в состоянии UP.

Правила алертинга для Nginx: контроль ошибок 5xx и недоступности

Метрики Nginx поступают через nginx-prometheus-exporter. Он отдаёт счётчики HTTP-ответов с разбивкой по кодам, данные о соединениях и времени ответа. Для настройки самого экспортера обратитесь к полному руководству по алертингу в Prometheus и Alertmanager 2026 - там разобрана интеграция с десятками сервисов.

Алерт на ошибки 5xx: правило и пороги

Рост ошибок 5xx сигнализирует о проблемах в бэкенде: падение базы данных, таймауты, баги приложения. Правило использует функцию rate() для вычисления среднего количества ошибок в секунду за 5-минутное окно:

groups:
  - name: nginx_alerts
    rules:
      - alert: NginxHigh5xxRate
        expr: rate(nginx_http_requests_total{status=~"5.."}[5m]) > 0.5
        for: 5m
        labels:
          severity: critical
          service: nginx
        annotations:
          summary: "Nginx: высокий уровень 5xx ошибок"
          description: "Экземпляр {{ $labels.instance }} генерирует {{ $value | humanize }} ошибок 5xx в секунду за последние 5 минут."

Порог 0.5 запросов в секунду - отправная точка. Для высоконагруженных серверов его поднимают до 5–10, для низконагруженных - снижают до 0.1. Директива for: 5m предотвращает срабатывание при кратковременных всплесках: алерт активируется, только если условие выполняется непрерывно 5 минут.

Алерт на недоступность Nginx: мгновенное оповещение

Метрика up равна 1, когда цель доступна, и 0, когда Prometheus не может до неё достучаться. Простейший алерт на недоступность:

      - alert: NginxDown
        expr: up{job="nginx"} == 0
        for: 1m
        labels:
          severity: critical
          service: nginx
        annotations:
          summary: "Nginx недоступен"
          description: "Экземпляр {{ $labels.instance }} не отвечает более 1 минуты."

Задержка в 1 минуту отсекает ложные срабатывания при рестарте контейнера или перезагрузке конфигурации. Если Nginx находится за балансировщиком, алерт на up дополняют проверкой кода ответа 200 с помощью blackbox-exporter.

Алертинг по серверным метрикам: загрузка CPU и нехватка RAM

Node Exporter отдаёт сотни метрик ядра Linux. Для алертинга критичны две группы: процессорное время и память. Ошибки в этих правилах приводят либо к ложным срабатываниям, либо к пропуску деградации.

Контроль загрузки процессора: предотвращение троттлинга

Загрузка CPU вычисляется через метрику node_cpu_seconds_total с режимом idle. Вычитая процент idle из 100, получаем утилизацию:

  - name: server_alerts
    rules:
      - alert: HighCpuLoad
        expr: (100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)) > 85
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Высокая загрузка CPU"
          description: "Средняя загрузка CPU на {{ $labels.instance }} превышает 85% ({{ $value | humanize }}%) в течение 10 минут."

Порог 85% выбран с запасом до критических 95–100%, когда начинается троттлинг. Окно 10 минут исключает пиковые нагрузки при запуске сервисов. Для серверов с гарантированной производительностью (bare metal) порог поднимают до 90%, для виртуализированных сред с нестабильным steal time - снижают до 75%.

Мониторинг оперативной памяти: избегаем OOM

Метрика node_memory_MemAvailable_bytes точнее, чем MemFree, потому что учитывает кэш и буферы, которые ядро может освободить. Правило срабатывает, когда доступно менее 10% от общего объёма:

      - alert: LowMemory
        expr: (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 < 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Нехватка оперативной памяти"
          description: "На {{ $labels.instance }} доступно {{ $value | humanize }}% памяти. Возможен вызов OOM Killer."

Дополнительно отслеживают использование swap. Если swap заполняется при наличии свободной RAM, это указывает на неверную настройку swappiness:

      - alert: SwapUsage
        expr: (node_memory_SwapTotal_bytes - node_memory_SwapFree_bytes) / node_memory_SwapTotal_bytes * 100 > 50
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Использование swap превышает 50%"
          description: "Swap на {{ $labels.instance }} заполнен на {{ $value | humanize }}%. Проверьте настройки swappiness."

Мониторинг Docker-контейнеров: состояние и перезапуски

cAdvisor собирает метрики о каждом контейнере: потребление CPU и памяти, сетевой трафик, счётчики перезапусков. Для алертинга важны две ситуации: контейнер остановился и контейнер нестабилен (постоянно перезапускается).

Алерт на остановку контейнера

Метрика container_last_seen обновляется, пока контейнер жив. Если разница между текущим временем и последним обновлением превышает порог - контейнер упал:

  - name: docker_alerts
    rules:
      - alert: ContainerDown
        expr: (time() - container_last_seen{name=~".+"}) > 60
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Контейнер {{ $labels.name }} остановлен"
          description: "Контейнер {{ $labels.name }} на {{ $labels.instance }} не подаёт признаков жизни более 60 секунд."

Фильтр name=~".+" исключает системные контейнеры без имени. Для отслеживания конкретных сервисов заменяют регулярное выражение на точное имя: name="nginx" или используют метки Docker Compose, которые cAdvisor подхватывает автоматически.

Обнаружение частых перезапусков контейнера

Счётчик container_restart_count монотонно растёт. Функция changes() фиксирует количество изменений за период. Три и более перезапуска за час - признак нестабильности:

      - alert: ContainerFrequentRestarts
        expr: changes(container_restart_count{name=~".+"}[1h]) >= 3
        for: 0m
        labels:
          severity: warning
        annotations:
          summary: "Частые перезапуски контейнера {{ $labels.name }}"
          description: "Контейнер {{ $labels.name }} перезапускался {{ $value }} раз за последний час. Проверьте логи и лимиты ресурсов."

Частые перезапуски указывают на нехватку памяти (OOM), ошибки в коде или неверные healthcheck. Этот алерт позволяет обнаружить проблему до того, как сервис станет полностью недоступным.

Настройка Alertmanager: маршрутизация, группировка и уведомления

Файл alertmanager.yml определяет, куда и как отправлять алерты. Ключевые параметры: group_by объединяет похожие алерты в одно уведомление, group_wait задаёт паузу перед первой отправкой (чтобы собрать группу), group_interval ограничивает частоту повторных уведомлений внутри группы, repeat_interval - частоту напоминаний о незакрытых алертах.

Маршрутизация строится на сопоставлении меток. Алерты с severity: critical отправляются мгновенно в Telegram, с severity: warning - только в email. Базовая структура:

route:
  receiver: 'default'
  group_by: ['alertname', 'service']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    - matchers:
        - severity="critical"
      receiver: 'critical-telegram'
      continue: true
    - matchers:
        - severity="warning"
      receiver: 'warning-email'

receivers:
  - name: 'default'
  - name: 'critical-telegram'
    telegram_configs:
      - bot_token: 'YOUR_BOT_TOKEN'
        chat_id: YOUR_CHAT_ID
        message: '{{ template "telegram.message" . }}'
  - name: 'warning-email'
    email_configs:
      - to: 'admin@example.com'
        from: 'alertmanager@example.com'
        smarthost: 'smtp.gmail.com:587'
        auth_username: 'alertmanager@example.com'
        auth_password: 'YOUR_APP_PASSWORD'
        html: '{{ template "email.html" . }}'

templates:
  - '/etc/alertmanager/templates/*.tmpl'

Интеграция с Telegram: создание бота и настройка получателя

Создайте бота через @BotFather в Telegram. Команда /newbot запросит имя и выдаст токен. Для получения chat_id отправьте боту любое сообщение и выполните запрос:

curl -s "https://api.telegram.org/bot/getUpdates" | jq '.result[0].message.chat.id'

Шаблон сообщения telegram.message форматирует алерт для мессенджера. Создайте файл templates/telegram.tmpl:

{{ define "telegram.message" }}
{{ if gt (len .Alerts.Firing) 0 }}
🔥 Сработавшие алерты ({{ len .Alerts.Firing }})
{{ range .Alerts.Firing }}
{{ .Labels.alertname }}
{{ .Annotations.summary }}
Severity: {{ .Labels.severity }}
Instance: {{ .Labels.instance }}
{{ .Annotations.description }}
{{ end }}
{{ end }}
{{ if gt (len .Alerts.Resolved) 0 }}
✅ Разрешённые алерты ({{ len .Alerts.Resolved }})
{{ range .Alerts.Resolved }}
{{ .Labels.alertname }} на {{ .Labels.instance }}
{{ end }}
{{ end }}
{{ end }}

Шаблон выводит список активных алертов с деталями и отдельно - список разрешившихся. Это позволяет видеть в одном сообщении и проблему, и подтверждение её решения.

Отправка алертов на email: SMTP-конфигурация и шаблоны

Для Gmail требуется пароль приложения (App Password), а не пароль от аккаунта. Создайте его в настройках безопасности Google. HTML-шаблон templates/email.tmpl:

{{ define "email.html" }}


Алерты Prometheus

{{ if gt (len .Alerts.Firing) 0 }}

Сработавшие ({{ len .Alerts.Firing }})

{{ range .Alerts.Firing }} {{ end }}
АлертSeverityInstanceОписание
{{ .Labels.alertname }} {{ .Labels.severity }} {{ .Labels.instance }} {{ .Annotations.description }}
{{ end }} {{ if gt (len .Alerts.Resolved) 0 }}

Разрешены ({{ len .Alerts.Resolved }})

    {{ range .Alerts.Resolved }}
  • {{ .Labels.alertname }} - {{ .Labels.instance }}
  • {{ end }}
{{ end }} {{ end }}

Ограничения: Gmail разрешает до 500 писем в сутки для личных аккаунтов. Для production-сред используйте корпоративный SMTP или сервисы транзакционной почты.

Тестирование и проверка системы алертинга

Первый шаг - проверка правил в веб-интерфейсе Prometheus. Перейдите на вкладку Alerts. Все правила из alert.rules.yml отображаются с текущим состоянием: Inactive (условие не выполнено), Pending (выполняется, но ждёт for), Firing (активный алерт). Если правило отсутствует в списке, проверьте синтаксис: promtool check rules /etc/prometheus/alert.rules.yml.

Для ручной генерации тестового алерта используйте API Alertmanager. Отправьте POST-запрос с JSON-представлением алерта:

curl -X POST http://localhost:9093/api/v2/alerts \
  -H "Content-Type: application/json" \
  -d '[{
    "labels": {
      "alertname": "TestAlert",
      "severity": "critical",
      "service": "test"
    },
    "annotations": {
      "summary": "Тестовый алерт",
      "description": "Проверка доставки уведомлений"
    },
    "startsAt": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
  }]'

Алерт появится в интерфейсе Alertmanager и будет обработан согласно маршрутам. Проверьте логи контейнера: docker logs alertmanager. Успешная доставка в Telegram выглядит как строка Notify attempt 1; recipient=telegram, ошибки содержат код ответа API.

Типовые проблемы и их решение

Алерты не срабатывают. Причина - неверные метки в выражении. Проверьте, что метрика существует: перейдите в Prometheus → Graph, введите PromQL-выражение из правила и нажмите Execute. Если результат пустой, проверьте имена метрик и лейблы. Команда curl -s http://localhost:9090/api/v1/label/__name__/values | jq '.data[]' | grep nginx выведет все доступные метрики с nginx в названии.

Уведомления не доходят в Telegram. Проверьте токен бота и chat_id: curl -s "https://api.telegram.org/bot/getMe" должен вернуть информацию о боте. Убедитесь, что контейнер Alertmanager имеет доступ в интернет. Если используется брандмауэр, откройте исходящие соединения на api.telegram.org:443.

Дублирование сообщений. Параметр group_by настроен слишком детально. Если в группировку включено поле instance, каждый сервер генерирует отдельное уведомление. Объедините алерты по alertname и service, а детализацию по инстансам вынесите в тело сообщения через шаблон.

Алерт-шторм при массовом сбое. Параметр group_wait собирает алерты в пачку перед отправкой. Увеличьте его до 60 секунд при большом количестве серверов. Параметр group_interval предотвращает повторную отправку внутри группы - установите его не менее 5 минут.

Для углублённого изучения принципов алертинга в DevOps-среде рекомендую практическое руководство по настройке систем оповещения, где разобраны эскалационные цепочки и интеграция с Terraform. Если ваша инфраструктура распределённая, статья по мониторингу SLA распределённых систем поможет настроить контроль health checks и circuit breakers.

Поделиться:
Сохранить гайд? В закладки браузера