← Назад к блогу
Мониторинг

Как мы мониторим 15 серверов в 3 дата-центрах из одного окна

Практический опыт мониторинга 15 серверов из одного окна.

Примерно год назад я поймал себя на том, что утром, садясь за компьютер, открываю семь разных вкладок браузера. Timeweb Cloud — посмотреть статус серверов. SSH-терминал — проверить диски. Отдельная вкладка с Grafana, которую мы пытались настроить. Ещё один таб с логами Bitrix24. И примерно через двадцать минут этого ритуала я понимал: что-то не так с контейнером на сервере с WordPress, но точно что — непонятно, потому что данные разбросаны по трём интерфейсам, и чтобы сложить картину, надо ещё и в голове держать, что к чему относится.

Это было у нас нормой. Не потому что мы не понимали, что так неправильно, а потому что задача "собрать всё в одно место" всегда казалась чем-то, чем займёмся потом, когда будет время. Время, разумеется, не появлялось.

Я не буду делать вид, что это какая-то уникальная история. Любой, кто управляет больше чем тремя-четырьмя серверами, рано или поздно приходит к этому хаосу. Сначала один сервер — всё под контролем. Потом второй, третий. Потом кто-то говорит "давайте поднимем Supabase отдельно для этого проекта", потом появляется 1С на выделенном Windows-сервере, потом VPN для команды, потом почтовый сервер, потому что мы устали зависеть от внешних провайдеров. И в какой-то момент ты обнаруживаешь, что у тебя 15 машин в трёх дата-центрах, и ты физически не можешь удержать в голове, что где крутится и в каком состоянии.

Именно тогда мы и начали делать CosDevDirector — наш внутренний дашборд, о котором я хочу рассказать подробно. Не как рекламу продукта (это внутренний инструмент, не коммерческий), а как опыт построения системы мониторинга с нуля, с конкретными решениями и конкретными граблями.

Что у нас за инфраструктура и почему это важно для понимания задачи

Прежде чем говорить о мониторинге, нужно понять, что именно мы мониторим. Потому что "15 серверов" звучит абстрактно, но за этими серверами стоят очень разные нагрузки и очень разные требования к наблюдаемости.

Основной кластер — 13 VPS в Timeweb Cloud, разбросанных по трём локациям. Москва (ru-3) — это большинство production-серверов: сайты, CRM, API. Петербург (ru-1) — несколько тестовых и вспомогательных машин. Амстердам (nl-1) — VPN-сервер, он должен быть за пределами России по понятным причинам. Плюс два выделенных сервера отдельно от облака: один под 1С на Windows (тут своя история с мониторингом, об этом отдельно), второй — под проект с высокими требованиями по вычислениям.

Список сервисов, если просто перечислить: Mailcow (почтовый сервер), несколько инстансов Supabase (PostgreSQL + аутентификация + хранилище для разных проектов), несколько WordPress-сайтов под управлением FASTPANEL, один сервер целиком под масла.сайт — это большой e-commerce на 8 CPU и 16 GB RAM, который живёт своей жизнью и требует особого внимания. Ещё PayloadCMS с несколькими Next.js-сайтами. VPN на WireGuard плюс 3X-UI. И 1С Управление торговлей на выделенном Windows-сервере — это вообще отдельный зверь, потому что Windows-серверы мониторятся иначе, чем Linux.

Вот в чём штука: все эти сервисы имеют разные метрики, которые важны именно для них. Для почтового сервера критична очередь писем и репутация IP. Для WordPress — время ответа и свободное место на диске (логи и кэш растут незаметно, пока не кончается место). Для Supabase — количество соединений с базой и задержки запросов. Для 1С — активные сессии, блокировки, выполнение регламентных заданий. Универсальный мониторинг "CPU/RAM/disk" работает для всего, но ни для чего конкретно недостаточен.

Это был первый урок, который мы усвоили: мониторинг должен быть контекстным, а не просто набором графиков.

