MAATRIX / Блог / Алерты, которые не бесят: как настроить пороги

Алерты, которые не бесят: как настроить пороги

MAATRIX

Алерт в три часа ночи про то, что CPU на секунду подскочил до 85% — это не мониторинг, это генератор недоверия. Через месяц такой практики администратор смотрит на уведомление от Zabbix или Prometheus Alertmanager и думает «опять ерунда», не открывая его вообще. Проблема почти всегда не в том, что алертов настроено мало или много, а в том, что пороги подобраны на глаз, без разбора того, как метрика на самом деле себя ведёт на этом конкретном сервере.

Почему «круглые» пороги не работают

Самая частая ошибка — взять число, которое звучит разумно, и поставить его как есть: CPU > 80%, диск > 90%, память > 85%. Эти цифры кочуют из мануала в мануал, но не имеют отношения к вашей нагрузке.

Пример: на сервере с 1С или тяжёлыми batch-джобами кратковременные всплески CPU до 95-100% — норма несколько раз в час, это часть рабочего процесса. Порог в 80% на таком сервере будет срабатывать десятками раз в день, и через неделю его либо отключат, либо будут игнорировать нотификации не глядя. А на веб-сервере, который в среднем держит 15-20% CPU, тот же порог в 80% — это уже реальный сигнал: что-то пошло не так (зависший процесс, DDoS, утечка в приложении).

Правило простое: порог — это функция от вашей реальной нагрузки, а не универсальная константа. Если вы не знаете, как метрика ведёт себя на вашем сервере в обычный рабочий день, вы не готовы ставить порог — вы готовы только гадать.

Шаг 1. Соберите baseline перед тем, как ставить пороги

Прежде чем писать expr: cpu_usage > 80, нужно посмотреть на реальные данные за представительный период — минимум 1-2 недели, а лучше месяц, захватывающий и будни, и выходные, и ночные бэкапы, и пиковые часы.

В Grafana это делается через обычный дашборд с длинным диапазоном:

# Prometheus query для оценки типичного разброса CPU за 30 дней
quantile_over_time(0.95, node_cpu_usage_percent[30d])
quantile_over_time(0.99, node_cpu_usage_percent[30d])
max_over_time(node_cpu_usage_percent[30d])

Смотрите не на максимум (он почти всегда будет пугающим — сервер хоть раз да упирался в 100%), а на 95-й и 99-й перцентиль. Если p95 CPU за месяц — 35%, а p99 — 60%, это значит: в 95% времени нагрузка не превышает 35%, и даже в самые нагруженные 1% времени редко переваливает за 60%. Разовые всплески до 100% — это шум, не отражающий типичное поведение системы.

Тот же подход применим к диску, памяти, времени ответа приложения, количеству соединений с базой — любой метрике. Собираете реальное распределение, а не воображаемое.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Шаг 2. Порог — это baseline плюс разумный запас

Когда есть p95/p99 за представительный период, порог ставится с запасом над верхней границей нормального разброса, а не произвольно.

Пример на диске:

  • p95 использования диска за месяц — 62%.
  • p99 — 68%.
  • Разумный порог первого уровня (warning) — 75-80%: заметно выше типичного максимума, но с запасом на рост.
  • Порог второго уровня (critical) — 90%: реальная опасность закончиться местом.
# Alertmanager rule (Prometheus) - пример двухуровневого порога для диска
groups:
  - name: disk_usage
    rules:
      - alert: DiskSpaceWarning
        expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 25
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "Свободного места на диске меньше 25%"

      - alert: DiskSpaceCritical
        expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 10
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Свободного места на диске меньше 10% - требуется немедленное вмешательство"

Без такого расчёта легко наткнуться на ситуацию, которую разбирали в статье про RAID, который сыпался месяц, пока мониторинг молчал: порог там был вообще не выставлен под реальное поведение диска, из-за чего деградация массива долго оставалась незамеченной. Плохо настроенный порог опасен в обе стороны — и когда он слишком чувствителен (шумит по пустякам), и когда слишком грубый (не видит реальную проблему).

Шаг 3. Длительность отклонения важнее самого факта превышения

Вторая по частоте ошибка — алерт срабатывает на любое мгновенное превышение порога, без учёта того, как долго метрика там находится. Загрузка CPU может на секунду подскочить до 95% из-за cron-задачи, ротации логов или GC-паузы — и тут же вернуться в норму. Это не инцидент, это штатное поведение системы под нагрузкой.

