Давайте дружить в Телеграме: рассказываем про новые фичи и общаемся в комментах Подписаться
support@serv.host
Личный кабинет

Свой мониторинг: Uptime Kuma или Prometheus с Grafana, и почему он обязан жить на отдельном сервере

Свой мониторинг: Uptime Kuma или Prometheus с Grafana, и почему он обязан жить на отдельном сервере

Вообще я микроразработчик, со мной можно связаться как угодно, я открыт ко всему

Сторонний мой проект: Zapret2UI.


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

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

Только стоял он на том же сервере, который и лёг.

Схема настолько распространённая, что её пора считать обрядом посвящения. Человек поднимает VPS, ставит туда сайт, базу, бота, а потом рядышком в докере поднимает Uptime Kuma - «чтобы всё было в одном месте, удобно же». И живёт с ощущением, что прикрыт. Пока не выясняется, что прикрыт он ровно от тех проблем, которые и так бы заметил: упал контейнер, кончилось место, отвалился сертификат. А от того единственного сценария, ради которого мониторинг и заводят - машина целиком перестала отвечать - не прикрыт вообще никак.

Разберём, чем Uptime Kuma отличается от связки Prometheus с Grafana (спойлер: они отвечают на разные вопросы и вообще не конкуренты), сколько это ест ресурсов, как развести мониторилку и цели по разным машинам и не открыть при этом дыру на весь интернет. И отдельно - кто сторожит самого сторожа.

Кому пригодится: если у вас один-два сервера и вы до сих пор узнаёте о падениях от людей; если хочется графиков, а не только «ок / не ок»; или если мониторинг уже есть, но вы подозреваете, что он стоит не там, где надо.

Всё, что ниже, гоняется на самом дешёвом VPS. Отдельная машина под мониторинг обходится дешевле одного часа простоя - если из статьи запомнить одну строчку, пусть будет эта.


Содержание

  1. Почему мониторинг на том же сервере бесполезен
  2. Два разных вопроса к своей инфраструктуре
  3. Uptime Kuma: десять минут и работает
  4. Prometheus и Grafana: когда нужен ответ «почему»
  5. Как теперь мониторинг доберётся до целей
  6. Главная дыра: node_exporter наружу
  7. Кто сторожит сторожа
  8. Как не оглохнуть от алертов
  9. Что в итоге брать
  10. Частые ошибки
  11. Где это поднимать
  12. Короткий итог

Источники


Почему мониторинг на том же сервере бесполезен

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

Разложим по уровням отказа, от мелкого к крупному.

Упал один сервис. Отвалился nginx, ушёл в себя PostgreSQL, контейнер перезапускается по кругу. Вот тут локальный мониторинг работает нормально: он жив, он видит, что порт не отвечает, он шлёт уведомление. Одна беда - такие штуки вы и без него заметите за час, а часто и за минуту.

Кончилась память, пришёл OOM killer. Ядро начинает отстреливать процессы по оценке oom_score, и жертвой становится не обязательно тот, кто съел память. Прожорливый питоновский скрипт может выжить, а мониторилка на Node.js - улететь первой, просто потому что у неё резидентная память больше. Уведомление не уходит, потому что уходить уже некому.

Машина встала целиком. Кернел-паника, зависший гипервизор, сосед по ноде устроил дискотеку и всё встало в iowait. Мониторинг мёртв ровно в тот момент, когда он нужен. Ноль уведомлений, полная тишина.

Отвалилась сеть. Вот это самое обидное. Сервер жив, все процессы крутятся, мониторинг честно видит, что локально всё зелёное. Но пакеты наружу не уходят: упал аплинк, хостер словил DDoS и загнал вашу подсеть в блэкхол, IP приехал в блэклист (про это есть отдельная статья(Не вышла на момент написания)). Мониторинг не сломан, он просто не может докричаться. Снаружи ваш сервис недоступен уже сорок минут, а внутри всё прекрасно.

Лёг дата-центр. Тут комментарии излишни.

Видите закономерность? Чем серьёзнее авария, тем меньше шансов, что локальный мониторинг о ней сообщит. Он надёжен ровно там, где не нужен, и бесполезен ровно там, где нужен. Это как поставить пожарную сигнализацию внутри печки.