Второй урок, который я осознал чуть позже: инфраструктура разбросана по трём географическим локациям не случайно, и эта распределённость создаёт свои специфические задачи для мониторинга. Амстердам — это сотни миллисекунд сетевой задержки от наших серверов в Москве. SSH-команды туда выполняются дольше. Если что-то тормозит на VPN-сервере — нужно учитывать, что задержка может быть сетевой, а не проблемой самого сервера. Мы добавили в мониторинг измерение времени SSH-коннекта: если к амстердамскому серверу обычно коннектимся за 200 мс, а сейчас это занимает 2 секунды — это сигнал проблем с маршрутизацией, а не с самим сервером. Казалось бы мелочь, но без этого контекста ложные алерты о "медленном" сервере в другом дата-центре очень раздражают.

Как устроен сбор метрик — SSH как универсальный транспорт

Первый вопрос, который возникает при проектировании мониторинга: как физически получать данные с серверов? Есть несколько подходов. Можно ставить агенты на каждый сервер — это Prometheus Node Exporter, Zabbix Agent, Datadog Agent. Подход рабочий, но требует поддержки на каждой машине. Обновился сервер — проверь, что агент живой. Переехал — переустанови. И для гетерогенной инфраструктуры вроде нашей, где есть и Ubuntu, и Debian, и Windows, агентская модель превращается в отдельный проект.

Мы пошли другим путём — агентлесс мониторинг через SSH. Идея простая: наш бэкенд сам подключается к серверу по SSH и выполняет нужные команды. `df -h` для дисков, `free -m` для памяти, `top -bn1` или `/proc/meminfo` для CPU. Никакого дополнительного ПО на серверах. Если SSH есть — мониторинг работает.

На практике это выглядит так: Express-бэкенд по крону каждые 30 секунд коннектится к каждому серверу и собирает быстрые метрики — CPU, RAM, disk. Каждые 5 минут запускается более тяжёлый сбор: Docker-статистика, статусы сервисов, проверка логов на ошибки. Каждые 15 минут — журналы systemd через journalctl, которые мы парсим и складываем в единую таблицу логов в PostgreSQL.

Здесь сразу возникает проблема, о которой я хочу предупредить отдельно, потому что наступил на эти грабли болезненно. Параллельные SSH-подключения к одному серверу могут заблокировать учётную запись. Это не теория — у нас была блокировка на 15 минут после того, как несколько cron-задач запустились одновременно и открыли несколько SSH-сессий к одной машине. Решение — очередь SSH-команд. Для каждого сервера есть своя очередь, и команды к одному серверу выполняются строго последовательно, одна за другой, никогда параллельно. Это немного замедляет сбор данных, но зато надёжно.

Для Windows-сервера с 1С ситуация ещё острее. 1С-сервер — это производственная система, и блокировка учётки там означает, что 1С перестаёт работать. Мы сделали отдельный sshQueue с явными задержками между командами, и это оказалось правильным решением. Принцип прост: все SSH-команды к одному серверу встают в очередь, выполняются строго одна за другой, и следующая команда не стартует, пока предыдущая не завершилась. Да, это медленнее, чем параллельный сбор. Для 15 серверов полный цикл занимает не 3 секунды, а около 40. Но надёжность важнее скорости, когда цена ошибки — заблокированный production-сервер с 1С и тридцать звонящих пользователей.

Отдельно стоит SSL-мониторинг. Истёкший сертификат — одна из самых неприятных аварий, потому что пользователи видят пугающее предупреждение браузера, а вы узнаёте об этом не от мониторинга, а от звонка клиента. Мы сделали отдельный сервис, который каждые 5 минут проверяет все сайты через HTTP HEAD-запрос и заодно проверяет SSL-сертификат — срок действия и цепочку доверия. Если до истечения меньше 14 дней — предупреждение. Меньше 7 дней — критический алерт. У нас был один кейс, когда certbot на одном сервере тихо перестал работать (конфигурационный конфликт после обновления Nginx), и мы узнали об этом за 10 дней до истечения, а не когда сертификат уже умер.

Где хранить все эти данные — и почему мы выбрали PostgreSQL вместо time-series БД

