Система мониторинга без оповещений - это приборная панель, на которую никто не смотрит до тех пор, пока не стало слишком поздно. Связка 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 }})
Алерт Severity Instance Описание
{{ range .Alerts.Firing }}
{{ .Labels.alertname }}
{{ .Labels.severity }}
{{ .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 }}Ограничения: 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 должен вернуть информацию о боте. Убедитесь, что контейнер Alertmanager имеет доступ в интернет. Если используется брандмауэр, откройте исходящие соединения на api.telegram.org:443.
Дублирование сообщений. Параметр group_by настроен слишком детально. Если в группировку включено поле instance, каждый сервер генерирует отдельное уведомление. Объедините алерты по alertname и service, а детализацию по инстансам вынесите в тело сообщения через шаблон.
Алерт-шторм при массовом сбое. Параметр group_wait собирает алерты в пачку перед отправкой. Увеличьте его до 60 секунд при большом количестве серверов. Параметр group_interval предотвращает повторную отправку внутри группы - установите его не менее 5 минут.
Для углублённого изучения принципов алертинга в DevOps-среде рекомендую практическое руководство по настройке систем оповещения, где разобраны эскалационные цепочки и интеграция с Terraform. Если ваша инфраструктура распределённая, статья по мониторингу SLA распределённых систем поможет настроить контроль health checks и circuit breakers.