Есть и вторая причина, менее очевидная

Наблюдатель искажает наблюдаемое. Prometheus с его базой временных рядов постоянно пишет на диск: WAL, потом блоки каждые два часа, потом компакция. Grafana при отрисовке дашборда за месяц выгребает из базы прилично данных и грузит процессор.

И вот вы сидите, смотрите на график iowait, пытаетесь понять, почему у вас тормозит диск. А часть этого iowait рисует сам мониторинг. На сервере с нормальным NVMe это в пределах погрешности, а вот на дешёвом тарифе с общим дисковым пулом - уже нет. Вы меряете термометром температуру термометра.

Что считать «отдельным»

Тут градация, и она важнее, чем кажется:

  • Тот же сервер. Не мониторинг. Просто красивые графики, которые исчезнут вместе с сервером.
  • Другая виртуалка у того же хостера. Уже лучше, но если это соседняя VPS на той же физической ноде - вы прикрыты только от программных проблем. Нода легла, легли обе.
  • Другой дата-центр того же хостера. Нормально. Разные машины, разные аплинки, разное питание. Общая точка отказа остаётся одна: биллинг. Забыли продлить - и всё погасло одновременно, включая мониторинг, который должен был об этом предупредить.
  • Другой хостер, другая страна. Правильно. Никакой общей точки отказа, кроме вашей банковской карты.

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

Теперь про обратную сторону, иначе картина выйдет слишком благостной. У выноса наружу есть плата: между мониторингом и целью теперь лежит сеть, и все замеры получаются с её примесью. Проверка сказала «ответ за 900 мс» - и это может значить «сайт тормозит», а может «маршрут между двумя ДЦ вечером превращается в тыкву». Отличать одно от другого надо уметь, а про это у меня отдельная статья о том, почему пинг ничего не говорит(Не вышла на момент написания). Но даже с этой примесью внешний мониторинг честнее внутреннего, потому что он меряет то же самое, что видит пользователь.


Два разных вопроса к своей инфраструктуре

Сравнивать Uptime Kuma с Prometheus в лоб - примерно как сравнивать градусник с анализом крови. Вроде оба про здоровье, но задачи разные.

Вопрос первый: оно вообще живое? Бинарный, снаружи, без доступа внутрь. Дёрнули порт, дёрнули URL, посмотрели на код ответа. Такой подход называют black-box: что внутри коробки, нас не волнует, волнует только отвечает она или нет. Ровно это и делает Uptime Kuma.

Вопрос второй: почему оно так себя ведёт? Тут снаружи ничего не увидишь. Нужны цифры изнутри: сколько свободной памяти, какой iowait, сколько открытых соединений, сколько времени процесс провёл в GC. Это white-box, и это территория Prometheus.

Разница проявляется в тот момент, когда что-то сломалось. Kuma скажет: «сайт не отвечал с 03:12 до 03:47». Полезно, спору нет. Но на вопрос «а почему» она не ответит никогда, потому что данных у неё нет - она снаружи стояла. Prometheus покажет, что с 02:50 начала расти память, к 03:10 своп забился под завязку, в 03:12 приехал OOM killer. Вот это уже разбор полётов.

Обратный случай тоже бывает. Prometheus видит только то, до чего дотягивается его scrape. Если у вас лёг DNS и домен перестал резолвиться, все метрики останутся зелёными: сервер жив, процессы крутятся, всё прекрасно. А сайт при этом не открывается ни у кого. Внешняя проверка, которая ходит по домену как обычный пользователь, поймает это мгновенно.

Поэтому «Kuma против Prometheus» - неправильная постановка. Правильная звучит так: чем закрывать вопрос «живо ли», а чем вопрос «почему». Довольно часто ответ на оба - «поставить оба, они не мешают друг другу».


Uptime Kuma: десять минут и работает

Опенсорсная мониторилка от Louis Lam, на Node.js, с приятным интерфейсом и репутацией «поставил и забыл». В августе 2026-го актуальна ветка 2.x, последняя версия 2.5.0.