Когда начинаешь думать об архитектуре хранения метрик, первое, что лезет в голову — это специализированные time-series базы данных. InfluxDB, TimescaleDB, VictoriaMetrics. Они оптимизированы именно под временные ряды, умеют хорошо сжимать данные, быстро делают агрегации по времени. Это правильный выбор для больших систем, где миллионы точек в секунду.

Я долго думал, идти ли по этому пути. В итоге решил не идти — и сейчас считаю это правильным решением для нашего масштаба. Объясню почему.

У нас 15 серверов. Мы собираем метрики каждые 30 секунд. За сутки это 2880 точек на сервер, за месяц — примерно 86 400. Для всех серверов за месяц — около 1,3 миллиона записей. Это вполне комфортная нагрузка для PostgreSQL с нормальными индексами. Да, специализированная time-series БД была бы быстрее на запросах типа "дай мне среднее значение CPU за последние 6 часов с шагом 5 минут". Но PostgreSQL со своими возможностями date_trunc и window functions тоже это умеет, и при нашем масштабе разница в миллисекунды.

Зато у PostgreSQL есть огромное преимущество: в той же базе живут все остальные данные. Инциденты, логи, настройки алертов, SSL-статусы, пользователи. Когда ты хочешь сделать запрос "покажи мне все инциденты за последний месяц, рядом с которыми был пик CPU выше 90%" — в PostgreSQL это один JOIN. С двумя разными базами данных это становится сложной оркестрацией на уровне приложения.

Отдельный вопрос — ретенция данных. Метрики с серверов мы храним на разных уровнях детализации. Сырые метрики (каждые 30 секунд) — 7 дней. Агрегированные по часам — 90 дней. Агрегированные по дням — 1 год. Это классический подход downsampling, который позволяет не раздувать базу до бесконечности, сохраняя при этом исторические данные для анализа трендов. Реализация простая: cron-задача в 3 ночи берёт метрики старше 7 дней, агрегирует их по часам (среднее, максимум, минимум CPU/RAM/disk за каждый час) и удаляет исходные записи.

Логи хранятся отдельно и с более коротким retention. По умолчанию 30 дней, но это настраивается через переменную окружения. Логи занимают значительно больше места, чем метрики, потому что это текст, а не числа. За 30 дней на 15 серверах с умеренной нагрузкой у нас накапливается примерно 2-3 GB логов в базе. Это вполне управляемо.

Важный момент, который я не сразу сообразил: индексы имеют принципиальное значение при работе с таблицами метрик. Когда у тебя миллион строк и ты делаешь запрос "все метрики для сервера X за последние 24 часа" — без составного индекса по (server_id, created_at) это может занять секунды. С индексом — миллисекунды. Звучит очевидно, но я видел несколько проектов, где об индексах думали уже после того, как база начала тормозить.

HealthSnapshot — отдельная таблица для агрегированных статусов подсистем. Она маленькая по объёму, но очень важная: там хранится история состояния Bitrix24, 1С, телефонии, бэкапов с шагом в 2 минуты за последние 7 дней. Это позволяет строить графики аптайма для каждой интеграции и видеть, когда и как долго была проблема.

Docker-контейнеры: мониторинг того, что внутри серверов

Большинство наших сервисов работают в Docker-контейнерах. Это современная реальность: даже на сервере с FASTPANEL часть сервисов живёт в контейнерах. Mailcow — это целый стек из примерно 12 контейнеров. Supabase — ещё больше. VPN — контейнер с wg-easy. И так далее.

Мониторинг на уровне сервера (CPU сервера, RAM сервера) здесь недостаточен по одной причине: ты видишь, что сервер загружен на 80% CPU, но не видишь, какой из 12 контейнеров это делает. И диагностика превращается в SSH на сервер и `docker stats` руками.

Мы добавили отдельный слой мониторинга контейнеров. Раз в час наш бэкенд коннектится к каждому серверу, где есть Docker, и собирает `docker ps --format json` — статусы всех контейнеров, uptime, health check результаты. Плюс `docker stats --no-stream --format json` — CPU и RAM для каждого контейнера в конкретный момент. Это тяжелее, чем системные метрики, поэтому делаем реже.

