MAATRIX GAMES / Блог / Grafana и Prometheus: дашборд для игрового хостинга

Grafana и Prometheus: дашборд для игрового хостинга

MAATRIX GAMES

Панель хостинга обычно показывает CPU и RAM за последние сутки — и всё, дальше история не хранится, а TPS, онлайн игроков и время последнего вайпа туда никто не выведет. Если у вас один сервер и вам хватает беглого взгляда раз в день — городить отдельный мониторинг избыточно. Но если серверов несколько, или вы хотите видеть просадку TPS за месяц назад, а не только текущий момент, — Prometheus и Grafana решают это за пару вечеров настройки, и дальше работают сами.

Зачем собственный мониторинг, если есть панель хостинга

Панель управления хостера honestly делает свою работу — общий график CPU/RAM в реальном времени есть почти у всех, включая MAATRIX GAMES. Но у неё есть предел: она не знает про TPS вашего Minecraft-сервера, не считает онлайн игроков как метрику с историей, не умеет присылать алерт в Discord, когда сервер зафризился на полчаса, и обычно хранит данные ограниченный период — неделю-две, не больше.

Prometheus+Grafana закрывают именно это: любые метрики, которые вы захотите собирать, хранятся столько, сколько вы настроите (месяцы — не проблема), и визуализируются как угодно — от простого графика линии до тепловой карты нагрузки по часам суток. Плюс это бесплатный open-source стек, который одинаково хорошо работает что на одной VPS с одним игровым сервером, что на связке из десятка серверов за одним proxy.

Минус — это лишний процесс на хосте, который сам потребляет RAM и CPU (Prometheus в базовой конфигурации на небольшом числе метрик — 100-200 МБ памяти, Grafana примерно столько же). На тарифе впритык под саму игру это стоит учитывать — либо брать сервис под мониторинг с небольшим запасом ресурсов, либо выносить Prometheus/Grafana на отдельную небольшую машину, которая опрашивает несколько игровых серверов сразу.

Ставим Prometheus и node_exporter

Схема простая: node_exporter — маленькая программа, которая крутится на игровом сервере и отдаёт метрики железа (CPU, RAM, диск, сеть) на порту 9100 в текстовом формате. Prometheus — отдельный сервис, который раз в N секунд опрашивает эти порты и складывает данные в свою базу временных рядов.

Скачиваем node_exporter (Linux, x86_64) и разворачиваем как systemd-сервис — про сам подход systemd для игровых процессов есть отдельная статья про systemd, screen и tmux, тут тот же принцип для служебного процесса:

wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz
tar xvfz node_exporter-1.8.2.linux-amd64.tar.gz
sudo mv node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin/

Юнит-файл /etc/systemd/system/node_exporter.service:

[Unit]
Description=Node Exporter
After=network.target