Что она умеет проверять: в двойке типов проверок стало за тридцать. Самое ходовое:

  • HTTP(s) - код ответа, время ответа, редиректы, свои заголовки и метод.
  • Ключевое слово на странице. Отдельно ценная штука: сайт может честно отдавать 200 и при этом показывать заглушку «технические работы». Проверка на слово ловит то, что код ответа проглатывает.
  • TCP-порт - для баз, прокси, SSH, всего, у чего нет HTTP.
  • Ping - именно ICMP. Работает, но врёт чаще всех остальных, об этом ниже.
  • DNS - резолвится ли имя и в тот ли адрес.
  • Срок действия сертификата. Из коробки, без плясок. Предупредит заранее, что через N дней всё встанет.
  • Docker-контейнер через сокет, gRPC, SNMP, Kafka, RabbitMQ и прочая экзотика, которая в двойке подъехала.

Каналов уведомлений в 2.x стало 91. В реальной жизни используются полтора: Telegram и почта. Telegram настраивается за минуту через BotFather, и это правда самый удобный вариант для одиночки.

Push-мониторы - штука, которую все проглядывают

Обычная проверка работает так: Kuma сама ходит и стучится. Push-монитор работает наоборот: Kuma генерирует уникальный URL, сидит и ждёт, что кто-то на него постучится. Не постучались в срок - уведомление.

Зачем это надо? Затем, что так проверяются вещи, у которых нет порта. Бэкап по крону, ротация логов, скрипт синхронизации, задача, которая должна отработать раз в сутки. Дописываете в конец крон-задания одну строку:

0 4 * * * /opt/backup.sh && curl -fsS -m 10 https://kuma.example.com/api/push/AbCdEf12

И теперь вы узнаете о двух разных бедах: что бэкап упал и что он тихо перестал запускаться вообще. Второе случается чаще, а обнаруживается обычно в самый неподходящий момент - когда бэкап понадобился.

Страница статуса

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

Ресурсы и установка

Node.js 20 и выше, база по умолчанию SQLite (в двойке появилась опциональная MariaDB - нужна, если у вас сотни мониторов, при десятке она только лишняя деталь). Ест в районе двух-трёх сотен мегабайт памяти. На тариф 1 vCPU / 1 ГБ встаёт с большим запасом.

# docker-compose.yml
services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    container_name: uptime-kuma
    restart: unless-stopped
    volumes:
      - ./data:/app/data
    ports:
      - "127.0.0.1:3001:3001"

Обратите внимание на 127.0.0.1 в проброске порта. Наружу вешать веб-морду мониторинга не надо, заверните её через nginx с нормальным TLS, а лучше вообще спрячьте за WireGuard. В админке мониторинга лежит полная карта вашей инфраструктуры: адреса, порты, имена сервисов. Отличный подарок тому, кто её найдёт.

Ещё нюанс при переезде с единички: официальный образ 2.x запускается от непривилегированного пользователя. Штука правильная, но старая папка data осталась с рутовыми правами, и контейнер в неё не запишет. Лечится одной командой chown перед первым запуском, но если не знать, выглядит как «обновился и всё сломалось».

Чего она не умеет

И вот тут начинается граница применимости. Kuma хранит историю пингов, но это не база метрик. Она не ответит:

  • почему во вторник вечером всё тормозило (данных о нагрузке у неё нет);
  • сколько осталось места на диске и когда оно кончится;
  • растёт ли потребление памяти третью неделю подряд;
  • какой из ваших пяти сервисов съел процессор.

Всё это не потому, что Kuma плохая, а потому, что она стоит снаружи и внутрь не заглядывает. Хотите ответы - нужна база временных рядов.


Prometheus и Grafana: когда нужен ответ «почему»

Тут не одна программа, а конструктор из нескольких. Сразу предупреждаю: порог входа заметно выше, за вечер вы это не соберёте, если раньше не собирали.

Как это устроено

Prometheus - база временных рядов плюс сборщик. Работает по pull-модели: он сам ходит на цели по HTTP и забирает метрики. Никакие агенты никуда ничего не отправляют, инициатива всегда на стороне Prometheus.

Что он забирает - обычный текст:

node_memory_MemAvailable_bytes 3.221225472e+09
node_filesystem_avail_bytes{mountpoint="/",fstype="ext4"} 2.1474836e+10
node_cpu_seconds_total{cpu="0",mode="steal"} 1834.21

Имя метрики, метки в фигурных скобках, число. Всё. Каждые пятнадцать секунд (или сколько настроите) Prometheus дёргает эту страницу и складывает значения к себе с меткой времени. Из этого потом строятся графики и считаются условия для алертов.

Отдельно отмечу приятный побочный эффект pull-модели: если цель не ответила на scrape, Prometheus сам синтезирует метрику up со значением ноль. То есть базовая проверка «жив ли хост» получается бесплатно, без всякой отдельной настройки.

Экспортеры - маленькие демоны, которые отдают ту самую страницу с метриками. node_exporter для системных метрик Linux, blackbox_exporter для внешних проверок HTTP/TCP/ICMP (по сути, тот же функционал, что у Kuma, только в терминах Prometheus), плюс отдельные экспортеры под PostgreSQL, nginx, Redis и вообще всё на свете.

Alertmanager - отдельный компонент, который принимает сработавшие алерты от Prometheus и решает, что с ними делать: кому слать, как группировать, что заглушить. Разделение неочевидное, но правильное: Prometheus считает условия, Alertmanager разруливает уведомления.

Grafana - рисовалка. Ходит в Prometheus, строит графики. С тринадцатой версии (её показали на GrafanaCON в апреле 2026-го) там ещё и своё алертинг-хозяйство, довольно вменяемое.

Кстати про версии, потому что в гайдах каша. Третий Prometheus вышел в ноябре 2024-го, и это было первое крупное обновление за семь лет: новый интерфейс на React вместо древнего бутстрапа, полноценная поддержка UTF-8 в именах метрик, встроенный приём OTLP-метрик и Remote Write 2.0. Актуальная LTS на сегодня - 3.13.2. Если натыкаетесь на статью, где скриншоты со старым синим интерфейсом, статье как минимум пара лет, и половина советов оттуда уже мимо.

PromQL - за что всё это терпят

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

Реальная загрузка процессора в процентах:

100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

Тот самый steal time, из-за которого пишут в поддержку (подробно про него - в статье про оверселл):

avg by (instance) (rate(node_cpu_seconds_total{mode="steal"}[5m])) * 100

А вот этот запрос я считаю лучшей рекламой всего стека:

predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}[6h], 4*3600) < 0

Читается так: возьми, как менялось свободное место последние шесть часов, продли тренд на четыре часа вперёд и скажи, уйдёт ли оно в минус. То есть Prometheus предупреждает не «место кончилось», а «место кончится к утру». Разница между этими двумя уведомлениями - разница между спокойным вечером и подъёмом в четыре ночи.

Ни одна проверка типа «жив или нет» такого не сделает в принципе. Для прогноза нужна история, а история есть только у базы метрик.

Сколько это ест

Вот тут людей обычно пугают страшилками про гигабайты, поэтому давайте посчитаем на реальных числах.

node_exporter со стандартным набором коллекторов отдаёт порядка тысячи с небольшим временных рядов на хост. При интервале в 15 секунд это примерно 70-100 сэмплов в секунду с одного сервера. Пять серверов - около 500 сэмплов в секунду.

Формула для диска простая, она прямо в документации:

место = время_хранения × сэмплов_в_секунду × байт_на_сэмпл

Байт на сэмпл после сжатия выходит порядка полутора-двух. Считаем месяц хранения для пяти хостов: 2 592 000 секунд × 500 × 2 байта ≈ 2,6 ГБ. Не гигабайты ужаса, а пара гигабайт. По умолчанию Prometheus вообще хранит 15 дней, меняется флагом:

--storage.tsdb.retention.time=30d

С памятью честнее так: сам Prometheus на такой нагрузке уложится в гигабайт, но сверху ещё Grafana (250-500 МБ), Alertmanager и обычно пара экспортеров. Тариф на 1 ГБ вы забьёте и будете жить на грани, на 2 ГБ станет комфортно. Для сравнения: Uptime Kuma в тех же условиях занимает треть гигабайта и не замечает нагрузки вообще.