Самое ценное здесь — healthcheck-статусы. Если в docker-compose.yml настроен healthcheck (а у Mailcow, Supabase и большинства наших стеков он есть), то Docker сам знает, здоров контейнер или нет. `docker inspect` возвращает `Status: healthy / unhealthy / starting`. Мы собираем это и показываем на дашборде: зелёный кружок у контейнера — healthy, жёлтый — starting или нет healthcheck, красный — unhealthy или not running.

Была ситуация с Mailcow: один из внутренних контейнеров (rspamd, антиспам-движок) тихо умер ночью. Сервер при этом выглядел абсолютно нормально — CPU 5%, RAM 40%, всё спокойно. Без мониторинга контейнеров мы бы не знали об этом до первой жалобы на то, что письма не фильтруются. Но контейнер показал статус unhealthy, алерт ушёл в Telegram, я увидел утром и поднял rspamd за две минуты.

Логи контейнеров — это отдельная история. Мы не тащим все логи постоянно (это огромный объём данных), а делаем умный сбор: раз в час смотрим на `docker logs --tail 100 --since 1h` каждого контейнера и ищем в них паттерны ошибок — `error`, `fatal`, `critical`, `exception`, `panic`. Если находим — пишем в таблицу логов с меткой источника. Это позволяет на странице логов видеть не сырой поток событий, а только то, что требует внимания.

Bitrix24 и интеграции: мониторинг не только серверов, но и бизнес-процессов

Когда я говорю "мониторим инфраструктуру", большинство людей думают: серверы, контейнеры, сеть. Но для нас критическими являются ещё и бизнес-системы. Bitrix24 — это CRM, которая живёт в облаке Битрикс, не у нас. Но если она недоступна или работает с задержками, это проблема такого же уровня, как упавший сервер.

Мы добавили мониторинг Bitrix24 через вебхуки. Раз в несколько минут делаем запрос к API Bitrix24 и проверяем время ответа. Нормальный ответ — до 500 мс. Медленный — 500 мс — 2 секунды. Очень медленный — больше 2 секунд, это уже деградация сервиса. Параллельно проверяем SIP-статус телефонии (у нас телефония интегрирована через Битрикс) и баланс на счету телефонии. Последнее звучит смешно, но мы однажды обнаружили нулевой баланс только потому, что кто-то позвонил и сказал "у вас телефон не работает". С тех пор мониторинг баланса — обязательная вещь.

Помимо доступности API, мы мониторим дубли в CRM. Это специфический для нас показатель: когда менеджеры вручную создают контакты, периодически возникают дубли (один и тот же клиент под двумя разными карточками). Это проблема не техническая, а операционная — но она влияет на качество данных и работу менеджеров. Раз в сутки мы запускаем поиск дублей по телефону и email и показываем их количество на дашборде. Не 0 — идёт в задачи для разбора.

GitHub — ещё одна интеграция. Мы мониторим статусы GitHub Actions для всех наших репозиториев. Это важно потому, что у нас настроен автодеплой: push в main → запускается workflow → деплой на сервер. Если workflow упал, а ты не знаешь — в production старая версия. Мы видим статус последнего запуска для каждого репозитория прямо на дашборде. Красный кружок у репозитория — workflow упал, надо разбираться.

Есть ещё одна интеграция, которую я считаю недооценённой — мониторинг API-ответов самих сервисов, а не только того, что сервер "живой". Разница принципиальная: сервер может быть живым (ping проходит, SSH работает, Docker-контейнеры running), но приложение при этом возвращать 500 на все запросы. Это может быть ошибка в базе данных, переполненный диск в tmpfs, протухший токен во внешней интеграции. Нужен именно application-level healthcheck.

Мы добавили endpoint `/api/health` в наш бэкенд, который не просто возвращает 200, а реально проверяет: коннект к базе данных работает, Prisma отвечает, основные таблицы доступны. И этот endpoint мы мониторим снаружи — через site monitor, который делает HTTP-запрос и проверяет не только код ответа, но и содержимое тела ответа. Если в теле нет `"status":"ok"` — это не просто медленный ответ, это реальная проблема приложения.

1С на Windows: особая история

Честно говоря, мониторинг 1С-сервера стал для меня самым неожиданным опытом во всём этом проекте. Я знал, что будет непросто, но не предполагал, что настолько много нюансов.

1С Управление торговлей работает на выделенном Windows Server. Это типичная конфигурация для промышленного предприятия — не виртуалка в облаке, а физическая машина с хорошим железом, потому что 1С любит ресурсы. И сразу же первый вопрос: как к ней подключаться? SSH на Windows требует установки OpenSSH Server, что мы и сделали, но работает это немного иначе, чем на Linux.

Что мы мониторим в 1С? Активные сессии — сколько пользователей сейчас работают. Это важно для планирования обслуживания: если хочешь сделать резервное копирование или обновление, нужно знать, когда сервер свободен. Блокировки — это особая метрика 1С. Когда два пользователя работают с одними данными одновременно, возникают блокировки, и если их много — система начинает тормозить. Мы смотрим количество блокировок через OData-интерфейс 1С и при превышении порога создаём инцидент. Регламентные задания — в 1С есть фоновые задачи (закрытие периода, пересчёт итогов, обмены данными), которые должны выполняться по расписанию. Если регламентное задание не выполнилось — это проблема, которую часто не замечают, пока не обнаруживают расхождение данных.

Технологический журнал 1С — это отдельный зверь. Это логи самого 1С-сервера, которые пишутся в XML-файлы на диске. Мы парсим их через SSH, ищем события с уровнем EXCP (исключения) и длительными запросами (дольше 3 секунд). Это позволяет заранее видеть, где начинаются проблемы с производительностью, до того как пользователи начнут жаловаться.

Резервное копирование 1С — это отдельная головная боль, которую мы решили через S3. Бэкапы уходят в отдельный бакет в Timeweb Object Storage. Наш мониторинг каждые 30 минут проверяет: когда был создан последний файл бэкапа в S3? Если больше 25 часов назад — это стale, алерт. Если больше 48 часов — это critical. Такой подход работает независимо от того, как именно делается бэкап (скрипт, встроенный в 1С, сторонний инструмент) — нам важен только факт появления свежего файла в бакете.

Важная деталь про пароли: пароль от SSH на Windows-сервере заканчивается на восклицательный знак. В bash history expansion раскрывает `!` в двойных кавычках, что может привести к передаче неправильного пароля или к ошибке. Правило, которое я жёстко соблюдаю: SSH-пароли только через переменные окружения и одинарные кавычки в bash, никогда не inline в команде.

Несколько реальных инцидентов и чему они нас научили

Хочу рассказать о нескольких конкретных случаях, потому что в них весь смысл того, зачем мы всё это строили.

История первая — масла.сайт и диск. Это e-commerce с загрузкой медиафайлов. Продавцы загружают фотографии товаров, генерируются превью в нескольких размерах, пишутся логи Nginx. Диск на сервере 100 GB. Мы поставили алерт на 85% заполненности. Однажды в пятницу вечером алерт сработал — 87%. Я зашёл на сервер, посмотрел что занимает место. Оказалось, что за три месяца накопилось около 8 GB логов Nginx, которые ротировались неправильно — файлы старше 30 дней не удалялись из-за ошибки в конфиге logrotate. Почистил, подправил конфиг. Если бы не мониторинг, узнал бы об этом когда диск был бы под 100% и сайт начал бы падать на попытках записи. А пятница вечером — это, как правило, максимум заказов в e-commerce.

История вторая — почта и rspamd. Я уже упоминал её коротко, но хочу рассказать детальнее, потому что она показывает ценность именно контейнерного мониторинга. Mailcow — это стек из 12 Docker-контейнеров. Один из них — rspamd, антиспам-движок. Он тихо упал ночью — по ошибке в памяти Redis, которую rspamd использует для хранения статистики. Всё остальное продолжало работать: письма приходили, отправлялись, сервер был доступен. Но фильтрации спама не было. Если бы это длилось сутки или двое, почтовый ящик засорился бы сотнями спам-писем. Благодаря healthcheck-мониторингу контейнеров мы увидели unhealthy-статус rspamd утром и поправили за пять минут.

