Я держу небольшую инфраструктуру: 5 VPS, MySQL и ClickHouse кластеры. На них работают пет-проекты и небольшие продукты вроде AskAds, VkAdsTool и ClearTranscriptBot. Есть реальные пользователи, которым важна стабильность.

Сервисы редко падают мгновенно. Обычно они сначала деградируют: под нагрузкой процессы начинают вытесняться в swap, RAM Usage постепенно растёт на несколько мегабайт в час, I/O Latency увеличивается до неприличных значений из-за шумного соседа на общем хосте. Но к моменту, когда приходит алерт "сервис недоступен", инцидент уже влияет на пользователей.

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

Что я хочу от мониторинга

От мониторинга мне нужно одно: когда в 3 ночи что-то сломалось, быстро понять, что именно деградировало и с какого момента.

Для этого мне нужны метрики по:

  • CPU по ядрам, отдельно system / user / iowait.
  • Memory pressure, swap-in / swap-out.
  • Диск: throughput, IOPS, длина очереди, ошибки.
  • Сеть: throughput, retransmits, packet drops.
  • Здоровье сервисов: Nginx, Postgres, MySQL, Redis, Docker, systemd-юниты.
  • Алерты: потому что дашборды помогают расследовать проблему, но редко помогают вовремя её заметить.
Алерт Netdata в Telegram: уведомление о превышении порога
Пример алерта Netdata — кликните, чтобы увеличить

Почему именно Netdata

Обычно для таких задач используют Prometheus + Grafana. Но в моей инфраструктуре Netdata оказалась удобнее из-за другого набора компромиссов:

  • Установка одной командой. Достаточно запустить kickstart.sh, и через несколько минут агент уже собирает базовые метрики сервера.
  • Низкое потребление ресурсов. На моих серверах Netdata обычно укладывается в 50–100 МБ RAM и 1–5% CPU.
  • Метрики с разрешением в 1 секунду. При агрегации метрик с интервалом 10–30 секунд короткий 4-секундный спайк легко теряется. С 1-секундным разрешением Netdata такие короткие пики остаются видимыми.
  • Автоматическое обнаружение локальных сервисов. Если Nginx, Postgres, Redis, Docker или systemd находятся на той же машине, где установлен Netdata agent, метрики начинают собираться автоматически после перезапуска агента.
  • Алерты из коробки. Базовые алерты на CPU, RAM, disk, swap, load average и другие типичные проблемы уже настроены. Дальше остаётся адаптировать пороги под свою инфраструктуру.

Три инцидента, которые начинались незаметно

Приведу три ситуации, где обычный healthcheck заметил бы проблему слишком поздно — уже когда она влияет на пользователей. Именно такие деградации метрики Netdata помогают увидеть раньше.

Случай 1. Утечка памяти, которая копилась неделю

Предыстория. В какой-то момент получаю сообщение от клиента, что сервис не работает. Быстро захожу по SSH, не нахожу процесса сервиса, смотрю в journalctl и вижу неприятные OOM Killed. Быстро перезапускаю и иду смотреть в код, чтобы найти проблему.

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

Помогло ли это. Конечно нет! Это наоборот ухудшило ситуацию: я стал меньше следить за uptime сервиса, предполагая, что теперь точно не будет никакой ошибки.

Чем всё закончилось. После очередного падения я нашёл банальную проблему в Python-коде - добавлял данные в массив и никогда его не очищал. Если бы я использовал Netdata, то увидел бы тренд роста памяти задолго до OOM.

Случай 2. Шумный сосед на общем диске

Преамбула. Простой бекенд на VPS начал тормозить в произвольные моменты. Ошибок никаких нет, ни в логах, ни в системных сообщениях.

Что увидел в Netdata. Здесь Netdata помогла почти сразу: disk.iops и disk.await улетели вверх, но моя виртуалка при этом почти ничего не читала и не писала. Значит, проблема была не в моём сервисе, а, скорее всего, в соседней виртуалке на том же shared-хосте, которая забивала общий диск.

Что помогло. Поддержка перенесла мою виртуалку на другой хост, и проблема ушла. А я вернул и нормально настроил I/O-алерты, которые до этого сам же выключил.

Случай 3. Постепенный рост swap usage

С чего всё началось. Один из бекендов начал отдавать случайные 500-е. Health-дашборд показывал рост response time p95, но не объяснял причину. Первый инстинкт был простой: перезапустить сервис и посмотреть, повторится ли. Но это как раз тот случай, когда рестарт замаскировал бы причину.