Если тесно с ресурсами, но история нужна - посмотрите в сторону VictoriaMetrics. Совместима с PromQL, ест заметно меньше, ставится в один бинарник. Grafana поверх работает так же.


Как теперь мониторинг доберётся до целей

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

И вот тут разница между двумя подходами становится практической, а не философской.

Uptime Kuma ходит туда, куда и так ходят все. Ей нужен ваш 443-й порт, ваш 80-й, ваш DNS. Всё это и так открыто наружу, потому что иначе сайт бы не работал. Никакой дополнительной поверхности атаки вы не создаёте, ставится и работает без единой настройки на стороне цели. За это её и любят, хотя вслух проговаривают редко.

Prometheus, наоборот, лезет внутрь. Ему нужен node_exporter на каждой цели, а это порт 9100, которого раньше не было. И вот его открывать наружу нельзя. Совсем.

Правильная схема выглядит так:

                 [ VPS с мониторингом ]
                  Prometheus + Grafana
                    Alertmanager
                          |
              WireGuard (10.8.0.0/24)
                    /           \
                   /             \
        [ сервер 1 ]           [ сервер 2 ]
        node_exporter          node_exporter
        слушает 10.8.0.2       слушает 10.8.0.3

Между мониторингом и целями поднимается WireGuard, экспортеры слушают только на внутреннем адресе туннеля, снаружи порт 9100 не существует вообще. Prometheus ходит по адресам внутри туннеля.

Конфиг Prometheus в таком раскладе:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

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