История третья — SSL и certbot. Certbot обновляет сертификаты автоматически по cron. Это работает везде и всегда, пока однажды не перестаёт. У нас certbot перестал работать на одном из серверов после обновления пакетов системы — изменился путь к Python, который certbot использует, и cron-задача начала тихо падать. Тихо — значит без видимых ошибок снаружи, без пуш-уведомлений. Сертификат продолжал работать, потому что до истечения ещё оставалось время. Наш SSL-мониторинг поймал ситуацию за 11 дней до истечения, когда автоматическое обновление уже должно было сработать, но не срабатывало. Мы разобрались, исправили, сертификат продлили вручную. Без мониторинга — звонок от клиента с сообщением "у вас сайт не открывается".

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

Алерты, инциденты и то, почему "просто отправить в Telegram" — плохая идея

Когда мониторинг только заработал, мы настроили простую логику: если CPU выше 80% — шлём сообщение в Telegram. Если диск занят больше 85% — шлём. Если сайт не отвечает — шлём. Казалось бы, всё правильно.

Через неделю я захотел выключить Telegram-уведомления вообще. Потому что раз в несколько минут приходило что-то вроде "CPU на masla-site 87%", потом через пару минут "CPU на masla-site 72%", потом снова "CPU на masla-site 89%". Masla.сайт — это e-commerce с реальным трафиком, там CPU скачет постоянно. Это не проблема, это норма. Но мониторинг об этом не знал.

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

Сейчас алерт создаётся не мгновенно, а по правилу: если метрика превышает порог в течение нескольких последовательных проверок подряд (для CPU — 3 проверки по 30 секунд, итого полторы минуты устойчивого превышения), только тогда это становится алертом. Это отсеивает почти все ложные срабатывания на кратковременные пики.

Второй важный элемент — инциденты как отдельная сущность. Алерт — это событие ("произошло что-то"). Инцидент — это проблема с жизненным циклом (открыт, в работе, закрыт). Мы разделили их: алерты создаются автоматически по правилам, инциденты — либо автоматически из алертов для критических событий, либо вручную. К инциденту можно добавлять события с таймлайном: "обнаружили проблему", "начали расследование", "нашли причину", "применили фикс", "подтвердили решение". Это создаёт историю для каждой аварии, и через месяц можно посмотреть: какие инциденты были, как долго длились, что было причиной.

Telegram и email работают по-разному. В Telegram уходят только алерты уровня critical с кратким описанием — одно-два предложения. Email с полным отчётом приходит раз в день утром и раз в день вечером: сводка по всем серверам, статистика инцидентов за день, топ-5 самых нагруженных машин. Такой подход работает: Telegram даёт мгновенное внимание когда нужно, email даёт контекст и историю без необходимости срочной реакции.

Третий элемент, который я долго не хотел делать, но в итоге рад, что сделал — это подавление алертов. Когда мы знаем, что сервер будет недоступен (плановое обслуживание, миграция, обновление), можно поставить временный mute на алерты с этого сервера. Без этой функции плановое окно обслуживания превращается в поток уведомлений, которые приходится игнорировать, что воспитывает плохую привычку игнорировать уведомления вообще.

Интерфейс: как выглядит "единое окно" изнутри

Я долго думал, писать ли об интерфейсе вообще. Казалось бы, это вторично — главное данные. Но потом понял, что интерфейс — это ровно половина ценности системы мониторинга. Данные есть везде. Но если для их просмотра нужно кликать через пять уровней меню или собирать дашборд руками в Grafana — большинство людей этого делать не будет. Мониторинг должен быть таким, чтобы ты заходил в него потому что это удобно, а не потому что заставляешь себя.

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

Главный экран дашборда — это сводная карта всех серверов. Каждый сервер — карточка: название, IP, локация (москва/питер/амстердам/dedicated), текущие CPU/RAM/disk в виде цветных полосок (зелёный — ок, жёлтый — внимание, красный — критично), количество активных контейнеров и сколько из них healthy. Внизу каждой карточки — время последней проверки. Всё это помещается на один экран без скролла, если у тебя монитор нормального размера. Я специально добивался именно этого: открыл — сразу видишь всё.