Практически во всех системах мониторинга есть механизм «порог должен держаться N времени, прежде чем сработает алерт»:

# Prometheus/Alertmanager: параметр "for" - отклонение должно держаться 5 минут
- alert: HighCPUUsage
  expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
  for: 5m
  labels:
    severity: warning
# Zabbix trigger - функция last() с параметром #3 требует 3 последовательных
# опроса подряд выше порога, а не одного мгновенного значения
last(/Template OS Linux/system.cpu.util,#3) > 85
# Uptime Kuma - "Retries" и "Heartbeat Interval" в настройках монитора:
# Retries = 3, Heartbeat Interval = 60s означает, что сервис должен быть
# недоступен 3 проверки подряд (около 3 минут), прежде чем придёт алерт

Разумная длительность зависит от метрики и от того, как быстро проблема реально становится критичной. Для CPU и памяти разумный диапазон — 3-10 минут устойчивого превышения. Для доступности сайта или API — 2-3 неудачные проверки подряд с интервалом в 30-60 секунд (то есть 1-3 минуты), не одна. Для места на диске — раз оно не может резко «отскочить» само, здесь можно требовать более короткого окна (5 минут), поскольку задержка сама по себе не создаёт риска ложного срабатывания.

Важный нюанс: слишком долгое окно for тоже вредно — если вы поставите for: 30m на недоступность сайта, то полчаса реального даунтайма пройдут незамеченными. Длительность должна быть соразмерна тому, насколько быстро вы готовы терпеть проблему, а не быть одинаковой «для перестраховки» на все метрики подряд.

Шаг 4. Разделите алерты по серьёзности — не всё достойно будить человека

Третья системная ошибка — когда все алерты одинаково «громкие»: и то, что сайт лежит, и то, что на диске осталось 30% места, летят одним и тем же сообщением в тот же Telegram-чат в 4 утра. В статье про настройку алертов в Telegram на VPS разбирается механика доставки, но здесь важнее логика разделения по важности до того, как алерт вообще ушёл в канал.

Практическая схема на два-три уровня:

УровеньПримеры ситуацийСпособ уведомленияВремя реакции
CriticalСайт/API недоступен, диск заполнен >95%, база данных не отвечает, сервис упал и не поднялсяЗвонок или push с эскалацией (PagerDuty, Opsgenia, звонок через Twilio), будит дежурного ночьюМинуты
WarningДиск заполнен на 75-90%, устойчивая повышенная нагрузка CPU/RAM, деградация производительности без падения сервисаСообщение в Telegram/Slack, без звука ночью либо с тихим режимомБлижайший рабочий день
InfoПлановые события: ротация сертификата через 30 дней, рост базы данных, окончание диска через N дней при текущем трендеНакопление в дашборде или дайджест раз в день/неделюНе требует немедленной реакции

Технически это реализуется через label severity в правиле алерта и маршрутизацию в Alertmanager:

# alertmanager.yml - маршрутизация по severity
route:
  receiver: default-telegram
  routes:
    - match:
        severity: critical
      receiver: pagerduty-oncall
      repeat_interval: 15m
    - match:
        severity: warning
      receiver: telegram-team
      repeat_interval: 4h
    - match:
        severity: info
      receiver: telegram-digest
      repeat_interval: 24h

В Zabbix та же идея реализуется через severity триггера (Warning/High/Disaster) и разные Action-и с разными Media Type и расписанием: критичные действия шлют SMS/звонок без ограничения по времени суток, а Warning — только в рабочее окно через Telegram.

Ключевая мысль: если дежурного будят ночью алертом уровня «через 20 дней закончится место на диске», доверие к системе алертов разрушается быстрее, чем от одного ложного срабатывания. Человек должен точно знать: если пришёл critical — нужно вставать и разбираться, если warning — можно посмотреть утром.

Разбор трёх типовых ошибок на примерах

Чтобы методика не осталась абстрактной, вот три конкретных «до/после» с реальными формулировками порогов.

Ошибка 1: порог без учёта baseline.

  • Плохо: CPU > 80% на сервере с батчевой обработкой, где p95 CPU — 90% в рабочие часы.
  • Хорошо: наблюдение показало, что вне периодов batch-обработки CPU держится на 15-25%, а во время неё — легитимно 85-95% по 10-15 минут. Порог: CPU > 95% на протяжении 20 минут — ловит именно аномально долгую нагрузку, а не штатный batch-джоб.

Ошибка 2: мгновенное срабатывание без окна.

  • Плохо: алерт на недоступность сайта при первой же неудачной HTTP-проверке (один таймаут раз в несколько тысяч запросов — это нормально для любого сетевого стека).
  • Хорошо: 3 неудачные проверки подряд с интервалом 30 секунд (полтора часа реальной недоступности не образуется, а случайный сетевой глитч не порождает алерт).

Ошибка 3: одинаковая громкость всех алертов.

  • Плохо: и «диск заполнен на 78%», и «сайт лежит 5 минут» уходят в один Telegram-чат без звука/тегов, дежурный физически не отличает их по важности в ленте сообщений.
  • Хорошо: недоступность сайта — critical, звонок дежурному; диск на 78% — warning в отдельный тред, без звукового уведомления, дайджест утром.

Общая нить всех трёх примеров одна: за каждым «хорошо» стоит наблюдение за реальным поведением конкретной системы, а не абстрактное «лучшая практика» из чужого мануала.

Пересмотр порогов — это процесс, а не разовая настройка

Пороги, выставленные один раз при установке мониторинга, устаревают: нагрузка растёт, состав сервисов меняется, появляются новые паттерны трафика. Разумная практика — вести короткий журнал срабатываний и раз в 1-2 месяца задавать по каждому алерту два вопроса: сработал ли он на реальную проблему, требующую действия, и было ли действие предпринято.

Простой способ вести такой учёт без отдельного инструмента — таблица (можно в Grafana как аннотации, можно в обычном issue-трекере):

ДатаАлертБыло реальной проблемой?ДействиеВывод
03.08DiskSpaceWarning 78%Нет, разовый лог-всплескНе потребовалосьПорог адекватен
11.08HighCPUUsage 90%/5mНет, ложное (batch-джоб)Не потребовалосьПоднять окно до 15m
22.08SiteDown 3 попыткиДа, упал nginxПерезапускПорог адекватен

Если алерт срабатывает регулярно и каждый раз оказывается ложным — либо порог слишком низкий, либо окно for слишком короткое, либо метрика вообще не подходящий индикатор для этой проблемы. Если алерт вообще ни разу не срабатывал за несколько месяцев — стоит проверить, не выставлен ли порог настолько высоко, что он никогда не поймает реальную деградацию (обратная сторона той же ошибки, разобранной на примере молчавшего RAID выше).

Отдельно стоит подключать сюда обратную связь от команды: если дежурный говорит «этот алерт постоянно ложный, я его игнорирую» — это не жалоба, а прямой сигнал пересчитать порог по свежему baseline, а не терпеть игнорирование молча. Именно накопление таких игнорируемых алертов и превращает мониторинг в шум, который со временем перестают замечать вообще — тема отдельного разбора того, к чему это приводит на практике.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

С чего начать, если мониторинг уже настроен, но алертов слишком много?

Не отключайте всё разом. Выгрузите статистику срабатываний за последний месяц (в Alertmanager это можно сделать через Prometheus API запросом к ALERTS metric), отсортируйте по частоте и для каждого топового алерта проверьте: был ли он хоть раз причиной реального действия. То, что ни разу не было — кандидат на повышение порога или увеличение for.

Нужно ли одинаковое окно for для всех алертов одной метрики?

Нет. Окно зависит от того, как быстро проблема становится критичной именно в этом контексте: для warning-уровня разумно требовать более долгого устойчивого отклонения (10-15 минут), для critical — от 1 до 5 минут, чтобы не терять время реакции.

Как быть с сервисами, у которых нагрузка сильно скачет по сезону или времени суток (например, интернет-магазин в период распродаж)?

Либо считать baseline отдельно для разных периодов (будни/выходные, обычные дни/распродажи) и переключать пороги вручную на время пиков, либо использовать относительные пороги — например, отклонение от скользящего среднего за последние N дней, а не абсолютное число.

Стоит ли использовать готовые дашборды и алерты из community (Grafana dashboards, Zabbix templates)?

Как отправную точку — да, они экономят время на структуру. Но пороги внутри них почти всегда общие и требуют пересчёта под вашу нагрузку по методике выше — иначе получите ровно тот шум, от которого хотели уйти.

Как быстро понять, что порог настроен неправильно, не дожидаясь месяца статистики?

Если алерт срабатывает чаще одного-двух раз в неделю и при разборе оказывается ложным больше чем в половине случаев — это уже достаточный сигнал пересчитать порог, ждать полный отчётный цикл не обязательно.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →