Кто мониторит монитор? Рекурсивная задача, у которой нет чистого решения

от автора

У вас есть Grafana. Она показывает графики с Prometheus. Prometheus скрейпит метрики с ваших сервисов. Если сервис упал — вы видите красный на дашборде. Если Prometheus упал — вы не видите ничего. Дашборд замирает на последних известных значениях. Если не знать, что Prometheus лежит, можно час смотреть на «зелёный» дашборд, который на самом деле показывает данные часовой давности.

Это не гипотетика. Я видел это дважды. Первый раз — Prometheus съел диск на мониторинг-сервере (да, Prometheus хранит данные на диске, и этот диск тоже может закончиться). Второй раз — kubelet убил pod с Prometheus из-за OOM, а Pod Disruption Budget не был настроен.

В обоих случаях дашборды выглядели нормально. Алерты не приходили — потому что Alertmanager получает данные от Prometheus, а Prometheus не работал. Мониторинг был мёртв, и выглядело это как «всё хорошо».


Проблема формулируется просто

Любая система мониторинга — это программа. Программа работает на инфраструктуре. Инфраструктура может сломаться. Если мониторинг сломался — кто об этом скажет?

Очевидный ответ: другой мониторинг. Но тогда кто мониторит тот мониторинг? И так до бесконечности.

Это не академическая задачка. Это практическая проблема, которую решает каждая команда, дошедшая до определённого уровня зрелости в observability. И решения, которые я видел, делятся на две категории: правильные (но дорогие) и практичные (но с оговорками).


Подход 1: Независимые домены отказа

Самый надёжный способ мониторить мониторинг — поместить его в другой домен отказа.

Что такое «домен отказа»? Это набор компонентов, которые ломаются вместе. Один VPS — один домен отказа. Один Kubernetes-кластер — один домен отказа (кластер может целиком потерять API server). Один облачный регион — один домен отказа (Yandex Cloud ru-central1 может лечь целиком, хоть это и редкость).

Если ваши сервисы и мониторинг живут на одном VPS — они в одном домене отказа. VPS упал — всё упало вместе. Это самый частый антипаттерн, и именно поэтому self-hosted решения вроде Uptime Kuma, при всех их достоинствах, имеют фундаментальную слабость: мониторинг умирает вместе с сервером.

Вариант: мониторинг на отдельном сервере. Два VPS: один для сервисов, один для мониторинга. Лучше, чем один VPS, но оба могут быть у одного провайдера, в одном ЦОДе, в одном коридоре стоек. Аутейдж провайдера — и оба недоступны.

Вариант: мониторинг в другом облаке. Сервисы в Yandex Cloud, мониторинг в AWS (или наоборот). Вероятность одновременного отказа двух облачных провайдеров — крайне низкая. Но: усложнение инфраструктуры, двойные расходы, необходимость поддерживать экспертизу в двух облаках.

Вариант: serverless мониторинг. Вынести критический путь мониторинга (проверка → алерт) в managed serverless-сервисы. Cloud Functions, Cloud Containers, managed queues, managed databases. Эти сервисы управляются облачным провайдером и работают независимо от вашего VPS. Если VPS упал — serverless-функции продолжают работать. Так устроена архитектура UpRadar: цепочка проверок вынесена в serverless среду и работает независимо от пользовательского интерфейса.

Ни один из вариантов не даёт 100% гарантии. Но каждый следующий уровень разделения снижает вероятность одновременного отказа на порядок.


Подход 2: Мета-heartbeat

Heartbeat-мониторинг — когда ваш сервис периодически «стучится» к внешнему сервису: «я жив». Если стук не пришёл — алерт.

Тот же принцип можно применить к самому мониторингу:

  1. Планировщик мониторинга каждую минуту записывает метку времени в отдельное хранилище (Redis, файл, что угодно).

  2. Независимый watchdog (максимально простой: лямбда-функция с одной проверкой) каждые 5 минут смотрит на эту метку.

  3. Если метка старше 5 минут — watchdog шлёт алерт по отдельному каналу (другой Telegram-бот, SMS, PagerDuty).

Ключевые слова: независимый и отдельный канал. Watchdog не должен зависеть от тех же компонентов, что и основной мониторинг. Если watchdog шлёт алерт через тот же Alertmanager, который зависит от того же Prometheus — вы не решили проблему, а добавили ещё один компонент, который ломается вместе со всем остальным.

Мета-heartbeat — это практический инструмент. Мы используем его в UpRadar: планировщик оставляет метку, watchdog проверяет. Мы мониторим мониторинг тем же механизмом, который даём пользователям.


Подход 3: Dead Man’s Switch

Разновидность мета-heartbeat, но с другой стороны. Вместо того чтобы активно проверять здоровье мониторинга, вы настраиваете внешний сервис, который ожидает периодический сигнал. Если сигнал не пришёл — значит, мониторинг (или что-то в его цепочке) не работает.

Некоторые инструменты имеют это как встроенную фичу:

  • Healthchecks.io — принимает периодические пинги и алертит при пропуске. Можно направить пинг из Alertmanager в Healthchecks.io как dead man’s switch для всего стека Prometheus + Alertmanager.

  • PagerDuty heartbeat monitoring — аналогичная концепция, интегрированная в PagerDuty.

  • Любой heartbeat-сервис — Deadman’s Snitch, Cronitor, или (позволю себе) UpRadar.