rule_files:
  - /etc/prometheus/rules/*.yml

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['10.8.0.2:9100', '10.8.0.3:9100']

  - job_name: 'blackbox'
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
          - https://example.com
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox:9115

Второй job - это blackbox_exporter, он же внешняя проверка. Обратите внимание, что живёт он на самой мониторилке и ходит на сайт снаружи, как обычный посетитель. Та самая функция, которую Kuma даёт из коробки и мышкой, а тут собирается из трёх блоков relabel-конфига. Хотите понять разницу в пороге входа - вот она, наглядно.

Экспортер на целевом сервере запускается с явным адресом:

# /etc/systemd/system/node_exporter.service
[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter \
  --web.listen-address=10.8.0.2:9100 \
  --collector.systemd
Restart=always

Весь смысл тут в --web.listen-address=10.8.0.2:9100. По умолчанию экспортер слушает на всех интерфейсах, и это надо менять руками.


Главная дыра: node_exporter наружу

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

node_exporter по умолчанию не требует никакой аутентификации. Пришёл, дёрнул /metrics, получил всё. И слушает он при запуске без флагов на всех интерфейсах. То есть базовая установка по гайду с первой страницы поиска выставляет ваш сервер наружу.

Aqua Security прогоняла это через Shodan и насчитала больше 296 тысяч торчащих в интернет экспортеров и ещё около 40 тысяч открытых серверов Prometheus. Триста с лишним тысяч машин, метрики которых может забрать кто угодно.

Что оттуда достаётся без единого пароля:

  • имя хоста, версия ядра, дистрибутив, аптайм;
  • полный список примонтированных файловых систем с путями и заполненностью;
  • все сетевые интерфейсы с адресами, включая внутренние и VPN-овые;
  • список юнитов systemd, если включён соответствующий коллектор - то есть перечень всего, что у вас крутится;
  • количество ядер, объём памяти, модель железа.

По отдельности каждый пункт вроде и не секрет. Вместе это готовая карта: что за система, насколько давно не обновлялась (аптайм в 400 дней означает, что ядро не патчилось с той же поры), какие сервисы запущены, какая внутренняя адресация. Разведка, за которую обычно надо потрудиться, отдаётся одним GET-запросом.

Отдельная история - профилировочные ручки Go по адресу /debug/pprof/. Они включены по умолчанию во многих компонентах Prometheus и сами по себе на пентестах отлетают как information disclosure. Плюс их можно использовать для отъедания ресурсов: запрос профиля - штука недешёвая.

Три способа закрыться, по возрастанию правильности:

  1. Файрвол. Тупо и работает: ufw allow from 10.8.0.1 to any port 9100. Минимум, ниже которого опускаться нельзя.
  2. Слушать не на всех интерфейсах. Флаг --web.listen-address на адрес приватной сети или туннеля. Порт просто не существует для внешнего мира.
  3. WireGuard плюс первые два пункта. Трафик метрик шифруется, экспортер вообще не виден снаружи, а Prometheus гарантированно разговаривает с вашей машиной, а не с чужой.

Если туннель по каким-то причинам не вариант, у экспортера с недавних версий есть встроенные TLS и basic auth через отдельный файл:

# /etc/node_exporter/web-config.yml
basic_auth_users:
  prometheus: $2y$10$<bcrypt-хэш-пароля>
tls_server_config:
  cert_file: /etc/node_exporter/cert.pem
  key_file: /etc/node_exporter/key.pem

Запускается с --web.config.file=/etc/node_exporter/web-config.yml. Это лучше, чем ничего, но туннель всё равно надёжнее.

И маленькая, но важная деталь: сама Grafana тоже не должна торчать наружу с дефолтным admin/admin. Смешно, но это до сих пор регулярно встречается.


Кто сторожит сторожа

Вынесли мониторинг на отдельную машину, молодцы. Теперь у вас две машины, и одна из них может лечь так же тихо, как раньше ложилась первая.

Проблема забавная своей рекурсивностью: мониторинг не может уведомить о собственной смерти. Ставить второй мониторинг для первого - путь в бесконечность.

Решается это через дохлого сторожа (dead man's switch): логику переворачивают. Вместо «сообщи, когда сломалось» - «постоянно сообщай, что всё в порядке, и если сообщения прекратились, значит, сломалось».

Для Prometheus это делается алертом, который всегда активен:

groups:
  - name: watchdog
    rules:
      - alert: Watchdog
        expr: vector(1)
        labels:
          severity: none
        annotations:
          summary: "Всегда активен. Пропал - значит, цепочка алертов сдохла"

vector(1) возвращает единицу всегда, безусловно. Алерт горит постоянно и уходит в Alertmanager, оттуда - на внешний сервис, который ждёт этот сигнал каждые N минут. Не дождался - пишет вам. Так проверяется вся цепочка целиком: Prometheus считает, Alertmanager маршрутизирует, канал доставки работает. Отвалилось любое звено - вы об этом узнаете.

Для Uptime Kuma есть аккуратный трюк, до которого не сразу додумываешься. Заводите бесплатный аккаунт на healthchecks.io, берёте оттуда ping-URL и добавляете его в Kuma как обычный HTTP-монитор. Для Kuma это рядовая проверка, она будет дёргать адрес каждую минуту, а для healthchecks каждое такое дёрганье и есть сигнал «я жива». Умерла Kuma целиком - пинги прекратились, healthchecks пишет вам. Бесплатного тарифа под такое хватает с запасом.

Не хочется зависеть от чужого сервиса - второй вариант: поднять Kuma в двух локациях и настроить их следить друг за другом крест-накрест. Слегка параноидально, зато всё своё.

Отдельно про канал доставки, потому что это тоже точка отказа. Уведомления должны уходить через инфраструктуру, которая от вашей не зависит - и Telegram тут неожиданно хорош именно этим. Его серверы не ваши, они не лягут вместе с вашим ДЦ. А вот почта со своего же VPS - плохая идея по той же причине, по которой плох локальный мониторинг: упадёт вместе со всем остальным. Плюс письмо с вашего IP может тихо уехать в спам, и вы даже не узнаете (про репутацию IP - есть статья(Ещё не вышла на момент написания)).


Как не оглохнуть от алертов

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

Явление называется alert fatigue, и убивает оно мониторинг вернее, чем любая техническая поломка. Приходит двадцать уведомлений в день, девятнадцать из них - ерунда, вы привыкаете игнорировать - и пропускаете двадцатое, настоящее.

Правило ночного дежурства. Перед тем как завести алерт, спросите себя: если он придёт в три ночи, я встану? Не встану - значит, это не алерт, а запись в дашборд. Пусть себе рисуется графиком, будильник трогать не должен.

Алертить на симптомы, а не на причины. Загрузка процессора 95% сама по себе ничего не значит - может, там видео кодируется, так и должно быть. А вот «сайт отвечает дольше трёх секунд» - симптом, который чувствует пользователь. Хорошее уведомление отвечает на вопрос «кому-то сейчас плохо?», а не «изменилась ли какая-то цифра?».

Обязательный for. Поле, без которого правила Prometheus превращаются в спам-машину:

- alert: InstanceDown
  expr: up == 0
  for: 3m
  labels:
    severity: critical
  annotations:
    summary: "{{ $labels.instance }} не отвечает больше трёх минут"

Без for: 3m вы получите уведомление на каждую секундную сетевую икоту. С ним - только когда проблема продержалась достаточно, чтобы быть настоящей. В Kuma то же самое настраивается полем retries: количество неудачных попыток подряд, после которых она поднимает тревогу. Ставьте минимум 2-3, дефолт слишком нервный.

Группировка. Лёг гипервизор, отвалились восемь серверов - вы должны получить одно сообщение, а не восемь. За это отвечает Alertmanager:

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

group_wait тут особенно полезен: подождать полминуты, вдруг сейчас приедут ещё - и отправить всё одним пакетом.

Минимальный набор того, на что реально стоит алертить, из моего опыта:

  • up == 0 дольше трёх минут;
  • место кончится в ближайшие сутки (тот самый predict_linear);
  • сертификат протухает через семь дней;
  • сервис отвечает дольше N секунд стабильно, а не разово;
  • упал systemd-юнит: node_systemd_unit_state{state="failed"} == 1.

Пять пунктов. Хочется больше - сначала поживите с этими пятью месяц.


Что в итоге брать

Uptime KumaPrometheus и Grafana
На какой вопрос отвечаетработает или нетпочему оно так себя ведёт
Откуда смотритснаружи, как пользовательизнутри, через агента
Время до первого результатаминут десятьвечер, если раньше не собирали
Память на мониторилке~300 МБ2 ГБ по-хорошему
Нужен агент на целевом серверенетда, node_exporter
Что с историейистория аптайма и времени откликавсе метрики за месяцы, с графиками
Прогнозынетесть, predict_linear и компания
Уведомления91 канал из коробки, мышкойAlertmanager или алертинг Grafana, конфигами
Публичная страница статусаестьнет
Сколько компонентов держатьодин контейнерчетыре и больше

Как я бы решал:

Один-два сервера, личные проекты, боты, сайт-визитка. Uptime Kuma, и не выдумывайте. Отдельная дешёвая VPS, docker compose, Telegram-бот, шесть проверок. Полчаса работы, и закрыто почти всё, ради чего мониторинг вообще заводят.

Что-то, за что платят деньги. Ставьте оба. Kuma отвечает на «лежит ли» и будит ночью, Prometheus копит историю и отвечает на «почему». Живут на одной мониторилке и друг другу не мешают, ресурсов хватит на самом скромном тарифе с двумя гигабайтами.

Только Prometheus, без Kuma - вариант рабочий, blackbox_exporter закрывает внешние проверки. Но настраивается это заметно дольше, а сертификаты и страница статуса потребуют отдельной возни. Если вы не собираете стек ради самого стека, экономить один контейнер особого смысла нет.

Только Kuma, без метрик - тоже нормально, и это, пожалуй, самый частый честный выбор. Просто отдавайте себе отчёт: в момент разбора аварии у вас не будет данных, чтобы понять, что произошло. Будет только время начала и конца.


Частые ошибки

  • Мониторинг на том же сервере. Главная и самая массовая. Прикрывает ровно от тех проблем, которые вы и так заметите.
  • node_exporter на 0.0.0.0 без файрвола. Триста тысяч машин в Shodan лежат готовым списком, по которому кто-то регулярно проходится.
  • Веб-морда мониторинга наружу. В ней лежит карта всей инфраструктуры: адреса, порты, имена сервисов, время отклика. Прячьте за туннель или хотя бы за нормальную авторизацию.
  • Проверка только по ICMP. Ping говорит, что сетевой стек хоста отвечает. Про то, жив ли ваш сервис, он не говорит ничего: сайт может лежать при идеальном пинге. И наоборот - хостер может резать ICMP как класс, и вы получите ложную тревогу на ровном месте. Проверяйте то, чем пользуются люди: HTTP, порт, ключевое слово на странице.
  • Нет for и нет retries. Уведомление на каждое моргание сети - прямая дорога к тому, чтобы через неделю всё замьютить.
  • Алерты без дохлого сторожа. Тишина в канале уведомлений двусмысленна: то ли всё хорошо, то ли мониторинг сдох. Разница принципиальная.
  • Забыли про ретеншен. Prometheus по умолчанию хранит 15 дней. Люди месяцами живут в уверенности, что у них есть годовая история, а потом идут смотреть прошлый квартал и обнаруживают пустоту.
  • Дашборд вместо алертов. Сорок красивых панелей, на которые никто не смотрит, потому что смотреть в них надо специально. Уведомление приходит само, дашборд - нет. Дашборды нужны для разбора, а не для обнаружения.

Где это поднимать

Мониторилке нужны две вещи, и мощность не входит ни в одну из них: стоять отдельно от того, за чем она следит, и быть доступной. Один процессор, гигабайт памяти, десять гигабайт диска - и Uptime Kuma с полусотней проверок будет скучать. Под Prometheus с историей возьмите два гигабайта.

Из этого следует приятное: отдельная машина под мониторинг обходится в стоимость чашки кофе в месяц, а закрывает сценарий, который иначе не закрывается никак. Мне для такого хватает самого младшего тарифа на serv.host (промокод promo22382) - главное брать локацию, отличную от той, где стоит основной сервер, иначе весь смысл разъезда теряется. Пара минут на выбор дата-центра сейчас против «почему я узнал об аварии от пользователя» потом.

Порядок действий на свежей мониторилке:

  1. Поднять WireGuard между мониторингом и целями (нужен только для Prometheus, Kuma обойдётся).
  2. Запустить docker compose с Uptime Kuma, повесить порт на localhost.
  3. Завести бота в BotFather, вкрутить токен в уведомления.
  4. Добавить проверки: HTTP по домену, ключевое слово, TCP на важные порты, срок сертификата.
  5. Настроить retries хотя бы 3, чтобы не будило на каждый чих.
  6. Прикрутить push-монитор к ночному бэкапу.
  7. Проверить, что оно вообще работает: погасите тестовый сервис и дождитесь уведомления. Мониторинг, который ни разу не срабатывал, - это мониторинг с неизвестным статусом.

Последний пункт пропускают почти все. А без него у вас не мониторинг, а вера в мониторинг: вроде всё настроено, но сработает ли - никто не проверял.


Короткий итог

  • Мониторинг на той же машине не мониторинг. Он умирает вместе с тем, за чем следит, и молчит ровно тогда, когда должен кричать.
  • «Отдельно» - это шкала, а не да/нет: другая нода лучше того же сервера, другой ДЦ лучше другой ноды, другой хостер лучше всего.
  • Kuma и Prometheus не конкуренты. Первая отвечает «живо ли оно», второй - «почему оно так себя ведёт». Вопросы разные, инструменты разные.
  • Uptime Kuma ставится за десять минут, ест триста мегабайт, ходит по тем портам, что и так открыты, и закрывает большинство бытовых сценариев.
  • Prometheus с Grafana дают историю и прогноз (predict_linear предупреждает, что место кончится к утру, а не сообщает, что оно кончилось), но это конструктор на вечер и два гигабайта памяти.
  • node_exporter наружу не выставлять. Он без пароля отдаёт карту системы, и таких машин в Shodan больше трёхсот тысяч. Туннель, --web.listen-address, файрвол.
  • Дохлый сторож обязателен. Без него молчание в канале уведомлений означает либо «всё хорошо», либо «мониторинг умер», и вы не отличите одно от другого.
  • Пять алертов, на которые вы реально встанете ночью, полезнее сорока, которые вы через неделю замьютите.

Смысл мониторинга не в графиках. Он в том, чтобы узнавать о своих проблемах раньше, чем о них узнают ваши пользователи. Всё остальное детали.


Вообще я микроразработчик, со мной можно связаться как угодно, я открыт ко всему

Сторонний мой проект: Zapret2UI.


Источники