Страница конкретного сервера — это уже детали. Графики CPU/RAM/disk за последние 24 часа, 7 дней, 30 дней (с переключалкой). Список контейнеров с их статусами и ресурсами. Последние логи с фильтром по уровню (error, warning, info). SSH-терминал прямо в браузере — WebSocket-мост к серверу, можно выполнить команду не выходя из дашборда. Это последнее особенно ценно: видишь проблему и тут же начинаешь разбираться, не переключая контекст.

Страница логов — это общая лента со всех серверов и интеграций с фильтрами по источнику, уровню и времени. Здесь же статистика: сколько ошибок за последние 24 часа по каждому источнику, топ повторяющихся сообщений. Это помогает замечать паттерны. Если одна и та же ошибка встречается 50 раз за сутки — скорее всего это не случайность, а системная проблема, которую стоит разобрать.

Страница инцидентов — это список открытых и закрытых инцидентов с таймлайном. Для каждого инцидента видно: когда открыт, кем (системой автоматически или вручную), какие события были в процессе, когда закрыт и как долго длился. Отдельный фильтр "только открытые" — это то, что смотришь утром после логов.

Одна деталь, которая кажется незначительной, но сильно влияет на удобство: мобильная версия. Дашборд адаптирован под телефон. Это важно потому, что инциденты случаются не только когда ты за ноутбуком. В выходной день, в дороге — быстро проверить статус и базово понять что происходит должно быть возможно с телефона. Не глубокая диагностика, не SSH-терминал (хотя и он работает), а именно быстрый взгляд: всё ли нормально, надо ли срочно садиться за компьютер.

AI-анализ логов: где это реально работает, а где пока нет

Я изначально был скептиком насчёт AI в мониторинге. Слишком много хайпа вокруг "AI предскажет проблему за час до того, как она случится". На практике это работает не совсем так.

Мы подключили AI-анализ на двух уровнях. Первый — анализ логов по запросу. Когда происходит что-то непонятное (контейнер падает, сервис тормозит, появляются странные ошибки), я жму кнопку "Проанализировать" в интерфейсе, и AI получает последние N строк логов плюс контекст (что это за сервер, какие сервисы там работают) и отвечает — что, по его мнению, происходит, и что стоит проверить. Это работает очень хорошо. Не как оракул, а как умный коллега, который быстро просматривает логи и говорит "смотри, вот тут три OOM killer события за последний час, скорее всего памяти не хватает". Без AI я бы сам до этого дошёл, но потратил бы 10 минут вместо 30 секунд.

Второй уровень — автоматический анализ каждые 7 часов. Берём последние логи и метрики по всем серверам, отдаём AI, получаем краткий отчёт с аномалиями и рекомендациями. Этот отчёт сохраняется в системе и доступен на дашборде. Честно скажу: полезность этого уровня пока меньше. AI иногда замечает реальные тренды (например, постепенный рост использования диска на конкретном сервере с оценкой "при текущей скорости роста закончится через 12 дней"), но чаще выдаёт очевидные вещи или рекомендации общего характера.

Где AI точно не работает так, как рекламируется — это "предсказание сбоев". Да, он может заметить тренд на росте нагрузки. Но большинство реальных сбоев случается не по тренду, а внезапно: обновление пакета сломало зависимость, DNS-запись протухла, память утекла из-за бага в приложении. Это не предсказывается через анализ метрик.

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

Что в итоге изменилось и какие выводы я сделал

Прошло достаточно времени с момента, как мы запустили всё это в работу, чтобы подводить осмысленные итоги. Не технические (технических итогов типа "мы написали 5000 строк TypeScript" вам не нужно), а практические.

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

Второе — мы начали видеть проблемы до того, как они становятся инцидентами. За прошедший период было несколько случаев, когда мониторинг поймал что-то до того, как это превратилось в аварию: медленно растущий диск, деградирующий контейнер с плохими healthcheck-ами, SSL-сертификат за 10 дней до истечения, 1С-регламентное задание которое перестало выполняться. Ни одно из этих событий не стало инцидентом с последствиями для бизнеса. Это, наверное, главная метрика успешности мониторинга.

