Ваш мониторинг съедает VPS: сколько ресурсов на самом деле нужны Prometheus и Grafana
Система мониторинга конкурирует за те же ресурсы, состояние которых должна отслеживать. Prometheus держит активные ряды в памяти, пишет WAL и регулярно уплотняет блоки TSDB. Grafana создаёт всплески запросов при обновлении дашбордов, а неудачные правила превращают Alertmanager в источник повторяющихся уведомлений. Если сервер выбран только по числу целей, нехватка RAM или дисковых операций обнаруживается уже после запуска. Надёжнее заранее оценить число временных рядов, скорость приёма образцов, срок хранения и профиль запросов. Эти параметры дают основу для выбора CPU, памяти и NVMe, а затем уточняются нагрузочным тестом и наблюдением за самим стеком.
Почему VPS – рабочий вариант под Prometheus и Grafana
Отдельный VPS-сервер подходит небольшим и средним командам, которым нужен контроль над retention, сетевым доступом и версиями компонентов без обслуживания физического узла. По сравнению с managed-сервисом команда сама отвечает за обновления, резервные копии и доступность. Managed-сервис удобнее, если команда не готова обновлять стек и реагировать на сбои самого мониторинга. Выделенный физический сервер становится оправданным при миллионах активных рядов, тяжёлых запросах или требованиях к предсказуемым IOPS, которые конкретный тариф VPS не подтверждает.
Стек лучше отделить от приложений: перегруженный сервис не должен вытеснять Prometheus из памяти вместе с данными о сбое. Но VPS в том же дата-центре или аккаунте не увидит отказ всей площадки. Добавьте независимую проверку из другой сети и внешний контроль получения периодического heartbeat-сигнала. Shared vCPU и общий дисковый контур тоже могут искажать картину, поэтому отслеживайте CPU steal, задержку диска и время выполнения правил.
Resource overhead: сколько реально потребляет стек
Число целей само по себе мало что говорит о нагрузке. Для ориентиров ниже предполагается по 500 активных рядов на цель, scrape каждые 15 секунд, обычные системные дашборды и отсутствие рендеринга изображений. Это около 1,7 тыс., 6,7 тыс. и 33 тыс. образцов в секунду. Диапазоны нужны для первого запуска, после которого ресурсы сверяют с prometheus_tsdb_head_series, скоростью приёма образцов, RSS процессов и длительностью запросов.
Prometheus
50 целей / 25 тыс. рядов: 1–2 vCPU, 2–4 ГБ RAM
200 целей / 100 тыс. рядов: 2–4 vCPU, 4–8 ГБ RAM
1000 целей / 500 тыс. рядов: 4–8 vCPU, 12–24 ГБ RAM
Grafana
50 целей / 25 тыс. рядов: 2 vCPU, 2–4 ГБ RAM
200 целей / 100 тыс. рядов: 2 vCPU, 2–4 ГБ RAM
1000 целей / 500 тыс. рядов: 2–4 vCPU, 4–8 ГБ RAM
Alertmanager
50 целей / 25 тыс. рядов: 0,1–0,3 ГБ RAM, доля vCPU
200 целей / 100 тыс. рядов: 0,2–0,5 ГБ RAM, до 1 vCPU
1000 целей / 500 тыс. рядов: 0,5–1 ГБ RAM, 1–2 vCPU
node_exporter
50 целей / 25 тыс. рядов: обычно десятки МБ на каждой цели; нагрузка зависит от включённых коллекторов
200 целей / 100 тыс. рядов: обычно десятки МБ на каждой цели; расход не относится к центральному VPS
1000 целей / 500 тыс. рядов: обычно десятки МБ на каждой цели; необходимо контролировать длительность scrape
Основную нагрузку от роста числа целей принимает Prometheus. Grafana рассчитывают по числу пользователей, панелей и правил, Alertmanager – по числу активных алертов, групп и получателей.
Prometheus: TSDB, retention и IOPS
По оценке разработчиков Prometheus, постоянные блоки TSDB занимают в среднем 1–2 байта на образец. При 33 тыс. образцов в секунду это около 2,9–5,8 ГБ в сутки, или 86–174 ГБ за 30 дней. WAL, chunks_head и временное место для compaction требуют дополнительной ёмкости. Практический план должен оставлять не менее 20–30% свободного пространства и ограничивать хранение одновременно по времени и размеру.
Уменьшение scrape_interval с 15 до 5 секунд утраивает скорость приёма при прежнем наборе рядов. Ещё опаснее рост кардинальности меток, то есть числа уникальных значений: user_id, UUID и необработанный URL порождают отдельный ряд на каждое из них. Сначала исключайте ненужные метрики и метки, затем увеличивайте интервал там, где минутная детализация достаточна.
remote_write отправляет образцы во внешнее долговременное хранилище, но увеличивает расход RAM, CPU и сети. В документации Prometheus отмечено, что пользователи сообщают примерно о 25% дополнительной памяти, хотя результат зависит от частоты появления и исчезновения рядов, а также очередей. Следите за отставанием и числом ожидающих образцов. Федерация решает другую задачу: верхний Prometheus забирает выбранные, обычно агрегированные ряды с нижестоящих серверов. Она не заменяет резервирование и долговременное хранилище.
Grafana и Alertmanager: лёгкие, но со своими нюансами
Для запуска Grafana достаточно 512 МБ RAM и одного ядра. Для небольшого развёртывания руководство рекомендует 2 ядра и 2–4 ГБ RAM. Расход зависит от числа пользователей, панелей, правил и частоты обновления. Широкие диапазоны, короткий auto-refresh и панели с тяжёлым PromQL нагружают прежде всего источник данных. Recording rules сокращают повторные вычисления. Сервис рендеринга изображений лучше выносить отдельно, поскольку браузерные процессы потребляют значительно больше памяти, чем обычный интерфейс.
Alertmanager хранит активные алерты, silences и журнал отправок. Расход обычно невелик, пока не растут число событий, маршрутов и получателей. Каталог данных должен быть постоянным, иначе после перезапуска пропадут silences и состояние дедупликации. node_exporter работает на наблюдаемой машине, а не на центральном узле. Его порт открывайте только для адресов сборщика.
Подбор конфигурации VPS под задачи мониторинга
В таблице сохранён тот же профиль: 500 рядов на цель, интервал 15 секунд, 30 дней локального хранения. NVMe указан с запасом для WAL, compaction и рабочих запросов. Если Grafana одновременно используют десятки пользователей или в Prometheus выполняются длинные ad hoc запросы, выбирайте верхнюю границу RAM и CPU.
До 50 целей
vCPU: 2
RAM: 4–8 ГБ
NVMe: 80–120 ГБ
Профиль: 15–30 дней хранения, простые дашборды
Около 200 целей
vCPU: 4
RAM: 8–16 ГБ
NVMe: 160–250 ГБ
Профиль: 30 дней хранения, recording rules, умеренный remote_write
Около 1000 целей
vCPU: 8
RAM: 24–32 ГБ
NVMe: 400–600 ГБ
Профиль: 30 дней хранения, разделение scrape-групп, план горизонтального роста
Высокая доступность
vCPU: от 4 на каждый узел
RAM: от 8 ГБ на каждый узел
NVMe: рассчитывается отдельно для каждого узла
Две реплики Prometheus с одинаковыми целями и дедупликация во внешнем хранилище или слое запросов
Проверяйте не только маркировку NVMe, но и лимиты IOPS, задержку записи и поведение диска во время compaction. RAM нужна активным рядам и запросам, поэтому увеличение retention влияет на диск сильнее, чем на память. Для сети посчитайте входящий поток scrape и исходящий remote_write, затем проверьте квоту трафика и доступность приватной сети.
Держите 30–40% запаса на рост кардинальности, обновление компонентов и временные очереди. Если Prometheus устойчиво приближается к лимиту RAM или во время compaction растёт задержка дисковых операций, простого увеличения диска недостаточно. Разделите сбор по площадкам, вынесите долговременное хранение или добавьте второй сервер до того, как одиночный узел станет точкой отказа.
Установка и базовая настройка стека
Разворачивая мониторинг на VPS через Docker Compose, закрепляйте проверенные версии образов и храните конфигурацию в Git. Ниже показан минимальный compose-файл с закреплёнными версиями образов. Перед развёртыванием сверьте их с текущими стабильными релизами. Административные интерфейсы привязаны к localhost: публикуйте Grafana через reverse proxy с TLS или открывайте её только из доверенной сети.
services:
prometheus:
image: prom/prometheus:v3.13.2
restart: unless-stopped
volumes:
- ./prometheus:/etc/prometheus:ro
- prometheus_data:/prometheus
ports: ["127.0.0.1:9090:9090"]
grafana:
image: grafana/grafana:13.1.1
restart: unless-stopped
volumes: ["grafana_data:/var/lib/grafana"]
ports: ["127.0.0.1:3000:3000"]
alertmanager:
image: prom/alertmanager:v0.33.1
restart: unless-stopped
volumes:
- ./alertmanager:/etc/alertmanager:ro
- alertmanager_data:/alertmanager
ports: ["127.0.0.1:9093:9093"]
volumes:
prometheus_data:
grafana_data:
alertmanager_data:
Выдайте контейнерам доступ только к нужным каталогам. На VPS оставьте доступными SSH и порты обратного прокси. К node_exporter разрешите подключение только с адреса Prometheus. Сохраняйте резервные копии конфигурации, provisioning Grafana и её БД. Копирование работающего каталога TSDB не гарантирует согласованный снимок.
В этом примере Grafana использует встроенную SQLite. Она подходит для тестового или небольшого внутреннего стенда. Для продакшена и нескольких реплик подключите внешнюю PostgreSQL или MySQL.
prometheus.yml и scrape-конфиги
В Prometheus 3.13 retention можно задать в prometheus.yml. Значение 60GB в примере рассчитано на небольшой профиль и том объёмом не менее 80 ГБ. Для другой скорости приёма лимит пересчитывают отдельно. Если одновременно заданы время и размер, Prometheus применит ограничение, которое сработает раньше. WAL и head-блокам всё равно нужно свободное место. metric_relabel_configs выполняется после получения метрик и помогает отбрасывать ненужные ряды до записи в TSDB.
global:
scrape_interval: 15s
evaluation_interval: 30s
external_labels:
environment: production
storage:
tsdb:
retention:
time: 30d
size: 60GB
rule_files: ["/etc/prometheus/rules/*.yml"]
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
scrape_configs:
- job_name: node
static_configs:
- targets: ["10.0.0.11:9100", "10.0.0.12:9100"]
labels:
cluster: core
metric_relabel_configs:
# Не сохраняем метрики временных точек монтирования
- source_labels: [mountpoint]
regex: "/run/.*"
action: drop
Не меняйте интервалы сразу для всех job. Короткий интервал нужен там, где изменения требуется обнаруживать за несколько секунд. Ёмкость диска или срок сертификата можно проверять реже.
Alerting без шума: правила и маршрутизация
Порог без выдержки времени реагирует на каждый короткий провал. Поле for оставляет алерт в состоянии pending, пока условие не выполняется непрерывно. Метки severity, team и service нужны маршрутизации, но не добавляйте в них динамические значения.
groups:
- name: availability
interval: 30s
rules:
- alert: TargetDown
expr: up == 0
for: 5m
labels:
severity: critical
team: platform
annotations:
summary: "Цель {{ $labels.instance }} недоступна более пяти минут"
В Alertmanager настройка маршрутизации начинается с группировки связанных событий. group_wait собирает первые алерты, group_interval задаёт интервал отправки изменений в группе, а repeat_interval ограничивает повтор уже известного уведомления. Inhibition подавляет предупреждение, когда для той же цели сработал критический сигнал.
route:
receiver: default
group_by: [cluster, alertname]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- receiver: oncall
matchers: ['severity="critical"']
inhibit_rules:
- source_matchers: ['severity="critical"']
target_matchers: ['severity="warning"']
equal: [alertname, instance]
receivers:
- name: default
webhook_configs:
- url: http://notification-gateway:8080/warnings
send_resolved: true
- name: oncall
webhook_configs:
- url: http://notification-gateway:8080/critical
send_resolved: true
Перед запуском проверьте Compose, конфигурацию Prometheus, правила и конфигурацию Alertmanager:
docker compose config
docker compose run --rm --entrypoint /bin/promtool prometheus check config /etc/prometheus/prometheus.yml
docker compose run --rm --entrypoint /bin/promtool prometheus check rules /etc/prometheus/rules/availability.yml
docker compose run --rm --entrypoint /bin/amtool alertmanager check-config /etc/alertmanager/alertmanager.yml
Не храните токены в открытом репозитории. После изменения отправьте тестовый алерт и проверьте уведомления о срабатывании и восстановлении, а также отсутствие дублей. Для каждого сигнала укажите действие или ранбук. Без понятной реакции он создаёт шум независимо от порога.
Оптимизация и типовые ошибки
Чаще всего стек перегружают лишние ряды и запросы. Сократите кардинальность и ненужные collectors, увеличьте интервалы для медленных показателей, вынесите повторяющийся PromQL в recording rules. Ограничьте auto-refresh и диапазон ad hoc запросов. Длительную историю храните снаружи, федерацию используйте для выбранных агрегатов.
Проверяйте здоровье стека по короткому списку:
· retention ограничен по времени и размеру, свободно не менее 20–30% диска.
· рост активных рядов и скорости приёма объясним.
· длительность scrape и evaluation укладывается в соответствующий интервал.
· remote_write не копит очередь, отказ приёмника проверен.
· для чувствительных к кратким провалам алертов задано for.
· проверены группировка, inhibition и инструкции по реакции.
· дашборды и правила версионируются, правила проверяются через promtool, изменения проходят ревью.
· собственные метрики Grafana, Alertmanager и Prometheus используются в алертах.
· независимая проверка обнаруживает недоступность VPS, а внешний контроль heartbeat-сигнала – отказ канала уведомлений.
Проверьте настроенный сервер под реальной нагрузкой и по метрикам, а восстановление резервных копий – отдельным тестом.



























