Tropic Host

Мониторинг серверов и сайтов на VPS: развертывание Uptime Kuma, Prometheus и Grafana в Docker

32 мин чтения
Tropic

Краткий вывод: Размещение стека телеметрии на том же сервере, где функционирует целевая нагрузка — фундаментальный антипаттерн проектирования инфраструктуры (Single Point of Failure). При исчерпании дескрипторов сокетов, шторме OOM Killer или аппаратной изоляции гипервизором локальный агент мониторинга деградирует и погибает синхронно с хостом, лишая команду инженеров сигнала аварии (эффект silent death). Полноценный мониторинг серверов на vps uptime kuma grafana prometheus, развернутый на изолированном инстансе стоимостью $3–$6 в месяц у независимого провайдера, обеспечивает независимый out-of-band контроль сетевой связности, аппаратных метрик и расчет p99 latency без критических единых точек отказа.


Содержание

  1. Аппаратные требования и сайзинг: Зачем выносить мониторинг на отдельный независимый VPS в 2026 году
  2. Сравнение инструментов: Uptime Kuma vs Prometheus + Grafana vs Zabbix vs Datadog
  3. Развертывание Uptime Kuma за 5 минут: запуск в Docker и настройка проверок
  4. Интеграция Uptime Kuma с Telegram: мгновенные алерты дежурным инженерам
  5. Глубокий мониторинг: развертывание стека Prometheus + Grafana в Docker Compose
  6. Установка Node Exporter на целевые серверы и безопасный сбор метрик
  7. Импорт лучших готовых дашбордов в Grafana: визуализация CPU, памяти и дисков
  8. Настройка правил оповещения в Alertmanager: предупреждения до аварии
  9. Часто задаваемые вопросы (FAQ)

Аппаратные требования и сайзинг: Зачем выносить мониторинг на отдельный независимый VPS в 2026 году


Анатомия «тихой смерти»: почему локальный мониторинг бесполезен при авариях

Главное правило эксплуатационной надежности гласит: «Никогда не мониторь сервер с самого этого сервера». Когда продакшн-узел сталкивается с критической деградацией, процессы мониторинга не просто перестают отправлять алерты — они сами становятся катализатором отказа.

Разберем системные сценарии, при которых совмещенный мониторинг гарантированно слепнет:

  1. Каскадный OOM Killer в условиях memory pressure.
    При утечке памяти в основном приложении ядро Linux начинает процедуру принудительного завершения процессов по алгоритму подсчета badness. Prometheus, активно кэширующий TSDB-блоки в RAM, потребляет существенный объем резидентной памяти (RSS). Если для контейнера с БД или приложением не выставлены жесткие лимиты в cgroup v2 (memory.max и memory.high), а для процесса мониторинга не задан защитный приоритет через oom_score_adj (например, -1000), ядро ликвидирует Prometheus за секунды до падения основного сервиса. В результате Alertmanager физически не успевает сериализовать и отправить webhook в сеть.
  2. I/O Starvation и блокировка дисковой подсистемы.
    Всплеск неоптимизированных дисковых операций (тяжелый SELECT, сброс WAL PostgreSQL на NVMe, бесконтрольный рост логов) загоняет очередь диска в 100% утилизацию (%util = 100 в выводе iostat -xz 1). Время ожидания операций (await) подскакивает с штатных 0.2–0.5 мс до 1500–4000 мс. Процессы TSDB (Prometheus chunk writer) переходят в состояние D (uninterruptible sleep). Приостанавливается не только сбор метрик с node_exporter, но и сброс очередей алертинга.
  3. Сетевая изоляция и сетевой стек ядра (Network Partitioning).
    Если канал хоста забит входящим SYN-флудом или провайдер включил blackholing (null-routing) по BGP из-за превышения PPS (packets per second), сетевой стек ядра дропает пакеты еще на уровне кольцевых буферов сетевой карты (NIC ring buffers) до попадания в сокеты tcp. Локальный Uptime Kuma рапортует, что http://localhost:8080 отдает статус 200 OK, в то время как весь внешний мир получает ERR_CONNECTION_TIMED_OUT.
  4. Аппаратные сбои и деградация гипервизора (Steal Time).
    Зависание процессора хост-ноды, сбой модулей ECC-памяти или высокий CPU Steal Time (%st > 35–50% в виртуализации KVM из-за overselling со стороны хостера) приводят к спонтанному kernel panic. В этот момент хост превращается в «черную дыру»: логов нет, метрик нет, уведомлений нет.

Сравнительный анализ архитектур мониторинга

Ниже представлена техническая матрица вариантов реализации наблюдаемости (Observability) инфраструктуры:

Параметр / Сценарий Совмещенный мониторинг (Localhost) Изолированный VPS ($3–$6/мес) Enterprise SaaS (Datadog / New Relic)
Единая точка отказа (SPOF) Критическая: падение хоста убивает мониторинг Отсутствует: мониторинг и целевые ноды разделены физически и сетевым сегментом Отсутствует: инфраструктура провайдера распределена по мульти-AZ
Реакция на Kernel Panic / OOM 0% (полная тишина в каналах связи) 100% (алерт о потере ping/heartbeat через 10–30 сек) 100% (алерт о потере связи с агентом)
Детекция BGP-блэкхолинга и DPI Невозможна (внутри хоста loopback функционирует штатно) Мгновенная детекция по синтетическим внешним TCP/HTTP-пробам Мгновенная детекция внешними синтетическими тестами
Стоимость эксплуатации Условно $0 (тратит ресурсы основного хоста) $36 – $72 в год (минимальный инстанс 1–2 ядра, 2 GB RAM, NVMe) От $180 – $600+ в месяц при расширенном числе хостов и кастомных метрик
Безопасность и суверенитет данных Высокая (данные не покидают хост) Полная (доступ строго через WireGuard/Tailscale overlay-сеть, шифрование в покое) Риск компрометации данных третьими лицами, привязка к вендору (Vendor Lock-in)
MTTD (Mean Time to Detect) $\infty$ (до обращения разъяренного клиента) 15–30 секунд (таймаут TCP SYN / ICMP unreach) 30–60 секунд

Экономика отказа: $4 в месяц против часов простоя

Покупка ультрабюджетного виртуального сервера за $3–$6 в месяц (например, 1 vCPU AMD EPYC, 2 GB RAM, 20 GB NVMe в независимом европейском или локальном дата-центре) окупается при первом же инциденте:

  • Прямые убытки от простоя (Downtime Cost): Для e-commerce проекта средней руки 30 минут необнаруженного ночного простоя при конверсии в корзину означают потерю от нескольких десятков до сотен тысяч рублей прямой выручки.
  • Штрафы SLA и репутация: Отсутствие фиксации деградации p99 latency (когда база данных не упала, но отвечает 8 секунд вместо 80 мс) приводит к массовому оттоку аудитории, который внутренний healthcheck на localhost не фиксирует вовсе.
  • MTTR (Mean Time to Recovery): Внешний стек мониторинга сохраняет исторические метрики последнего вздоха системы (last-gasp metrics). Вы видите точные графики всплеска IOPS, sysctl vm.dirty_bytes или скачка сетевых очередей netstat -s за миллисекунды до краша, что сокращает расследование инцидента с нескольких дней до 10 минут ретроспективного анализа.

Базовый стек внешнего мониторинга: развертывание за 2 минуты

Для внешнего независимого узла достаточно минималистичной конфигурации, объединяющей синтетический мониторинг (Uptime Kuma) и сбор глубоких системных метрик (Prometheus + Grafana).

Файл docker-compose.yml для изолированного сервера мониторинга:

services:
  uptime-kuma:
    image: louislam/uptime-kuma:1.23.16-alpine
    container_name: uptime-kuma
    restart: always
    volumes:
      - ./data/kuma:/app/data
    ports:
      - "127.0.0.1:3001:3001"
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          memory: 512M

  prometheus:
    image: prom/prometheus:v2.51.0
    container_name: prometheus
    restart: always
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=30d'
      - '--web.enable-lifecycle'
    volumes:
      - ./config/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./data/prometheus:/prometheus
    ports:
      - "127.0.0.1:9090:9090"
    deploy:
      resources:
        limits:
          memory: 1024M

  grafana:
    image: grafana/grafana-oss:10.4.0
    container_name: grafana
    restart: always
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=SetSecurePasswordHere678!
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - ./data/grafana:/var/lib/grafana
    ports:
      - "127.0.0.1:3000:3000"
    deploy:
      resources:
        limits:
          memory: 512M

Первичный аудит «соседства» и стабильности арендованного VPS под мониторинг выполняется одной цепочкой команд прямо в терминале:

# Проверка наличия CPU Steal Time (паразитная нагрузка соседей на гипервизоре)
vmstat 1 5 | awk '{print "US:" $13 " SY:" $14 " ID:" $15 " WA:" $16 " ST(Steal):" $17}'

# Проверка параметров ядра для устойчивости сетевого стека мониторинга к TIME_WAIT сокетам
sudo sysctl -w net.ipv4.tcp_fin_timeout=15
sudo sysctl -w net.ipv4.ip_local_port_range="10240 65535"
sudo sysctl -w vm.swappiness=10