[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter --collector.textfile.directory=/var/lib/node_exporter/textfile_collector
Restart=always

[Install]
WantedBy=multi-user.target

Флаг --collector.textfile.directory понадобится в следующем разделе — именно через него node_exporter подхватит кастомные игровые метрики. Запускаем:

sudo mkdir -p /var/lib/node_exporter/textfile_collector
sudo useradd -rs /bin/false node_exporter
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter

Сам Prometheus ставится так же — бинарник или Docker-контейнер, конфиг prometheus.yml с адресом node_exporter в блоке scrape:

scrape_configs:
  - job_name: 'game-server'
    scrape_interval: 15s
    static_configs:
      - targets: ['localhost:9100']

Если игровой сервер и Prometheus на разных машинах — вместо localhost укажите реальный IP, и не забудьте открыть порт 9100 в файрволе только для IP машины с Prometheus, а не для всех — метрики железа лучше не светить наружу.

Нужен игровой сервер?

MAATRIX GAMES — 45+ игр, деплой за минуты, DDoS-защита, автобэкапы. Тарифы от 399 ₽/мес.

Создать сервер

Кастомные метрики: онлайн игроков и TPS

Это самое интересное — node_exporter из коробки не знает ничего про TPS или количество игроков, эти метрики нужно генерировать самим через textfile collector: любой скрипт раз в N секунд пишет файл .prom в папку /var/lib/node_exporter/textfile_collector/, а node_exporter сам подхватывает его и отдаёт в общей выдаче.

Для Minecraft (Paper/Spigot) — данные берём через RCON, про сам протокол подробно есть отдельная статья про RCON-подключение и команды. Пример скрипта на Python с библиотекой mcrcon, который дергает /tps и список игроков и пишет метрики:

import re
from mcrcon import MCRcon

with MCRcon("127.0.0.1", "rcon_password", port=25575) as mcr:
    tps_raw = mcr.command("tps")
    players_raw = mcr.command("list")

tps_match = re.findall(r"[\d.]+", tps_raw)
tps_1m = tps_match[0] if tps_match else "0"

online_match = re.search(r"(\d+) of a max", players_raw)
online = online_match.group(1) if online_match else "0"

with open("/var/lib/node_exporter/textfile_collector/mc_metrics.prom.tmp", "w") as f:
    f.write(f"minecraft_tps 1m={tps_1m}\n".replace("1m=", ""))
    f.write(f"minecraft_tps {tps_1m}\n")
    f.write(f"minecraft_players_online {online}\n")

import os
os.replace(
    "/var/lib/node_exporter/textfile_collector/mc_metrics.prom.tmp",
    "/var/lib/node_exporter/textfile_collector/mc_metrics.prom"
)

Запись через временный файл с os.replace в конце — не косметика, а защита от того, что node_exporter прочитает файл в момент, когда скрипт ещё не дописал его до конца, и получит битые метрики. Вешаем скрипт в cron раз в 30 секунд:

* * * * * for i in 0 30; do sleep $i && /usr/bin/python3 /opt/scripts/mc_metrics.py & done

Для серверов на Source-движке и других играх с A2S-протоколом (CS2, TF2, Rust, ARK и десятки других) — тот же принцип, но онлайн и другие поля берутся через A2S-запрос статуса, разбор протокола и готовые библиотеки описаны в статье про Server Query API для ботов мониторинга — там же примеры на Python, которые с минимальной переделкой пишут .prom-файл вместо ответа боту в Discord.

Готовый файл метрик выглядит просто — это обычный текст с именем метрики и значением через пробел:

minecraft_tps 19.87
minecraft_players_online 14

Если тикрейта или онлайна у игры вообще нет как понятия (некоторые инди-проекты) — можно ограничиться метрикой онлайна через RCON/лог-парсинг и не выдумывать несуществующие показатели, TPS есть далеко не у всех движков в том виде, в каком он есть у Minecraft.

Ставим Grafana и подключаем источник данных

Grafana ставится отдельно от Prometheus, обычно на ту же машину или на выделенную для мониторинга VPS:

sudo apt-get install -y apt-transport-https software-properties-common
sudo add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"
sudo apt-get update
sudo apt-get install grafana
sudo systemctl enable --now grafana-server

По умолчанию Grafana слушает порт 3000. Заходим в веб-интерфейс, логин/пароль по умолчанию admin/admin — сразу меняем при первом входе. Дальше: Connections → Data sources → Add data source → Prometheus, указываем URL (http://localhost:9090 или адрес удалённого Prometheus) и сохраняем.

Если Grafana смотрит наружу в интернет, а не только изнутри VPN — обязательно поставьте сложный пароль и, если панель позволяет, ограничьте доступ по IP на уровне файрвола: дашборд с метриками сервера — не критичные данные, но открытый вход в саму Grafana — потенциальная дыра для доступа к конфигурации мониторинга.

Собираем дашборд: панели и запросы

Дашборд в Grafana — это набор панелей, у каждой свой PromQL-запрос к Prometheus. Несколько рабочих примеров под игровой сервер:

Загрузка CPU (Type: Time series):

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

Использование RAM в процентах:

100 * (1 - ((node_memory_MemAvailable_bytes) / (node_memory_MemTotal_bytes)))

Сетевой трафик, входящий/исходящий (байт/сек):

rate(node_network_receive_bytes_total{device="eth0"}[5m])
rate(node_network_transmit_bytes_total{device="eth0"}[5m])

TPS сервера — просто прямая метрика без агрегации:

minecraft_tps

Для панели TPS удобно настроить пороговые цвета (Thresholds в настройках панели): зелёный от 19, жёлтый 15-19, красный ниже 15 — так на дашборде сразу видно проблемные моменты без чтения точных цифр.

Онлайн игроков за сутки — тут полезнее не текущее число, а история, чтобы видеть пики активности по часам:

minecraft_players_online

c типом панели Time series и группировкой по часам — так будет видно, во сколько сервер реально загружен, что полезно и для решения о тарифе, и для планирования вайпов/рестартов в тихие часы.

Собранные вместе на одном дашборде CPU, RAM, сеть, TPS и онлайн дают полную картину без необходимости лезть в SSH при каждой жалобе на лаги — если совмещать это с ручной диагностикой из статьи про мониторинг TPS и лагов, то большинство разборов «почему лагает» сводится к одному взгляду на дашборд вместо получаса беготни по логам.

Алерты: узнавать о проблеме раньше игроков

Дашборд, на который никто не смотрит в 4 утра, не спасает от простоя ночью. В Grafana есть встроенный Alerting — не нужен отдельный Alertmanager для простых сценариев на один-два сервера.

Создаём алерт-правило на панели TPS: Alert → New alert rule, условие — среднее значение minecraft_tps ниже 15 в течение 5 минут подряд. Каналом уведомлений (Contact point) можно подключить Discord-вебхук — просто вставляете URL вебхука канала в настройках, без дополнительного кода. Если у вас уже есть Discord-бот для мониторинга статуса сервера — алерты из Grafana дополняют его: бот обычно показывает текущий онлайн/статус по запросу, а Grafana сама толкает уведомление именно в момент проблемы, не дожидаясь, пока кто-то спросит.

Аналогично стоит настроить алерт на отсутствие данных вообще (absent() в PromQL) — если node_exporter или игровой сервер упали целиком, метрики просто перестанут поступать, и это тоже надо ловить отдельным правилом, а не полагаться только на пороги по значению.

Не переусердствуйте с чувствительностью — короткая просадка TPS на 10-15 секунд при массовом эксплоуже чанков или спавне ивента это нормально, а не авария. Порог в 5 минут подряд ниже 15 TPS отсекает случайные всплески и ловит именно устойчивую проблему.

Нужен игровой сервер?

MAATRIX GAMES — 45+ игр, деплой за минуты, DDoS-защита, автобэкапы. Тарифы от 399 ₽/мес.

Создать сервер

Частые вопросы

Обязательно ли ставить Prometheus и Grafana на отдельную машину?

Нет, для одного-двух серверов вполне достаточно поднять их прямо на игровой VPS, если тариф позволяет лишние 200-400 МБ RAM под сам стек мониторинга. Отдельная машина имеет смысл, когда серверов много и опрашивать их удобнее централизованно.

Сколько ресурсов реально съедает такой мониторинг?

Ориентировочно — node_exporter почти не заметен (десятки МБ), Prometheus и Grafana вместе на небольшом наборе метрик обычно укладываются в 200-400 МБ RAM и минимальную нагрузку на CPU. На тарифе впритык под саму игру эту прибавку стоит закладывать заранее.

Можно ли собирать метрики с нескольких игровых серверов в одну Grafana?

Да, это стандартный сценарий — один Prometheus с несколькими блоками в scrape_configs, по одному на каждый сервер, и один общий дашборд с фильтром по instance, чтобы переключаться между серверами без создания копий панелей.

Что делать, если игра не даёт вообще никаких игровых метрик, только через сторонние тулы?

Опираться на ресурсы хоста (CPU/RAM/сеть через node_exporter) как на базовый минимум и по возможности парсить лог сервера на предмет событий типа коннект/дисконнект игрока — даже без прямого TPS это уже даёт рабочую картину онлайна во времени.

Grafana подходит только для игровых серверов на Linux?

Сам стек кросс-платформенный, но node_exporter для Windows-хостов заменяется на windows_exporter — принцип с textfile collector и кастомными метриками там тот же самый, конфиг Prometheus меняется минимально.