Что показала Netdata. На графике mem.swapio было видно, что последние 36 часов постепенно увеличивался swap-out. Свободной памяти почти не оставалось. CPU Usage выглядел нормально, но на самом деле процессор часто ждал диск: система тратила время не на полезную работу, а на постоянный обмен страницами памяти со swap.

Где была проблема. В предыдущем обновлении конфига сервиса один из параметров был увеличен в 5 раз, но запаса по памяти на сервере уже не было. Даже небольшие дополнительные аллокации начали уходить в swap. Откатил конфиг и добавил два алерта: на system.ram available_percent < 15 и на mem.swapio out > 1MB/s в течение 5 минут. Теперь такую деградацию видно заранее.

Быстрая установка Netdata без лишней возни

1. Установка агента. Официальный установочный скрипт сам определит дистрибутив и настроит запуск Netdata через systemd.

bash
# Скачиваем скрипт в /tmp/netdata-kickstart.sh
wget -O /tmp/netdata-kickstart.sh https://get.netdata.cloud/kickstart.sh
# Запускаем установку агента
sh /tmp/netdata-kickstart.sh --stable-channel --disable-telemetry

2. Закрытие публичного доступа. По умолчанию дашборд Netdata разворачивается на порту 19999 и доступен без логина и пароля. Если этот порт открыт, метрики сможет посмотреть любой, кто знает адрес сервера. Поэтому Netdata остаётся доступной только локально, а внешний доступ я проксирую через Nginx с basic auth.

/etc/netdata/netdata.conf
[web]
    bind to = 127.0.0.1

Ставим утилиту htpasswd и заводим пользователя (например, stats):

bash
sudo apt install apache2-utils
sudo htpasswd -c /etc/nginx/netdata.htpasswd stats

Добавляем в конфиг Nginx новый location, который проксирует запросы на локальный Netdata и требует basic auth:

/etc/nginx/sites-enabled/your-domain
location /netdata/ {
    proxy_pass http://127.0.0.1:19999/;

    auth_basic "Netdata";
    auth_basic_user_file /etc/nginx/netdata.htpasswd;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

Перезагружаем Nginx, и дашборд становится доступным по https://your-domain/netdata/ за логином и паролем:

bash
sudo systemctl reload nginx

3. Настройка уведомлений в Telegram. Для одного человека Telegram удобнее остальных каналов: алерт прилетает мгновенно, видно прямо на экране, настраивается за пару минут.

Сначала создаём бота: пишем @BotFather, отправляем /newbot, придумываем имя — в ответе будет токен вида 1234567890:AAA.... Свой chat ID берём через @userinfobot: достаточно отправить ему любое сообщение.

Дальше указываем оба значения в конфиге уведомлений:

/etc/netdata/health_alarm_notify.conf
SEND_TELEGRAM="YES"
TELEGRAM_BOT_TOKEN="1234567890:AAA..."
DEFAULT_RECIPIENT_TELEGRAM="123456789"

Отправляем тестовое сообщение, чтобы убедиться, что алерты доходят:

bash
sudo netdatacli reload-health
sudo -u netdata /usr/libexec/netdata/plugins.d/alarm-notify.sh test

4. Убираем лишний шум и нагрузку. Netdata из коробки показывает много метрик, но не все они нужны каждый день. Я советую немного отредактировать конфиги, чтобы уведомления не засирали чатик с алертами.

Например, отключить то, что вам скорее всего не пригодится:

/etc/netdata/netdata.conf
[plugins]
    # Очень прожорливый, нужен только для deep kernel tracing
    ebpf = no
    # Low-level профилирование CPU
    perf = no
    # Читает логи, лишняя нагрузка
    systemd-journal = no

    # Отключайте только если вы не используете OpenTelemetry
    otel = no
    otel-signal-viewer = no
    network-viewer = no

    # Низкоуровневые метрики ядра, почти никогда не нужны
    nfacct = no
    slabinfo = no
    debugfs = no

Как смотреть метрики всех серверов в одном месте

Если у вас несколько VPS, у Netdata есть схема с одним parent-агентом и несколькими child-агентами. Каждый child-агент собирает метрики своего сервера и отправляет их на parent-агент, который хранит эти данные и показывает состояние всей инфраструктуры в одном месте.


                         ┌──────────────────────────┐                      
                         │  vps-01                  │                      
                         │   Netdata parent         │                      
                         │   alerts → Telegram      │                      
                         └──────────▲───────────────┘                      
                                    │                                      
                    ┌───────────────┴────────────────┐                     
                    │                                │                     
                 stream                       collect metrics              
                    │                                │                     
        ┌───────────┼───────────┐          ┌─────────┴─────────┐           
        │           │           │          │                   │           
   ┌────▲────┐      │      ┌────▲────┐ ┌───▼──────────┐ ┌──────▼──────────┐
   │ vps-02  │     ...     │ vps-05  │ │ MySQL        │ │ ClickHouse      │
   │  child  │             │  child  │ │ cluster      │ │ cluster         │
   └─────────┘             └─────────┘ └──────────────┘ └─────────────────┘

На parent-сервере, где уже настроен доступ через Nginx с basic auth, в /etc/netdata/stream.conf настраиваем приём метрик от child-серверов. Для этого можно создать один общий стрим с одним API key или отдельные стримы для каждого child-сервера:

/etc/netdata/stream.conf (parent)
[788df748-08ef-4f6b-be56-78247dec3ac5]
    enabled = yes
    default history = 21600

[9edcf9b2-cb5b-4654-b5c0-78acacbad8cd]
    enabled = yes
    default history = 21600

default history = 21600 - это размер локальной истории для child-метрик на parent-сервере (измеряется в entries: при update every = 1 получается примерно 6 часов). Долговременное хранение метрик на parent-сервере настраивается отдельно в файле /etc/netdata/netdata.conf в секции [db].

Один UUID (и по совместительству API key) можно использовать для нескольких child-агентов, а можно завести отдельный ключ для каждого child-сервера. Второй вариант удобнее, если для разных серверов нужны разные настройки: например, разное время хранения метрик.

На child-сервере нужно добавить настройки стриминга в /etc/netdata/stream.conf (дефолтный шаблон лежит в /usr/lib/netdata/conf.d/stream.conf: его можно скопировать и отредактировать):

/etc/netdata/stream.conf (child)
[stream]
    enabled = yes
    destination = stats.gistrec.cloud:19999
    api key = 788df748-08ef-4f6b-be56-78247dec3ac5

После рестарта обоих агентов child начинает стримить метрики, и они появляются в дашборде parent. Уведомления я настраиваю только на parent: так все алерты приходят из одного места, а пороги можно править централизованно.

Базовые метрики хоста в Netdata: CPU, память, диск, сеть
Базовые метрики одного из хостов в дашборде parent — кликните, чтобы увеличить

Сбор метрик с внешних сервисов

Parent-сервер может запускать collectors, которые подключаются к внешним managed-сервисам по сети и забирают метрики напрямую. Это отлично работает для MySQL, ClickHouse, Redis и т.д.

Например, для сбора метрик из моего managed-кластера ClickHouse я сделал вот такой конфиг collector’а (указал host, port и учётные данные):

/etc/netdata/go.d/clickhouse.conf
jobs:
  - name: clickhouse_projects
    url: https://projects.clickhouse.gistrec.cloud:8443
    username: ...
    password: ...
Метрики ClickHouse кластера в Netdata
Метрики ClickHouse кластера в Netdata — кликните, чтобы увеличить

Плюс Netdata из коробки умеет собирать метрики не только с внешних сервисов, но и с локальных: MySQL, PostgreSQL, Redis, ClickHouse, MongoDB, RabbitMQ, Elasticsearch, Nginx, HAProxy и десятки других. Метрики и базовые алерты — из коробки, без отдельного exporter-процесса.

Грабли, на которые важно не наступить:

  • Порт 19999 по умолчанию открыт. Все данные доступны без логина и пароля, поэтому порт точно не стоит открывать наружу.
  • Использовать все дефолтные алерты. Netdata из коробки включает много базовых проверок, но не все они одинаково важны для конкретной инфраструктуры. Я отключил сбор лишних метрик (пример в конфиге выше) и подобрал пороги так, чтобы уведомления не были шумными.
  • Реагировать на каждый warning как на инцидент. Варнинг не значит, что что-то сломалось. Но это сигнал, что скоро что-то может сломаться. Поэтому мьютить варнинги всё-таки не стоит.
  • Забить на регулярный просмотр дашбордов. Раз в день полезно открыть дашборд и быстро проверить основные метрики. Раз в неделю — посмотреть историю алертов и подкрутить пороги для всего, где было false-positive срабатывание.

Если у вас есть Linux-сервер, но нет понятного мониторинга, смело начинайте использовать Netdata! Часто уже за первые десять минут становится видно то, что раньше оставалось незаметным.