Третье — документирование инфраструктуры. Когда у тебя есть система, которая постоянно сканирует серверы и знает, что на них работает, появляется актуальная карта инфраструктуры. Это звучит банально, но у большинства компаний, с которыми я работал, такой карты нет — есть разрозненные таблички в Notion или у кого-то в голове. Когда в три ночи что-то падает, очень хорошо иметь инструмент, который покажет: вот этот сервер, вот его контейнеры, вот последние логи, вот история инцидентов.

Теперь о том, что я бы сделал иначе, знай я это с самого начала.

Я бы не пытался мониторить всё с самого начала. Начинать надо с самого важного: uptime сайтов, SSL-сертификаты, заполненность дисков. Это три метрики, которые наиболее часто вызывают проблемы с реальными последствиями. Всё остальное (Docker-статистика, логи, AI-анализ) можно добавлять постепенно.

Я бы с самого начала потратил время на настройку алертов. Не на сбор данных, а именно на то, какие события реально требуют моего немедленного внимания. Плохо настроенные алерты хуже, чем их отсутствие: они приучают игнорировать уведомления, что убивает весь смысл мониторинга.

И ещё один вывод, который кажется мне важным: мониторинг — это не проект, который когда-то заканчивается. Это живая система, которую надо постоянно дорабатывать под изменяющуюся инфраструктуру. Добавили новый сервер — добавили его в мониторинг. Изменилась нагрузка на сервис — пересмотрели пороговые значения. Появилась новая критичная зависимость — добавили проверку. Если к мониторингу относиться как к "настроили и забыли", через полгода он устаревает и перестаёт адекватно отражать реальность.

Когда меня спрашивают, стоит ли тратить время на разработку собственного дашборда или лучше взять готовое решение — Grafana, Zabbix, Datadog — у меня нет универсального ответа. Готовые решения мощнее и надёжнее. Но у собственного инструмента есть одно неоспоримое преимущество: он делает ровно то, что тебе нужно, и ничего лишнего. Grafana требует времени на освоение. Datadog стоит серьёзных денег при нашем масштабе. Zabbix — это целый зоопарк с агентами на каждом сервере. Наш инструмент знает, что такое 1С, что такое Bitrix24, как устроена наша инфраструктура. Это не конкурент энтерпрайзным решениям. Это наш инструмент, под наши задачи.

В конце концов, мониторинг — это не про технологии. Это про уверенность. Уверенность в том, что если что-то пойдёт не так, ты узнаешь первым. Не от клиента, не от пользователя, не от коллеги, который случайно заметил — а от системы, которая смотрит за инфраструктурой круглосуточно, пока ты занимаешься другими делами. Ради этой уверенности всё и затевалось.

Есть ещё один момент, о котором редко говорят в контексте мониторинга, и он кажется мне важным. Хорошо работающий мониторинг меняет не только реакцию на проблемы, но и то, как ты принимаешь решения по инфраструктуре. Когда у тебя есть история метрик за полгода, ты можешь обоснованно решить: стоит ли апгрейдить этот сервер или нагрузка реально небольшая, и деньги лучше потратить на другое. Ты видишь, что сервер с масла.сайт действительно нужен на 8 CPU — потому что в пиковые часы он реально под 70% нагрузки. А вот тестовый сервер с Supabase можно смело уменьшить, потому что за три месяца нагрузка ни разу не превышала 15%. Это не экономия ради экономии — это осознанное управление ресурсами на основе данных, а не ощущений.

Я не знаю, будем ли мы когда-нибудь мигрировать с самописного инструмента на что-то стандартное. Может быть, когда инфраструктура вырастет до 50+ серверов — тогда, наверное, энтерпрайзные решения начнут оправдывать свою сложность и стоимость. Но пока наш дашборд закрывает всё, что нам нужно, и делает это ровно так, как нам удобно. А это, на мой взгляд, и есть главный критерий успеха любого инструмента.