Если колонка ST(Steal) регулярно превышает 3–5%, этот VPS непригоден для наблюдаемости: его таймеры искажены гипервизором, что вызовет ложные срабатывания синтетических проб по таймаутам. Надежный мониторинг строится исключительно на базе независимой платформы с чистыми аппаратными ресурсами.

Сравнение инструментов: Uptime Kuma vs Prometheus + Grafana vs Zabbix vs Datadog

Архитектурно грамотный мониторинг серверов на VPS (Uptime Kuma, Grafana, Prometheus) строится на жестком разграничении двух взаимодополняющих подходов: Blackbox (черный ящик) и Whitebox (белый ящик). Попытка закрыть обе парадигмы одним монолитным инструментом на виртуальных мощностях неизбежно приводит либо к перерасходу оперативной памяти, либо к слепым зонам во время инцидентов.

                    ┌─────────────────────────────────────────────────────────┐
                    │               Blackbox (Синтетический контур)            │
                    │   Внешний зонд: DNS RTT, TLS Handshake, HTTP 200/502    │
                    └────────────────────────────┬────────────────────────────┘
                                                 │ WAN Probe
                                                 ▼
┌─────────────────────────────────────────────────────────────────────────────────────────────┐
│ VPS Target Node (KVM / Hypervisor Slice)                                                    │
│                                                                                             │
│  [ Ingress (Nginx / Envoy) ] ──> [ Application Container ]                                  │
│                 │                             │                                             │
│                 ▼                             ▼                                             │
│       /proc/net/tcp, somaxconn      cgroups v2: memory.max, oom_kill                        │
│                 ▲                             ▲                                             │
│                 └──────────────┬──────────────┘                                             │
│                                │                                                            │
│                    ┌───────────┴──────────┐                                                 │
│                    │ node_exporter / Agent│                                                 │
│                    └───────────┬──────────┘                                                 │
│                                │ Internal Scrape (:9100)                                    │
└────────────────────────────────┼────────────────────────────────────────────────────────────┘
                                 │
                    ┌────────────┴────────────────────────────┐
                    │               Whitebox (Телеметрия ядра)│
                    │   Prometheus TSDB: IOPS, %st, p99, RAM  │
                    └─────────────────────────────────────────┘

Blackbox vs Whitebox: разделение зон ответственности

  • Blackbox (Synthetic Monitoring): Проверка сервиса глазами внешнего клиента через сетевой периметр (WAN). Эмулирует реальный трафик: валидность TLS-сертификата (срок истечения X.509, renegotiation), DNS latency, TCP SYN-ACK handshake, HTTP-коды ответов и полезная нагрузка (JSON payload match). Blackbox детектирует факт деградации даже тогда, когда внутренняя ОС зависла, сеть гипервизора изолирована null-route, либо упал ingress-контроллер с переполненным сокетом net.core.somaxconn.
  • Whitebox (Внутренняя телеметрия): Сбор аппаратных и системных счетчиков изнутри экземпляра ОС (/proc/stat, /proc/vmstat, /sys/fs/cgroup). Показывает причину деградации: насыщение очередей диска (avgqu-sz), задержка p99 на запись в NVMe, сброс грязных страниц (vm.dirty_ratio), утечки дескрипторов файлов (fs.file-nr), срабатывание cgroups v2 OOM Killer и процессорное голодание из-за оверселлинга хостера (%st — CPU Steal Time).

Архитектурный разбор платформ

1. Uptime Kuma: легковесный Blackbox-эталон

Автономный движок синтетического мониторинга на Node.js с локальной базой SQLite (или MariaDB). * Специфика: Идеален для размещения на копеечной изолированной VPS (1 vCPU, 512 МБ – 1 ГБ RAM) вне основного инфраструктурного контура. Выполняет периодические опросы по протоколам HTTP(s), TCP, Ping, DNS, Steam Game Server, Docker Container status. Поддерживает push-мониторинг (Heartbeat/Cron). * Ограничения: Полное отсутствие функционала time-series телеметрии хоста. Uptime Kuma не покажет рост iowait, исчерпание RAM или сетевые коллизии на интерфейсе eth0.

2. Prometheus + Grafana: стандарт Whitebox-метрик и TSDB

Классический стек для сбора структурированных временных рядов (Time Series Data). * Специфика: Prometheus работает по модели Pull, опрашивая легковесный агент node_exporter (написанный на Go, потребляющий всего 15–30 МБ RAM). Хранилище TSDB с блочным сжатием (Gorilla compression) сохраняет сотни тысяч метрик. Grafana берет на себя рендеринг дашбордов и управление алертами. * Ограничения: Сам сервер Prometheus требователен к памяти. При частых интервалах сбора (scrape interval $\le 5$s) и высоком объеме серий (cardinality) Prometheus требует от 2 до 4 ГБ RAM только под буферы WAL (Write-Ahead Log) и компакцию чанков. Для микро-VPS с 1 ГБ RAM необходима строгая оптимизация флагов сборщика мусора и удержание retention period в рамках 7–15 дней.

3. Zabbix: энтерпрайз-монолит с гибридными агентами

Традиционная система распределенного мониторинга с сервером на C/PHP и реляционным бэкендом (PostgreSQL + TimescaleDB или MySQL). * Специфика: Агент zabbix-agent2 (на Go) минимально нагружает целевую ноду (от 15 МБ RAM) и поддерживает как Push (активные проверки), так и Pull. Отлично подходит для разнородного железа, сетевого оборудования (SNMPv3), IPMI и крупных парков виртуальных машин. * Ограничения: Катастрофический оверхед серверной части на единичных VPS. Поддержка СУБД, веб-интерфейса и демона Zabbix Server требует отдельной виртуальной машины минимум с 4–8 ГБ RAM и тонкого тюнинга shared_buffers и work_mem в PostgreSQL.

4. Datadog: полнофункциональный SaaS за высокий бюджет

Проприетарная облачная observability-платформа с унифицированным сбором APM-трейсов, логов и метрик ядра через eBPF. * Специфика: Нулевые трудозатраты на развертывание и обслуживание серверного кластера TSDB. Дает готовые дашборды, машинное обучение для аномалий и автоматический аудит безопасности. * Ограничения: datadog-agent тяжеловесен — он включает в себя встроенные runtime Python и Go, стабильно забирая от 350 до 700 МБ RAM на каждой отслеживаемой VPS, что губительно для бюджетных тарифов. Финансовая модель уничтожает рентабельность: фиксированная ставка от $15–$23 за ноду в месяц плюс драконовские тарифы за Custom Metrics и Ingested Logs.


Сравнительная матрица характеристик

Критерий Uptime Kuma Prometheus + Grafana Zabbix 7.x Datadog (SaaS)
Основной фокус Synthetic / Blackbox Metrics / Whitebox / APM Infrastructure / Whitebox Full-stack Observability
Потребление RAM (Server) 120 – 250 МБ 1.5 – 4+ ГБ (TSDB WAL) 2.5 – 6+ ГБ (+ RDBMS) 0 МБ (Managed SaaS)
Потребление RAM (Target Agent) Агент не требуется 15 – 30 МБ (node_exporter) 18 – 40 МБ (zabbix-agent2) 350 – 750 МБ (datadog-agent)
Сетевая архитектура Pull (ICMP/TCP/HTTP) Pull (HTTP /metrics) Hybrid (Active/Passive) Push (HTTPS/gRPC в облако)
Хранилище данных SQLite / MariaDB Встроенная TSDB (PromQL) PostgreSQL / TimescaleDB Проприетарное Cloud TSDB
Гранулярность (Resolution) 20 – 60 сек 1 – 15 сек 10 – 60 сек 10 – 15 сек
Сложность развертывания Минимальная (Docker run) Средняя (Compose/Alertmanager) Высокая (СУБД, шаблоны) Минимальная (One-line shell)
Стоимость на 10 VPS ($/мес) $0 (Self-hosted на $4 VPS) $0 (Self-hosted на $10 VPS) $0 (Self-hosted на $15 VPS) ~$180–$350+ (Лицензии + трафик)

Практическая конфигурация комбинированного стека (Docker Compose)

Оптимальный сетап для продакшена без раздувания бюджета — вынос легковесного сервера Uptime Kuma и связки Prometheus/Grafana на отдельную дешевую мастер-ноду.

# /opt/monitoring/docker-compose.yml (Master VPS)
services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: unless-stopped
    volumes:
      - ./data/kuma:/app/data
    ports:
      - "3001:3001"
    deploy:
      resources:
        limits:
          memory: 300M

  prometheus:
    image: prom/prometheus:v2.51.0
    container_name: prometheus
    restart: unless-stopped
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=15d'
      - '--storage.tsdb.retention.size=10GB'
      - '--storage.tsdb.min-block-duration=2h'
      - '--storage.tsdb.max-block-duration=2h'
    volumes:
      - ./config/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./data/prometheus:/prometheus
    ports:
      - "127.0.0.1:9090:9090"
    deploy:
      resources:
        limits:
          memory: 1500M

  grafana:
    image: grafana/grafana:10.4.0
    container_name: grafana
    restart: unless-stopped
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=StrictSecretTokenHex99
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - ./data/grafana:/var/lib/grafana
    ports:
      - "127.0.0.1:3000:3000"
    deploy:
      resources:
        limits:
          memory: 512M

На целевых подконтрольных VPS запускается только бинарник node_exporter, защищенный через iptables / nftables для доступа исключительно с IP-адреса мастера мониторинга:

# Установка и изоляция node_exporter на целевом узле
curl -sSLO https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar -xvf node_exporter-1.7.0.linux-amd64.tar.gz
sudo mv node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/

# Разрешаем сбор метрик только с доверенного IP мастер-ноды (198.51.100.25)
sudo iptables -A INPUT -p tcp -s 198.51.100.25 --dport 9100 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 9100 -j DROP

Конфигурация таргетов сбора в /opt/monitoring/config/prometheus.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'vps_nodes'
    static_configs:
      - targets: ['203.0.113.10:9100', '203.0.113.11:9100']
        labels:
          environment: 'production'

Диагностика узких мест VPS через PromQL

Связка Prometheus и node_exporter позволяет вовремя поймать критические инфраструктурные патологии гипервизора хостера, которые невозможно выявить стандартными Blackbox-пробами:

  • Детекция CPU Steal Time (оверселлинг физического CPU соседями по ноде): promql 100 * sum(rate(node_cpu_seconds_total{mode="steal"}[5m])) BY (instance) / sum(rate(node_cpu_seconds_total[5m])) BY (instance) > 5 Порог: Если метрика держится выше 5% дольше 15 минут — виртуальный процессор VPS принудительно замораживается шедулером KVM. Пора эвакуировать сервис или менять тариф.
  • Насыщение дисковой подсистемы (iowait): promql 100 * sum(rate(node_cpu_seconds_total{mode="iowait"}[5m])) BY (instance) / sum(rate(node_cpu_seconds_total[5m])) BY (instance) > 15 Свидетельствует об исчерпании лимитов дисковых IOPS хостера или медленном сетевом блочном хранилище (Ceph/NFS).
  • Давление по памяти и активация OOM: promql rate(node_vmstat_oom_kill[5m]) > 0 Фиксирует завершение процессов ядром Linux до того, как они уронят критически важные демоны баз данных или веб-сервера.

Развертывание Uptime Kuma за 5 минут: запуск в Docker и настройка проверок

Когда выстраивается отказоустойчивый мониторинг серверов на VPS, Uptime Kuma, Grafana, Prometheus закрывают разные уровни наблюдаемости. В то время как связка Prometheus и node_exporter собирает whitebox-метрики ядра (CPU Steal Time %st, насыщение дисковых очередей, IOPS, троттлинг cgroups и потребление памяти), Uptime Kuma берет на себя роль независимого blackbox-пробера. Он симулирует реальные пользовательские запросы снаружи периметра, фиксирует деградацию latency p99 и оповещает об инцидентах за секунды до того, как мониторинг инфраструктуры зафиксирует перегрузку хоста.

Архитектурно Uptime Kuma представляет собой однопоточный Node.js-сервис со встроенной СУБД SQLite. При развертывании на бюджетных VPS (1 vCPU, 512–1024 МБ RAM) ключевая инженерная задача — исключить блокировки дискового ввода-вывода (IO wait) и деградацию сетевого стека контейнера при интенсивных проверках сотен эндпоинтов.

Подготовка ядра и запуск контейнера

Перед запуском Docker-контейнера необходимо настроить сетевой стек хоста. По умолчанию непривилегированные контейнеры лишены права открывать сырые сокеты (SOCK_RAW), что приводит к ошибке EPERM при попытке выполнения ICMP-пинга. Чтобы Uptime Kuma могла отправлять echo-запросы без повышения привилегий до --privileged, разрешаем диапазон групп для ICMP-сокетов и увеличиваем лимиты файловых дескрипторов для предотвращения исчерпания сокетов (EMFILE):

# Разрешение непривилегированного ICMP для всех групп пользователей
sudo sysctl -w net.ipv4.ping_group_range="0 2147483647"

# Увеличение пула доступных эфемерных портов для высокочастотных TCP/HTTP проб
sudo sysctl -w net.ipv4.ip_local_port_range="1024 65535"

# Сохранение параметров в sysctl.d для персистентности после перезагрузки
echo -e "net.ipv4.ping_group_range=0 2147483647\nnet.ipv4.ip_local_port_range=1024 65535" | sudo tee /etc/sysctl.d/99-uptime-kuma.conf

Для минимизации оверхеда изоляции и упрощения сетевой маршрутизации контейнер монтируется к выделенному локальному каталогу. База данных SQLite требует режима WAL (Write-Ahead Logging), поэтому файловая система хоста должна поддерживать блокировки POSIX (fcntl):

mkdir -p /opt/uptime-kuma/data
chown -R 1000:1000 /opt/uptime-kuma/data

docker run -d \
  --name uptime-kuma \
  --restart=always \
  -p 3001:3001 \
  -v /opt/uptime-kuma/data:/app/data \
  --memory=512m \
  --memory-swap=512m \
  --cpus="0.75" \
  --cap-add=NET_RAW \
  --security-opt no-new-privileges:true \
  louislam/uptime-kuma:1

Если развертывание стандартизировано через оркестрацию, эквивалентный production-манифест docker-compose.yml фиксирует жесткие лимиты cgroups v2, предотвращая вытеснение самого демона мониторинга при дефиците оперативной памяти (OOM Killer):

services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: always
    ports:
      - "127.0.0.1:3001:3001"
    volumes:
      - /opt/uptime-kuma/data:/app/data
    cap_add:
      - NET_RAW
    deploy:
      resources:
        limits:
          cpus: '0.75'
          memory: 512M
        reservations:
          memory: 128M
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3001/ || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3

После старта веб-интерфейс доступен на порту 3001. Рекомендуется сразу проксировать трафик через Nginx или Caddy с обязательной поддержкой WebSocket (Upgrade $http_upgrade, Connection "upgrade"), так как дашборд синхронизирует состояние проверок через Socket.IO в реальном времени.

Конфигурация типов проверок (L3–L7)

Архитектура проверок разделяется на сетевые уровни модели OSI для точной локализации аварий:

1. HTTP(s) с валидацией полезной нагрузки

Простой проверки HTTP-статуса 200 OK недостаточно: CDN-прокси (Cloudflare, Qrator) могут отдавать статус 200 на кастомные страницы заглушек при недоступности апстрима. * В настройках монитора укажите метод GET или HEAD (для снижения исходящего трафика). * Поле Accepted Status Codes: строго 200-299. * Активируйте Keyword Search (проверка ключевого слова в теле ответа). Задайте точный фрагмент HTML или JSON-ключа (например, {"status":"operational"}), чтобы исключить ложноположительные аптаймы. * Установите Request Timeout в пределах 2000–3000 ms. Накопление медленных соединений при таймаутах по умолчанию в 48 секунд исчерпывает пул дескрипторов событий epoll внутри Node.js.

2. Автоматический контроль срока действия SSL/TLS-сертификатов

Uptime Kuma автоматически инициирует TLS-рукопожатие при выборе протокола https:// и считывает поле NotAfter структуры X.509. * В секции Certificate Expiry активируйте триггер предупреждения за 14 и 7 дней до истечения срока действия. * Настройте проверку цепочки доверия (Chain of Trust) и флага SNI (Server Name Indication). Это исключает аварии, вызванные сбоем автообновления через Certbot, ошибками проверки DNS-01/HTTP-01 ACME-челленджей или некорректным промежуточным сертификатом (Intermediate CA).

3. TCP Port и ICMP Ping

Сетевой мониторинг базовой доступности: * TCP Port: проверяет доступность сокетов баз данных (PostgreSQL 5432, Redis 6379, ClickHouse 9000) без прохождения авторизации на прикладном уровне. Монитор отправляет пакет SYN и ждет SYN-ACK. Если сервер сбрасывает соединение (RST) или пакеты уходят в blackhole из-за правил iptables/nftables, статус немедленно переводится в Down. * Ping (ICMP): измеряет RTT (Round Trip Time). Фиксируйте отклонения jitter и деградацию сетевого маршрута. Нормальный интервал проверки: 60 секунд с 3 повторными попытками (Retries) перед переходом в аварийное состояние, чтобы сгладить микроберсты потери пакетов на транзитных магистралях провайдера.

4. DNS-записи

Монитор типа DNS валидирует корректность резолвинга записей (A, AAAA, MX, CNAME, TXT) через внешние публичные резолверы (1.1.1.1, 8.8.8.8), игнорируя локальный /etc/resolv.conf. Это позволяет мгновенно обнаружить ошибки сбоя DNSSEC, истечения срока аренды домена или отравления кэша (DNS cache poisoning).

Push-мониторы: настройка Dead Man's Switch для бэкапов

Push-мониторинг реализует обратную телеметрию (Heartbeat): Uptime Kuma не опрашивает сервер сама, а пассивно ожидает входящий HTTP-запрос от фонового процесса. Если в течение заданного интервала плюс допустимый буфер ожидания (Grace Period) запрос не поступает, монитор генерирует критический алерт.

Это ключевой паттерн для контроля ночного резервного копирования (pg_dump, restic, borgmatic) и системных скриптов, выполняемых через cron или systemd-timers. Стандартный планировщик задач не оповещает о зависании задачи, исчерпании дискового пространства или аварийном завершении по сигналу SIGKILL (OOM).

Создайте в панели монитор с типом Push, скопируйте сформированный токен и внедрите вызов в производственный bash-скрипт резервного копирования:

#!/usr/bin/env bash
set -Eeuo pipefail

PUSH_URL="https://kuma.example.internal/api/push/aBcDeFgHiJ?status=up&msg=OK"
ERR_URL="https://kuma.example.internal/api/push/aBcDeFgHiJ?status=down"
START_TIME=$(date +%s%N)

# Ловушка ошибок: при любом ненулевом коде возврата отправляется статус DOWN
trap 'curl -fsS --retry 3 --max-time 10 "${ERR_URL}&msg=BackupFailed_Line_${LINENO}" || true' ERR

# Тело рабочей операции: дамп базы данных и сжатие
pg_dump -U postgres -h 127.0.0.1 -Fc production_db > /backup/prod_$(date +%F).dump

# Вычисление времени выполнения операции в миллисекундах
END_TIME=$(date +%s%N)
DURATION=$(( (END_TIME - START_TIME) / 1000000 ))

# Отправка успешного heartbeat с передачей метрики времени выполнения
curl -fsS --retry 5 --max-time 15 "${PUSH_URL}&ping=${DURATION}" > /dev/null

Ключ --max-time 15 защищает скрипт бэкапа от вечного зависания в состоянии SYN_SENT, если сам сервер мониторинга окажется временно изолирован сетевым сбоем. В настройках самого Push-монитора укажите Heartbeat Interval равным периодичности выполнения задачи (например, 86400 секунд для ежедневного расписания) и Grace Period в пределах 3600 секунд, чтобы компенсировать плавающие задержки длительности архивации при росте объема данных.

Интеграция Uptime Kuma с Telegram: мгновенные алерты дежурным инженерам

В архитектуре, где развернут комплексный мониторинг серверов на VPS (Uptime Kuma, Grafana, Prometheus), задачи строго разделены по слоям ответственности. Prometheus через node_exporter собирает внутреннюю белую телеметрию хоста — процессорный steal time (%st), сбросы страниц под давлением cgroups v2, насыщение дисковой подсистемы по IOPS и задержки latency p99. Задача Uptime Kuma принципиально иная: выступать внешним синтетическим blackbox-сенсором, фиксирующим доступность сетевых портов, валидность TLS-сертификатов и сквозной статус HTTP/TCP эндпоинтов. При возникновении сетевой изоляции или падении демона дежурный инженер должен получить пуш-уведомление в Telegram быстрее, чем сработает тяжелый стек Alertmanager, с задержкой доставки менее 800 мс.


Шаг 1. Регистрация бота и извлечение Chat ID через Telegram Bot API

Интеграция опирается на стандартный протокол Telegram Bot API через исходящий HTTPS-вебхук к https://api.telegram.org. Для исключения человеческого фактора подготовка транспорта выполняется строго через консоль.

  1. Создание сервисного аккаунта в @BotFather:
  2. Отправьте команду /newbot, задайте системное имя бота (например, infra_vps_kuma_bot) и уникальный юзернейм с суффиксом _bot.
  3. Сохраните полученный HTTP API Token вида 7123456789:AAFn_example_token_xK89QWzM.
  4. Для предотвращения спама и несанкционированного изменения конфигураций выполните /setjoingroups -> Disable (если бот используется только для прямых сообщений) или добавьте созданного бота администратором в закрытый дежурный супергрупповой чат с правами на отправку сообщений.
  5. Определение chat_id и message_thread_id (для форум-топиков): Отправьте боту любое тестовое сообщение в целевом чате (например, /start или ping), затем выполните парсинг эндпоинта getUpdates через curl и утилиту jq:
BOT_TOKEN="7123456789:AAFn_example_token_xK89QWzM"