Схема:

[Ваш мониторинг] --периодический пинг--> [Внешний Dead Man's Switch]                                          |                                    (пинг не пришёл)                                          |                                    [Алерт по отдельному каналу]

Это работает, но создаёт зависимость от внешнего сервиса. Если и он ляжет — вы снова без оповещения. Рекурсия не исчезла, но вероятность одновременного отказа вашего мониторинга И внешнего dead man’s switch — уже очень мала.


Подход 4: Кросс-мониторинг

Две независимые системы мониторинга проверяют друг друга.

[Мониторинг A] --проверяет--> [Мониторинг B][Мониторинг B] --проверяет--> [Мониторинг A]

Если A упал — B это заметит и пошлёт алерт. И наоборот. Обе системы должны быть в разных доменах отказа.

На практике это означает: вы платите за два мониторинг-сервиса (или поддерживаете два self-hosted инструмента). Для критической инфраструктуры — оправдано. Для типичного SaaS-проекта — overkill.

Более реалистичный вариант: основной мониторинг — полнофункциональный (Prometheus + Grafana, или SaaS вроде Datadog, или UpRadar), а второй — максимально примитивный (cron-скрипт на отдельном сервере, который пингует URL вашего основного мониторинга и шлёт SMS, если он не отвечает). Второй не заменяет первый — он только проверяет, что первый жив.


Принцип «достаточно хорошо»

В определённый момент рекурсия становится академической.

Вот реалистичная оценка вероятностей для типичного setup:

Событие

Приблизительная вероятность

Ваш VPS упал

~0.1–1% в месяц

Облачный провайдер целиком упал

~0.01% в месяц

Два независимых провайдера упали одновременно

~0.0001% в месяц

Три независимых провайдера упали одновременно

Астрофизика

Два уровня независимого мониторинга — это практический предел для 99.9% систем. Не потому, что три уровня бесполезны, а потому, что стоимость поддержки третьего уровня не окупается снижением и без того ничтожного риска.

Для большинства команд разумный setup:

  1. Основной мониторинг — полнофункциональный, в отдельном от сервисов домене отказа (SaaS или serverless)

  2. Dead man’s switch — внешний heartbeat-сервис, проверяющий здоровье основного мониторинга

  3. Всё — выдыхаем

Если ваш основной мониторинг, dead man’s switch и Telegram одновременно недоступны — у вас проблемы масштаба, при котором мониторинг вообще нерелевантен (ядерная война, глобальный блэкаут, развал BGP).


Часто игнорируемые аспекты

Канал уведомления — тоже домен отказа

Ваш мониторинг работает. Алерт сформирован. Он отправляется через… Slack. Slack лежит. Алерт не доставлен.

Канал уведомления — это часть критического пути, и он тоже может сломаться. Решение: несколько каналов для критических алертов. Telegram + email. Или Telegram + SMS. Вероятность одновременного отказа двух каналов — на порядок ниже, чем одного.

Мониторинг без состояния vs. мониторинг с состоянием

Prometheus хранит историю метрик и строит алерты на основе временных рядов. Если он упал и поднялся через 10 минут — в истории дыра. Алерты, которые должны были сработать за эти 10 минут, потеряны навсегда.

Stateless мониторинг (простая проверка «URL отвечает?» без истории) менее функционален, но более устойчив: если он перезапустился, он просто начинает проверять заново. Ничего не потеряно — кроме данных за время простоя.

Это аргумент в пользу того, чтобы stateful мониторинг (Prometheus, Datadog) дополнять stateless (простые внешние проверки). Они решают разные задачи и ломаются по-разному.

Тестирование мониторинга

Вы тестируете свой код. Вы тестируете бэкапы (вы ведь тестируете бэкапы?). Тестируете ли вы мониторинг?

Простой тест: выключите один из сервисов и посмотрите, придёт ли алерт. Звучит очевидно, но я знаю команды, которые настроили мониторинг, ни разу его не тестировали, и через полгода обнаружили, что Alertmanager перестал слать сообщения из-за истёкшего Telegram-токена.

Game day: раз в квартал сознательно «ломайте» что-то в staging и проверяйте, что мониторинг это поймал. Это дешевле, чем узнать о мёртвом мониторинге во время реального инцидента.


Итого

Идеального решения задачи «кто мониторит монитор» не существует. Рекурсия бесконечна, и в какой-то момент приходится принять остаточный риск.

Но практические решения — есть:

  • Разнесите мониторинг и мониторимые сервисы по разным доменам отказа

  • Добавьте dead man’s switch или мета-heartbeat для проверки здоровья мониторинга

  • Используйте несколько каналов уведомления

  • Тестируйте мониторинг как тестируете код

Два уровня независимости — достаточно для всех, кроме тех, кто мониторит ядерные реакторы. Если вы мониторите ядерные реакторы — вам нужен не Хабр, а ISO 61513.

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

ссылка на оригинал статьи https://habr.com/ru/articles/1023188/