# Получение сырого JSON ответа и фильтрация идентификаторов чата
curl -s -X GET "https://api.telegram.org/bot${BOT_TOKEN}/getUpdates" | jq -r '
  .result[-1] | 
  "Chat ID: " + (.message.chat.id // .my_chat_member.chat.id | tostring) + 
  " | Type: " + (.message.chat.type // "unknown") + 
  " | Thread ID: " + (.message.message_thread_id // "none" | tostring)'

Идентификаторы групповых суперчатов Telegram всегда начинаются с префикса -100 (например, -1001987654321). Если инцидентный канал разделен на темы (Telegram Topics), зафиксируйте message_thread_id, чтобы алерты дежурной смены падали в изолированный поток #incidents, не смешиваясь с общим чатом разработки.


Шаг 2. Конфигурация провайдера уведомлений в Uptime Kuma

Подключение транспорта осуществляется в веб-интерфейсе Uptime Kuma: Settings $\rightarrow$ Notifications $\rightarrow$ Setup Notification.

  • Notification Type: Telegram
  • Friendly Name: Telegram Prod Ops Channel
  • Bot Token: Вставьте полученный токен от @BotFather.
  • Chat ID: Целевой ID (например, -1001987654321 или 45829104).
  • Message Thread ID: ID топика (оставьте пустым, если чат без разделения на темы).
  • Auto get Chat ID: Отключите. Автоматическое определение часто сбоит при наличии нескольких сообщений в очереди getUpdates.
  • Send Silently: Снимите чекбокс. Алерты о деградации инфраструктуры обязаны пробивать системный режим «Не беспокоить» у дежурного инженера.
  • Default enabled: Включите, чтобы все вновь создаваемые мониторы автоматически привязывались к этому каналу оповещения.

Нажмите Test. Uptime Kuma отправит тестовый POST-запрос с полезной нагрузкой:

# Имитация запроса Uptime Kuma на стороне ядра Linux
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "-1001987654321",
    "text": "🔴 [Testing] Test Notification from Uptime Kuma",
    "parse_mode": "Markdown"
  }'

Шаг 3. Настройка шаблонов алертинга: Service DOWN, UP и Certificate Expiry

Uptime Kuma генерирует уведомления по событиям смены внутреннего конечного автомата (FSM). Для промышленной эксплуатации необходимо настроить поведение мониторов так, чтобы исключить усталость от алертов (alert fatigue) и ложные срабатывания при микроразрывах BGP-сессий.

1. Алерты о недоступности (Service DOWN) и порог пинга

В настройках каждого монитора задаются параметры устойчивости: * Heartbeat Interval: 30 секунд (оптимальный баланс между сетевым оверхедом и скоростью реакции). * Retries: 3 попытки. * Retry Interval: 10 секунд.

Система не генерирует алерт в Telegram при одиночной потере пакета. Статус DOWN и уведомление в чат активируются только тогда, когда $3$ последовательных проверки завершаются таймаутом ($3 \times 10\text{с} = 30\text{с}$ подтвержденного отказа). В телеграм-уведомлении автоматически выводятся: * Имя сервиса и целевой URL/IP. * Код ошибки протокола: HTTP 502 Bad Gateway, ECONNREFUSED или ETIMEDOUT. * Метрика задержки: значение пинга на момент сбоя (например, Ping: 2150 ms, свидетельствующее о деградации канала или насыщении очередей netdev_max_backlog).

2. Автоматическое уведомление о восстановлении (Service UP)

Как только хост возвращает статус 200 OK или успешный ответ на ICMP echo-request, Uptime Kuma немедленно отправляет парный зеленый статус с указанием точного времени простоя:

✅ [Service UP] API Gateway VPS-01
URL: https://api.prod.internal/v1/health
Downtime: 2m 45s
Ping: 14 ms

Это позволяет дежурному инженеру мгновенно понять, был ли инцидент кратковременным флаппингом или системным сбоем, требующим ручного расследования в логах journalctl и дампах Prometheus.

3. Мониторинг срока действия SSL/TLS-сертификатов (Certificate Expiry)

Для мониторов типов HTTP(s) включите опцию Certificate Expiry Notification: * Expiry Notification Thresholds: Задайте контрольные точки: 21, 14, 7, 3, 1 дней. * Uptime Kuma через TLS-хендшейк извлекает поле NotAfter X.509-сертификата. При пересечении установленного порога бот отправляет warning-алерт:

⚠️ [Cert Expire] api.prod.internal
Days remaining: 7
Issuer: Let's Encrypt Authority X3
Action required: Verify certbot systemd timer and renewal hooks.

Шаг 4. Устранение инфраструктурных узких мест на VPS

При одновременном падении стойки или перезагрузке upstream-шлюза сотни мониторов переходят в статус DOWN синхронно. Без оптимизации стека контейнеров это приводит к локальным сбоям доставки алертов:

  1. Лимиты Telegram API (HTTP 429 Too Many Requests): Telegram Bot API ограничивает отправку сообщений до 30 пакетов в секунду глобально и не более 1 сообщения в секунду в рамках одного чата. При массовом отказе Uptime Kuma выстраивает внутреннюю очередь. Не устанавливайте интервал повторов (Resend Notification) меньше 0 (Disabled), иначе очередь сообщений заблокирует отправку свежих алертов по другим инцидентам.
  2. Сетевой тюнинг ядра Linux для Docker-контейнера: Если Uptime Kuma развернут в изолированной bridge-сети Docker, исчерпание пула открытых сокетов при массовых параллельных проверках может заблокировать исходящие вызовы к api.telegram.org. Добавьте в /etc/sysctl.d/99-monitoring.conf хоста:
# Расширение диапазона эфемерных портов
net.ipv4.ip_local_port_range = 10240 65535

# Ускорение перевода сокетов из состояния TIME_WAIT
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15

# Защита от переполнения очереди соединений
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096

Примените изменения: sysctl --system.

  1. Отказоустойчивость DNS внутри контейнера: В манифесте docker-compose.yml явно укажите резервные DNS-резолверы, чтобы сбой локального демона systemd-resolved на VPS не парализовал отправку алертов:
services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: always
    volumes:
      - ./kuma-data:/app/data
    ports:
      - "127.0.0.1:3001:3001"
    dns:
      - 1.1.1.1
      - 8.8.8.8
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '0.75'

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

Глубокий мониторинг: развертывание стека Prometheus + Grafana в Docker Compose

Полноценный мониторинг серверов на VPS (Uptime Kuma, Grafana, Prometheus) требует жесткого разделения ответственности: если Uptime Kuma закрывает внешний синтетический Blackbox-контроль доступности эндпоинтов по ICMP/HTTP(S), то связка Prometheus и Grafana отвечает за Whitebox-интроспекцию операционной системы и контейнеров. Prometheus реализует pull-модель сбора числовых временных рядов (time-series), опрашивая экспортеры через HTTP с заданным интервалом, сжимает данные алгоритмом Gorilla (XOR для float64 и delta-of-delta для меток времени) и сохраняет их во встроенную TSDB.

На бюджетных виртуальных машинах с разделяемыми ядрами (где значение %st — CPU Steal Time — может скакать от 3% до 15% при оверселлинге гипервизора) неконтролируемый рост кардинальности метрик и фоновое уплотнение блоков (compaction) в TSDB гарантированно вызывают всплески IOPS, рост iowait (%wa) и деградацию дисковой подсистемы. Чтобы предотвратить срабатывание ядра Linux OOM Killer и избежать деградации latency p99 при выполнении PromQL-запросов, развертывание стека выполняется с жесткими ограничениями cgroups, тюнингом sysctl и предварительным расчетом дискового пространства.

1. Расчет емкости TSDB и системные требования к хосту

Объем дискового хранилища под базу метрик вычисляется по формуле:

$$\text{DiskSpace} = \text{RetentionSeconds} \times \frac{\text{Series}}{\text{ScrapeInterval}} \times \text{BytesPerSample} \times 1.25$$

Где: * BytesPerSample в Prometheus в среднем составляет 1.5–2 байта благодаря дельта-компрессии. * Множитель 1.25 резервирует 25% емкости под Write-Ahead Log (WAL), блоки индексации (index) и накладные расходы при компактификации 2-часовых блоков TSDB.

При интервале опроса scrape_interval: 15s, хранении метрик в течение 30 дней (retention.time = 30d) и пуле из 1 500 активных тайм-серий со стандартного node_exporter: $$\text{DiskSpace} = 2\,592\,000 \times \left(\frac{1500}{15}\right) \times 2 \times 1.25 \approx 648\,000\,000 \text{ байт } (\approx 618 \text{ МБ})$$

Однако при подключении мониторинга контейнеров через cAdvisor кардинальность возрастает до 10 000–15 000 серий, что потребует уже от 4 до 6 ГБ чистого NVMe-пространства только под метрики.

Перед развертыванием контейнеров скорректируйте лимиты открытых дескрипторов и виртуальной памяти ядра хоста, предотвратив ошибки too many open files во время сброса сегментов WAL из оперативной памяти на диск:

# Увеличение лимита дескрипторов и областей отображения памяти (mmap)
sudo sysctl -w fs.file-max=2097152
sudo sysctl -w vm.max_map_count=262144

# Персистентная фиксация параметров в sysctl.d
cat <<EOF | sudo tee /etc/sysctl.d/99-monitoring.conf
fs.file-max = 2097152
vm.max_map_count = 262144
EOF

2. Подготовка файловой структуры и прав доступа (POSIX UID/GID)

Контейнеры Prometheus и Grafana по соображениям безопасности запускаются от непривилегированных системных пользователей: Prometheus использует UID 65534 (nobody), а Grafana — UID 472. Несоответствие прав на томах хоста приведет к падению контейнеров с ошибкой open /prometheus/queries.active: permission denied.

Создайте изолированное дерево каталогов и выставьте владельцев:

sudo mkdir -p /opt/monitoring/{prometheus/data,grafana/data}
sudo chown -R 65534:65534 /opt/monitoring/prometheus
sudo chown -R 472:472 /opt/monitoring/grafana/data
sudo chmod -R 755 /opt/monitoring

3. Конфигурация Prometheus (prometheus.yml)

Создайте конфигурационный файл /opt/monitoring/prometheus/prometheus.yml. В блоке global жестко задаются интервалы сбора и тайм-ауты. Время ожидания ответа экспортера (scrape_timeout) обязательно должно быть меньше scrape_interval, иначе при сетевых задержках или зависании целевого процесса опрос начнет наслаиваться, вызывая лавинообразный рост потребления памяти.

global:
  scrape_interval: 15s     # Дефолтный интервал опроса всех таргетов
  evaluation_interval: 15s # Частота расчета правил алертинга и recording rules
  scrape_timeout: 10s      # Тайм-аут ожидания HTTP-ответа от метрик-экспортера

# Правила фильтрации и обогащения метрик
scrape_configs:
  - job_name: "prometheus"
    metrics_path: /metrics
    static_configs:
      - targets: ["localhost:9090"]

  - job_name: "node-exporter"
    scrape_interval: 15s
    static_configs:
      - targets: ["node-exporter:9100"]

  - job_name: "uptime-kuma"
    scrape_interval: 30s
    metrics_path: /metrics
    static_configs:
      - targets: ["uptime-kuma:3001"]

  - job_name: "cadvisor"
    scrape_interval: 15s
    static_configs:
      - targets: ["cadvisor:8080"]

4. Production-ready docker-compose.yml

Файл /opt/monitoring/docker-compose.yml описывает запуск сервисов в изолированной bridge-сети с включением сжатия WAL (--storage.tsdb.wal-compression), ограничения размера хранилища и явных лимитов cgroups (CPU/Memory) во избежание дестабилизации соседних сервисов на сервере.

services:
  prometheus:
    image: prom/prometheus:v2.51.0
    container_name: prometheus
    restart: unless-stopped
    user: "65534:65534"
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.path=/prometheus"
      - "--storage.tsdb.retention.time=30d"
      - "--storage.tsdb.retention.size=15GB"
      - "--storage.tsdb.wal-compression"
      - "--web.enable-lifecycle"
      - "--web.console.libraries=/usr/share/prometheus/console_libraries"
      - "--web.console.templates=/usr/share/prometheus/consoles"
    volumes:
      - /opt/monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - /opt/monitoring/prometheus/data:/prometheus:rw
    networks:
      - monitoring-net
    ports:
      - "127.0.0.1:9090:9090"
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 1024M
        reservations:
          memory: 512M

  grafana:
    image: grafana/grafana-oss:10.4.0
    container_name: grafana
    restart: unless-stopped
    user: "472:472"
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=GenerateStrongPasswordHex32
      - GF_USERS_ALLOW_SIGN_UP=false
      - GF_SERVER_HTTP_PORT=3000
      - GF_SERVER_DOMAIN=localhost
      - GF_LOG_MODE=console
      - GF_METRICS_ENABLED=false
    volumes:
      - /opt/monitoring/grafana/data:/var/lib/grafana:rw
    networks:
      - monitoring-net
    ports:
      - "127.0.0.1:3000:3000"
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: 512M
        reservations:
          memory: 256M

networks:
  monitoring-net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16

Ключевые флаги запуска Prometheus: * --storage.tsdb.wal-compression: снижает объем операций записи на диск для WAL почти на 50%, разгружая дисковую очередь (await по данным iostat). * --storage.tsdb.retention.size=15GB: страхует сервер от переполнения накопителя при резком росте количества метрик; при достижении лимита самые старые блоки удаляются независимо от --storage.tsdb.retention.time. * --web.enable-lifecycle: активирует эндпоинт /-/reload. Это позволяет применять изменения в prometheus.yml на лету отправкой POST-запроса без рестарта контейнера и потери накопленного кеша в оперативной памяти. * Привязка портов строго к 127.0.0.1: закрывает административные интерфейсы Prometheus и Grafana от сканирования внешним трафиком, направляя работу через реверс-прокси Nginx/Caddy с TLS-терминацией.

5. Инициализация и верификация контура

Запустите стек из директории /opt/monitoring:

cd /opt/monitoring
docker compose up -d

Проверьте корректность старта процессов и статус аллокации памяти контейнеров:

docker compose ps
docker stats --no-stream prometheus grafana

Проверьте, что TSDB успешно инициализировала базу и сегменты WAL без ошибок прав доступа:

docker logs prometheus 2>&1 | grep -E "Server is ready to receive web requests|WAL segment"

При обновлении конфигурации таргетов (например, при добавлении новых серверов или перенастройке экспортера Uptime Kuma) примените изменения горячим перезапуском:

curl -X POST http://127.0.0.1:9090/-/reload

Команда возвращает HTTP 200, инициируя внутренний системный вызов ядра на перечитывание дескриптора конфигурации без сброса тайм-серий из оперативной памяти в блочные сегменты на диске. Теперь стек полностью готов к добавлению DataSource в Grafana по внутреннему DNS-имени Docker: http://prometheus:9090.

Установка Node Exporter на целевые серверы и безопасный сбор метрик

Полноценный мониторинг серверов на VPS Uptime Kuma Grafana Prometheus разделяет зоны ответственности: Uptime Kuma проверяет внешнюю доступность сервисов (L7/L4 проверки по протоколам HTTP/TCP), в то время как связка Prometheus и Node Exporter отвечает за глубокую интроспекцию ядра Linux, дисковой подсистемы и cgroups на целевых хостах.

Сбор метрик на уровне хоста опирается на node_exporter — легковесный демон на Go, который транслирует псевдофайловые системы /proc и /sys в формат тайм-серий Prometheus. При развертывании агента на удаленных производственных нодах критически важно решить две инженерные задачи: минимизировать оверхед на CPU/память и исключить компрометацию периметра через открытые порты сбора данных.


Анатомия угрозы: почему порт 9100 запрещено открывать в открытый интернет

Node Exporter по умолчанию слушает TCP-порт 9100 на адресе 0.0.0.0 без встроенной аутентификации и шифрования. Публикация этого порта наружу без жесткой сетевой фильтрации превращает сервер в открытую книгу для внешних сканеров (Shodan, Censys, masscan):

  1. Разведка архитектуры и векторов атак (Reconnaissance):
    Эндпоинт /metrics отдает полный профиль системы: точные версии ядра (node_uname_info), используемые сетевые интерфейсы, локальные IP-адреса, топологию подсетей, смонтированные файловые системы и имена внутренних блочных устройств (/dev/vda, /dev/nvme0n1). Активация коллектора systemd раскрывает список всех запущенных сервисов, что позволяет злоумышленнику подобрать целевые эксплойты под конкретные версии демонов.
  2. Утечка паттернов нагрузки и таймингов:
    По метрикам node_cpu_seconds_total, node_memory_MemAvailable_bytes и системным вызовам в node_disk_* внешний наблюдатель видит пики бизнес-логики, расписания ночных бэкапов и фазы деградации дисков. Это позволяет синхронизировать DDoS-атаку с моментом максимальной утилизации памяти или пика IOPS.
  3. Обнаружение оверселлинга и троттлинга:
    Метрика %st (node_cpu_seconds_total{mode="steal"}) демонстрирует задержки планировщика гипервизора, когда хост делит ядра с «шумными соседями». В открытом доступе эти данные раскрывают внутреннее состояние виртуализации провайдера.
  4. Отказ в обслуживании через парсинг метрик (Scrape Exhaustion DoS):
    Каждый HTTP-запрос к /metrics инициирует чтение десятков файлов в /proc и /sys. Интенсивный внешний скрейпинг порта 9100 параллельными потоками приводит к шквалу контекстных переключений ядра (context switches), скачку load average и блокировкам дисковых очередей.

Развертывание Node Exporter через systemd

Запуск Node Exporter внутри Docker-контейнера создает лишний слой изоляции: демону все равно требуются флаги --net=host, --pid=host, а также монтирование /proc и /sys с флагами rslave,ro. Нативная установка бинарника под управлением systemd исключает накладные расходы и позволяет изолировать сервис через стандартные директивы безопасности Linux.

Создайте системного пользователя без права входа в шелл и домашней директории:

sudo useradd --no-create-home --shell /bin/false node_exporter

Загрузите актуальный бинарный релиз (архитектура amd64) и установите его в /usr/local/bin:

VERSION="1.8.2"
wget https://github.com/prometheus/node_exporter/releases/download/v${VERSION}/node_exporter-${VERSION}.linux-amd64.tar.gz
tar -xvf node_exporter-${VERSION}.linux-amd64.tar.gz
sudo cp node_exporter-${VERSION}.linux-amd64/node_exporter /usr/local/bin/
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter
rm -rf node_exporter-${VERSION}.linux-amd64*

Создайте systemd unit-файл с включением отслеживания Pressure Stall Information (PSI), метрик дисковой задержки и системных демонов:

# /etc/systemd/system/node_exporter.service
[Unit]
Description=Prometheus Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter \
  --web.listen-address=127.0.0.1:9100 \
  --collector.systemd \
  --collector.processes \
  --collector.pressure \
  --collector.diskstats \
  --no-collector.infiniband \
  --no-collector.ipvs

Restart=always
RestartSec=3s

# Песочница безопасности systemd
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
MemoryDenyWriteExecute=true

[Install]
WantedBy=multi-user.target

Параметр --collector.pressure активирует сбор метрик PSI (/proc/pressure/{cpu,memory,io}), позволяя зафиксировать деградацию latency p99 и нехватку ресурсов задолго до срабатывания OOM Killer. Привязка --web.listen-address=127.0.0.1:9100 жестко замыкает прослушивание сокета на loopback-интерфейсе, полностью отсекая внешний трафик.

Запустите сервис и включите его автозагрузку:

sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
sudo systemctl status node_exporter --no-pager

Сетевая изоляция: UFW против оверлейных сетей (WireGuard / Tailscale)

Для доставки телеметрии с целевого хоста в центральный Prometheus применяются две архитектурные модели: фильтрация на уровне файрвола хоста либо инкапсуляция сбора данных в приватный VPN-туннель.

Вариант 1. Белый список IP-адресов через UFW / iptables

Если сервер мониторинга Prometheus имеет статический публичный IPv4-адрес, трафик разрешается точечно.

Если Node Exporter привязан к публичному интерфейсу (0.0.0.0:9100), настройте UFW так, чтобы скрейпинг был доступен только доверенному IP:

# Разрешить трафик к порту 9100 исключительно с IP сервера Prometheus
sudo ufw allow proto tcp from 198.51.100.24 to any port 9100 comment "Prometheus-Scraper-Production"

# Проверка активных правил в таблице фильтрации
sudo ufw status verbose
Критическое предупреждение по Docker и iptables:
Если на целевом хосте запущен Docker daemon, он по умолчанию модифицирует цепочку PREROUTING в обход правил UFW. Проброс портов через директиву ports: - "9100:9100" в docker-compose.yml откроет порт всему миру, игнорируя блокировки ufw deny. При контейнеризации публикуйте порт исключительно на петлевой адрес: 127.0.0.1:9100:9100 либо на IP туннельного интерфейса.

Вариант 2. Приватный оверлей через WireGuard / Tailscale (Zero Trust)

Наиболее защищенный production-стандарт — изоляция метрик внутри сквозного шифрованного туннеля (ChaCha20-Poly1305). Порт 9100 не открывается в брандмауэре вовсе, а трафик ходит по приватной адресации (10.x.x.x или 100.x.x.x).

  1. Привязка к интерфейсу WireGuard:
    Если хост объединен с Prometheus через интерфейс wg0 с адресом 10.100.0.15, в конфигурации unit-файла node_exporter.service указывается: ini ExecStart=/usr/local/bin/node_exporter --web.listen-address=10.100.0.15:9100 ...
  2. Привязка к интерфейсу Tailscale:
    При использовании Tailscale сокет связывается с адресом интерфейса tailscale0 (диапазон CGNAT 100.64.0.0/10): bash TAILSCALE_IP=$(tailscale ip -4) # Переопределение ExecStart в /etc/systemd/system/node_exporter.service.d/override.conf: # ExecStart=/usr/local/bin/node_exporter --web.listen-address=${TAILSCALE_IP}:9100

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


Верификация сбора метрик с сервера Prometheus

После настройки ограничений выполните валидацию сетевого пути и формата отдачи данных непосредственно с сервера, где развернут Prometheus:

# Проверка доступности метрик через curl с замером времени ответа
curl -s -w "\nHTTP Code: %{http_code} | Total time: %{time_total}s\n" \
  http://10.100.0.15:9100/metrics | head -n 20

Проверьте наличие критических аппаратных маркеров:

# Проверка метрик насыщения CPU (CPU Steal Time)
curl -s http://10.100.0.15:9100/metrics | grep 'node_cpu_seconds_total{.*mode="steal"}'

# Проверка задержки дискового ввода-вывода (IO time)
curl -s http://10.100.0.15:9100/metrics | grep 'node_disk_io_time_seconds_total'

# Проверка PSI по памяти (фактор дефицита RAM в миллисекундах)
curl -s http://10.100.0.15:9100/metrics | grep 'node_pressure_memory_waiting_seconds_total'

Если curl возвращает статус 200 OK за время менее 0.05s, а внешние сканеры со стороны интернета получают Connection refused или Timeout при попытке постучаться на публичный IP целевого сервера по порту 9100 — агент готов к добавлению в scrape_configs центрального сервера Prometheus.

Импорт лучших готовых дашбордов в Grafana: визуализация CPU, памяти и дисков

Развертывая мониторинг серверов на vps uptime kuma grafana prometheus, ручная сборка графиков с нуля для базовых аппаратных метрик — неоправданная трата инженерных ресурсов. В экосистеме Prometheus де-факто отраслевым эталоном визуализации хостовых метрик является комьюнити-дашборд Node Exporter Full (Grafana Dashboard ID: 1860). Он агрегирует тысячи точек данных из коллектора node_exporter, маппит системные вызовы ядра Linux и экспортирует комплексные таймсерии с минимальным оверхедом на саму Grafana.

Автоматизация импорта дашборда 1860 без веб-интерфейса

Ручной импорт через GUI (Dashboards → New → Import → ввод ID 1860 → выбор источника данных Prometheus) подходит для разовых тестов. В production-инфраструктуре дашборд должен быть описан декларативно через механизм provisioning. Это гарантирует воспроизводимость при пересоздании контейнеров в Docker Compose.

Для автоматической загрузки свяжите конфигурацию провайдера и предварительно загруженный JSON-шаблон дашборда:

# /etc/grafana/provisioning/dashboards/infrastructure.yaml
apiVersion: 1
providers:
  - name: 'Host Metrics'
    orgId: 1
    folder: 'Infrastructure'
    type: file
    disableDeletion: false
    editable: true
    updateIntervalSeconds: 60
    allowUiUpdates: true
    options:
      path: /var/lib/grafana/dashboards

Скрипт загрузки последней ревизии ID 1860 и подстановки datasource:

#!/usr/bin/env bash
set -euo pipefail

DASHBOARD_DIR="./grafana/dashboards"
mkdir -p "${DASHBOARD_DIR}"

# Загрузка актуального JSON дашборда Node Exporter Full с подстановкой переменной источника Prometheus
curl -sL "https://grafana.com/api/dashboards/1860/revisions/latest/download" | \
  sed 's/${DS_PROMETHEUS}/Prometheus/g' > "${DASHBOARD_DIR}/node-exporter-full.json"

chmod 644 "${DASHBOARD_DIR}/node-exporter-full.json"

После перезапуска контейнера Grafana дашборд развернется автоматически со всеми предустановленными переменными окружения: node, job, disk, interface.


Анализ ключевых панелей и системных метрик

Импортированный дашборд содержит десятки графиков. Для изоляции аппаратных узких мест на виртуализированных узлах критично понимать физику четырех базовых панелей.

1. CPU Steal Time (%st) и обнаружение оверселлинга хостера

На виртуальных серверах (KVM, Xen, Proxmox) процент использования процессора раскладывается ядром в файле /proc/stat на режимы: user, nice, system, idle, iowait, irq, softirq, steal, guest.

Метрика CPU Steal Time (%st) отражает процент времени, в течение которого виртуальный процессор (vCPU) был готов исполнять инструкции процесса в очереди планировщика CFS (Completely Fair Scheduler), но физический гипервизор не выделил физические такты CPU, переключив контекст на виртуальные машины других жильцов ноды («noisy neighbors»).

PromQL-выражение на панели:

sum by (instance) (rate(node_cpu_seconds_total{mode="steal"}[2m])) 
/ 
sum by (instance) (rate(node_cpu_seconds_total[2m])) * 100
  • Норма: 0.0% – 0.5%.
  • Повод для аудита: Регулярные всплески от 3% до 7%. Приводят к деградации latency p99 в веб-серверах (Nginx, Envoy) и таймаутам на уровне TCP-сокетов.
  • Критический уровень: Полка выше 10%. Провайдер жестко оверселлит физические ядра. Приложение замирает без признаков нагрузки внутри самой ОС хоста.

Диагностика с терминала VPS для подтверждения данных метрики:

# Чтение текущего %st по всем ядрам с шагом в 1 секунду
mpstat -P ALL 1 5
# Либо через vmstat (колонка st)
vmstat 1 5

2. Load Average и структуры очередей ядра

Метрика node_load1, node_load5, node_load15 считывается из /proc/loadavg. В отличие от BSD-систем, где Load Average учитывает только процессы в состоянии TASK_RUNNING (состояние R), в ядре Linux туда включаются процессы в состоянии TASK_UNINTERRUPTIBLE (состояние D — ожидание дискового I/O, системные вызовы к файловым системам, блокировки мьютексов в ядре).

Правило сопоставления: * Load Average делится на количество доступных vCPU: node_load1 / count(count(node_cpu_seconds_total) by (cpu)). * Если LA значительно превышает количество ядер, но график CPU Busy показывает менее 20–30%, узкое место гарантированно находится в дисковой подсистеме (высокий %iowait). В этот момент потоки зависают на системных вызовах fsync(), read(), write().

Быстрый поиск заблокированных потоков в D-state:

ps -eo state,pid,ppid,comm | grep -E "^D"

3. Дисковый I/O: задержка (await), насыщение и лимиты NVMe

Стандартные хостинги дешевых VPS заявляют диски NVMe, однако выставляют жесткие лимиты на уровне cgroups гипервизора (IOPS и bandwidth limit). Панели дашборда опираются на счетчики ядра /proc/diskstats.

Ключевые PromQL-запросы на панели Disk Throughput / IOPS / Latency:

  • IOPS (операции чтения/записи в секунду): ```promql rate(node_disk_reads_completed_total{device!~"loop.|dm-."}[1m])
  • rate(node_disk_writes_completed_total{device!~"loop.|dm-."}[1m]) ```
  • Disk Await / Latency (время отклика в миллисекундах): ```promql ( rate(node_disk_read_time_seconds_total{device!~"loop.|dm-."}[1m])
    • rate(node_disk_write_time_seconds_total{device!~"loop.|dm-."}[1m]) ) / ( rate(node_disk_reads_completed_total{device!~"loop.|dm-."}[1m])
    • rate(node_disk_writes_completed_total{device!~"loop.|dm-."}[1m]) ) * 1000 ```

Если показатель Disk Latency на чтении или записи подскакивает выше 15–20 мс на NVMe (норма для NVMe — менее 0.5–1.5 мс), дисковый контроллер хоста исчерпал пул Burst IOPS и сбросил виртуальную машину на базовый throttling (например, до 300–500 IOPS), что приводит к лавинообразному росту очередей транзакций баз данных (PostgreSQL, Redis AOF/RDB).

Детализация параметров очередей через консоль:

# Просмотр утилизации дисков, размера очереди (aqu-sz) и задержки (await)
iostat -x -z 1 5

4. Network I/O и скрытые дропы пакетов

Панель сетевого интерфейса отображает не только ширину канала (rate(node_network_receive_bytes_total[1m]) * 8), но и ошибки со стеком пакетов.

Обращайте внимание на графики Network Drops / Errors: * node_network_receive_drop_total * node_network_transmit_drop_total

Рост drop_total на фоне незаполненного сетевого канала указывает на переполнение буферов сетевой карты (ring buffer) или очереди ядра:

# Проверка переполнения backlog-буфера сетевого стека
cat /proc/net/softnet_stat
# Инспекция ошибок физического/виртуального интерфейса
ethtool -S eth0 2>/dev/null || ip -s link show eth0

При обнаружении дропов без физического исчерпания канала увеличьте максимальный размер очереди обработки сетевых пакетов ядра через sysctl:

# Применение тюнинга сетевых буферов
sysctl -w net.core.netdev_max_backlog=5000
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216

Связка метрик дашборда 1860 позволяет мгновенно локализовать корневую проблему: аппаратный троттлинг провайдера (%st, IOPS await) или неоптимальную конфигурацию операционной системы (память, сетевой стек, планировщик).

Настройка правил оповещения в Alertmanager: предупреждения до аварии

Реактивный мониторинг фиксирует инцидент постфактум, когда сервис уже недоступен, а Nginx отдает клиентам 502 Bad Gateway. Организуя комплексный мониторинг серверов на VPS (Uptime Kuma, Grafana, Prometheus), инженер обязан выстроить предиктивную сигнализацию: алерты должны срабатывать на стадии деградации ресурсов, оставляя дежурному запас времени на реакцию до вмешательства OOM Killer или деградации дисковой подсистемы.

Alertmanager берет на себя агрегацию, дедупликацию, группировку и маршрутизацию алертов, генерируемых сервером Prometheus на базе предикатов PromQL.


1. Архитектура предиктивных метрик: правила Prometheus

Создайте файл правил /etc/prometheus/rules/alerts.yml. В виртуализированных средах (KVM, LXC) при оценке CPU и дисков стандартных пороговых значений недостаточно: необходимо отсекать шум от виртуальных файловых систем и учитывать фактор оверселлинга хоста.

groups:
  - name: node_infrastructure_alerts
    interval: 30s
    rules:
      # Дефицит дискового пространства: статический порог < 15%
      - alert: HostDiskSpaceLow
        expr: |
          (node_filesystem_avail_bytes{fstype!~"tmpfs|fuse.lxcfs|squashfs|overlay", mountpoint="/"})
          / (node_filesystem_size_bytes{fstype!~"tmpfs|fuse.lxcfs|squashfs|overlay", mountpoint="/"}) * 100 < 15
        for: 5m
        labels:
          severity: warning
          tier: infrastructure
        annotations:
          summary: "Критически мало места на корневом разделе (инстанс {{ $labels.instance }})"
          description: "Свободное место на диске {{ $labels.mountpoint }} упало ниже 15%. Текущий остаток: {{ $value | printf \"%.2f\" }}%."

      # Предиктивный алерт: прогнозируемое переполнение диска в течение 6 часов
      - alert: HostDiskFillingFastPredictive
        expr: |
          predict_linear(node_filesystem_free_bytes{fstype!~"tmpfs|squashfs|overlay"}[4h], 6 * 3600) < 0
          and rate(node_filesystem_free_bytes[1h]) < 0
        for: 15m
        labels:
          severity: critical
          tier: infrastructure
        annotations:
          summary: "Диск {{ $labels.mountpoint }} на {{ $labels.instance }} переполнится в течение 6 часов"
          description: "На основе экстраполяции заполнения за последние 4 часа свободное место будет исчерпано менее чем за 6 часов при текущем темпе ввода-вывода."

      # Насыщение CPU > 90% в течение 10 минут с учетом CPU Steal
      - alert: HostCpuExhaustion
        expr: |
          100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
        for: 10m
        labels:
          severity: warning
          tier: infrastructure
        annotations:
          summary: "Высокая утилизация CPU на {{ $labels.instance }}"
          description: "Загрузка процессора превышает 90% на протяжении 10 минут. Текущая средняя утилизация: {{ $value | printf \"%.2f\" }}%."

      # Аномалия гипервизора: паразитная нагрузка CPU Steal Time (%st) > 15%
      - alert: HostCpuStealHigh
        expr: |
          avg by (instance) (rate(node_cpu_seconds_total{mode="steal"}[5m])) * 100 > 15
        for: 5m
        labels:
          severity: critical
          tier: hypervisor
        annotations:
          summary: "Критический CPU Steal Time на VPS {{ $labels.instance }}"
          description: "Соседние виртуалки на физическом узле монополизируют процессорное время (%st > 15%). Требуется перенос или тикет в саппорт хостера."

      # Всплеск HTTP 5xx ошибок бэкенда > 5% от общего объема трафика
      - alert: HttpHigh5xxRate
        expr: |
          (
            sum by (instance, job) (rate(nginx_http_requests_total{status=~"^5.."}[5m]))
            /
            sum by (instance, job) (rate(nginx_http_requests_total[5m]))
          ) * 100 > 5
        for: 2m
        labels:
          severity: critical
          tier: application
        annotations:
          summary: "Высокий уровень 5xx кодов ответа на {{ $labels.instance }}"
          description: "Доля серверных ошибок (500, 502, 503, 504) составляет {{ $value | printf \"%.2f\" }}% за последние 5 минут (порог: > 5%)."

Инженерные нюансы PromQL-запросов:

  • Фильтрация псевдо-ФС: Регулярное выражение fstype!~"tmpfs|fuse.lxcfs|squashfs|overlay" исключает артефакты монтирования слоев Docker и LXC-контейнеров, предотвращая ложные срабатывания по read-only системным путям.
  • Функция predict_linear(): Линейная аппроксимация по методу наименьших квадратов за интервал [4h] позволяет перехватить утечку логов или разрастание временных файлов (/tmp, WAL базы данных) задолго до того, как сработает жесткий барьер в 15%.
  • Анализ %st (CPU Steal): На недорогих VPS перегрузка vCPU часто вызвана не пользовательскими процессами, а троттлингом со стороны планировщика гипервизора KVM (cfs_quota_us / cfs_period_us). Отдельный алерт на mode="steal" локализует вину провайдера до того, как начнется беспричинный дебаг собственного кода.

2. Конфигурация Alertmanager: роутинг, группировка, ингибирование

Alertmanager структурирует оповещения так, чтобы дежурная команда не попадала под шторм сообщений (Alert Fatigue). Конфигурация /etc/alertmanager/alertmanager.yml реализует разделение очередей: предупреждения (warning) поступают в Slack-канал мониторинга, а аварийные сбои (critical) немедленно пушатся в Telegram с включенным звуковым триггером.

global:
  resolve_timeout: 5m
  slack_api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'

route:
  group_by: ['alertname', 'cluster', 'tier']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 3h
  receiver: 'slack-warnings'
  routes:
    # Критические алерты дублируются в Telegram инженерам дежурной смены
    - match:
        severity: critical
      receiver: 'telegram-oncall'
      continue: true

    - match:
        severity: critical
      receiver: 'slack-critical'

    # Низкоприоритетные предупреждения отправляются только в Slack
    - match:
        severity: warning
      receiver: 'slack-warnings'

inhibit_rules:
  # Подавлять предупреждение о дефиците места (warning), если уже стреляет аварийное (critical)
  - source_match:
      alertname: 'HostDiskFillingFastPredictive'
      severity: 'critical'
    target_match:
      alertname: 'HostDiskSpaceLow'
      severity: 'warning'
    equal: ['instance', 'mountpoint']

receivers:
  - name: 'slack-warnings'
    slack_configs:
      - channel: '#alerts-warning'
        send_resolved: true
        title: '{{ if eq .Status "firing" }}:warning:{{ else }}:white_check_mark:{{ end }} [{{ .Status | toUpper }}] {{ .CommonLabels.alertname }}'
        text: >-
          *Инстанс:* `{{ .CommonLabels.instance }}`
          *Степень:* `{{ .CommonLabels.severity }}`
          *Описание:* {{ range .Alerts }}{{ .Annotations.description }}{{ end }}

  - name: 'slack-critical'
    slack_configs:
      - channel: '#alerts-critical'
        send_resolved: true
        color: 'danger'
        title: ':fire: [CRITICAL INCIDENT] {{ .CommonLabels.alertname }}'
        text: >-
          *Инстанс:* `{{ .CommonLabels.instance }}`
          *Сводка:* {{ range .Alerts }}{{ .Annotations.summary }}{{ end }}
          *Детали:* {{ range .Alerts }}{{ .Annotations.description }}{{ end }}

  - name: 'telegram-oncall'
    telegram_configs:
      - bot_token: '1234567890:ABCdefGHIjklMNOpqrSTUvwxYZ_example'
        chat_id: -1001234567890
        send_resolved: true
        parse_mode: 'HTML'
        message: >-
          {{ if eq .Status "firing" }}<b>🚨 [ALARM: {{ .CommonLabels.severity | toUpper }}]</b>{{ else }}<b>✅ [RESOLVED]</b>{{ end }}
          <b>Алерт:</b> {{ .CommonLabels.alertname }}
          <b>Сервер:</b> <code>{{ .CommonLabels.instance }}</code>
          <b>Уровень:</b> <i>{{ .CommonLabels.tier }}</i>

          {{ range .Alerts }}
          <b>Детали:</b> {{ .Annotations.description }}
          <b>Старт:</b> {{ .StartsAt.Format "15:04:05 MSK (02.01)" }}
          {{ end }}

Параметр inhibit_rules критически важен: при лавинообразном росте нагрузки или стремительном заполнении диска инженеру не нужны два дублирующих пуша. Ингибирование глушит менее приоритетный алерт HostDiskSpaceLow при активности таргетированного HostDiskFillingFastPredictive.


3. Валидация синтаксиса и сквозное тестирование пайплайна

Перед перезагрузкой демонов Prometheus и Alertmanager через SIGHUP обязательна верификация AST-дерева конфигов встроенными бинарными утилитами. Ошибка в пробелах YAML приведет к отказу перезапуска всего демона с падением процесса в CrashLoopBackOff.

Выполните валидацию в терминале:

# Валидация синтаксиса и PromQL-выражений в алерт-правилах
promtool check rules /etc/prometheus/rules/alerts.yml

# Проверка конфигурации маршрутизации Alertmanager
amtool check-config /etc/alertmanager/alertmanager.yml

# Применение конфигурации на горячую (без рестарта контейнеров)
curl -X POST http://127.0.0.1:9090/-/reload
curl -X POST http://127.0.0.1:9093/-/reload

Для проверки фактической доставки сообщения в Telegram и Slack без ожидания реального сбоя сымитируйте инъекцию аварийного алерта через Alertmanager API v2 посредством curl:

curl -H "Content-Type: application/json" -d '[
  {
    "labels": {
      "alertname": "SyntheticDiskExhaustionTest",
      "instance": "vps-edge-01.internal",
      "severity": "critical",
      "tier": "infrastructure"
    },
    "annotations": {
      "summary": "Имитация аварии дискового накопителя",
      "description": "Тестовый пуш через API v2 для проверки валидности токена Telegram и вебхука Slack."
    },
    "generatorURL": "http://prometheus.local/test"
  }
]' http://127.0.0.1:9093/api/v2/alerts

Успешное выполнение вернет HTTP-код 200 OK, и через 30 секунд (таймаут group_wait) сгенерированное форматированное оповещение отобразится в Telegram-чате дежурной смены и соответствующем Slack-канале. Это гарантирует бесперебойную работу связки транспортного уровня до наступления реальных инцидентов на боевом сервере.

Часто задаваемые вопросы (FAQ)

Хватит ли самого дешевого VPS с 1 GB RAM под Uptime Kuma?

Да, Uptime Kuma написана на Node.js с легковесной базой SQLite и потребляет всего 100–250 MB RAM, отлично работая на сервере с 1 vCPU и 1 GB RAM.

Сколько места на диске требует Prometheus при хранении метрик?

Prometheus сжимает временные ряды до 1–2 байт на метку. При мониторинге 5–10 серверов с периодом хранения 30 дней база TSDB займет не более 5–10 GB диска NVMe.

Как мониторить доступность сайта из разных стран?

В Uptime Kuma можно подключить удаленные легковесные агенты (Remote Browsers / Push Monitors) на VPS в разных локациях для проверки региональных блокировок.

Можно ли выводить статус-страницу для клиентов компании?

Да, Uptime Kuma включает встроенный конструктор публичных статус-страниц (Status Pages), который можно повесить на отдельный поддомен (например, status.company.com).