Monitoring stack — Garage cluster (vps01 + bigbox + vps02) + Vinograd WAN
Стек мониторинга для S3-кластера Garage (репликация RF=3, WireGuard 10.8.0.0/24)
и внешнего канала связи объекта «Винный город» (провайдер Ростелеком).
Расположен на bigbox в /opt/monitoring.
Архитектура
bigbox (10.8.0.2)
┌─────────────────────────────────────────────────┐
│ prometheus :9090 (host net) │
│ │ scrape ──► garage x3 :3903 (WG admin) │
│ ├──► node-exporter :9100 (bigbox) │
│ ├──► 10.8.0.1:3903 (vps01) │
│ ├──► 10.8.0.4:3903 (vps02) │
│ └──► blackbox :9115 (host net) → /health │
│ │
│ grafana :3001 (dashboards, alerts) │
│ loki :3100 (logs) │
│ promtail ── docker.sock ──► docker logs garage │
└─────────────────────────────────────────────────┘
│ │
▼ WireGuard 10.8.0.0/24 ▼ caddy (vps02)
vps01 (10.8.0.1) grafana.nixg.ru
vps02 (10.8.0.4) → 87.242.100.206 → reverse_proxy 10.8.0.2:3001
Прометеус и blackbox-exporter работают в host network (иначе не видят WireGuard-подсеть 10.8.0.0/24 хостa). Остальные — в bridge-сети monitoring.
Сервисы и порты
| Сервис | Порт | Доступ | Примечание |
|---|---|---|---|
| Prometheus | 9090 | локально/WG | host network, retention 30d (TSDB) |
| Grafana | 3001 | браузер + публично | 3000 занят gitea → 3001 |
| Loki | 3100 | локально | сбор логов, retention 7d |
| Promtail | — | docker.sock | docker logs garage и др. |
| blackbox-exporter | 9115 | host network | HTTP-пробы /health нод |
| node-exporter | 9100 | WG | на каждой ноде (apt) |
Публичный доступ
grafana.nixg.ru → 87.242.100.206 (vps02) → caddy → reverse_proxy 10.8.0.2:3001
- Запись добавлена в
/opt/caddy/Caddyfileна vps02:grafana.nixg.ru { reverse_proxy 10.8.0.2:3001 } - Caddy — docker-контейнер (
network_mode: host), перезагрузка:docker exec caddy caddy reload --config /etc/caddy/Caddyfile - Сертификат Let's Encrypt выпускается автоматически.
- Логин: estorozhenko (сменён с admin через UI), пароль — задан пользователем.
- Read-only доступ: it@vinogorod.ru (роль Viewer, создан вручную в UI,
пароль
1qazXSW2). Только просмотр дашбордов, без правки. Учётка вgrafana-data(переживает пересоздание контейнера).
Garage admin API (метрики)
В Garage v2.1 admin API (включая /metrics в Prometheus-формате) слушает
отдельный порт [admin] api_bind_addr. На всех трёх нодах прописано:
[admin]
api_bind_addr = "<WG-IP>:3903" # bigbox 10.8.0.2, vps01 10.8.0.1, vps02 10.8.0.4
admin_token = "..."
metrics_token = "..."
Проверка метрик:
curl -H "Authorization: Bearer TOKEN" http://10.8.0.2:3903/metrics
/health возвращает 200 при кворуме (≥2 нод), 503 иначе.
Порты 3903 и 9100 открыты только для WG-подсети:
- vps01:
ufw allow from 10.8.0.0/24 to any port 3903(и 9100 аналогично) - vps02/bigbox: файрвол не блокирует (policy ACCEPT)
Запуск
cd /opt/monitoring
docker compose up -d
Пароль Grafana — переменная GRAFANA_ADMIN_PASSWORD в .env (по умолчанию admin).
Пользователь Grafana: estorozhenko (сменён пользователем вручную).
Полезные команды
# статус кластера
docker run --rm -v /opt/garage/garage.toml:/etc/garage.toml:ro \
-v /opt/garage/meta:/var/lib/garage/meta \
--entrypoint /garage dxflrs/garage:v2.1.0 status
# метрики одной ноды (Prometheus-формат)
curl -s -H "Authorization: Bearer TOKEN" http://10.8.0.2:3903/metrics | head
# health
curl -s -o /dev/null -w "%{http_code}" http://10.8.0.2:3903/health
# таргеты прометея (все должны быть UP)
curl http://127.0.0.1:9090/api/v1/targets
# принудительная синхронизация mirror'а в gitea
curl -X POST -H "Authorization: token GITEA_TOK" \
http://127.0.0.1:3000/api/v1/repos/estorozhenko/monitoring/mirror-sync
Алерты (prometheus/alerts.yml)
| Алерт | Условие | Severity |
|---|---|---|
| GarageNodeDown | up{job="garage"} == 0 (2м) |
critical |
| GarageNoQuorum | <2 нод up (2м) |
critical |
| GarageResyncErrors | block_resync_errored_blocks > 0 (10м) |
warning |
| GarageNodeUnstable | cluster_layout_node_connected == 0 (5м) |
warning |
| TProxyDown | up{job="tproxy"} == 0 (2м) |
critical |
| TProxyBackendErrors | increase(tproxy_backend_dial_failures_total[5m]) > 0 (10м) |
warning |
| VinogradRostelecomDown | probe_success{job="vinograd_wan"} == 0 (2м) |
critical |
Примечание: метрики Garage из admin API (:3903) НЕ имеют префикса garage_ —
это api_s3_request_counter, block_resync_*, cluster_*. Префикс garage_
только у garage_build_info, garage_local_disk_*, garage_replication_factor.
Vinograd WAN — внешний канал «Винный город» (Ростелеком)
Объект «Винный город» (г. Геленджик, ул. Туристическая, 25), канал Ростелеком (договор Бастион, Static IP). Адреса из «Реестра внешних каналов связи.ods» (закладка «Винный город»):
| Адрес | Роль |
|---|---|
| 83.239.50.145 | Шлюз (gateway) — поднимается от РТК |
| 83.239.50.146 | Наше оборудование (CPE, Static IP, /30) |
Мониторинг через blackbox-exporter (ICMP-проба) → Prometheus job vinograd_wan:
- Интервал scrape: 30s (графики скорости ответа каждые 30 секунд)
- Метрики:
probe_success{job="vinograd_wan"}— доступность (1/0)probe_icmp_duration_seconds{job="vinograd_wan",phase="rtt"}— RTT, сек
- Лейблы
instance:vinograd-gw-83.239.50.145,vinograd-cpe-83.239.50.146 - Алерт: VinogradRostelecomDown (critical, 2м подряд недоступен)
- Grafana: дашборд Vinograd WAN (RTT ms + availability), панели в фолдере Garage
Retention: глобальный 30d (прометеевский TSDB) — данные хранятся минимум неделю, что покрывает требование «хранить неделю» с запасом (жёсткий 7d для одного job требовал бы отдельного инстанса Prometheus).
Проверка вручную:
# ICMP-проба через blackbox (debug)
curl -s "http://127.0.0.1:9115/probe?target=83.239.50.146&module=icmp&debug=true"
# данные в Prometheus
curl -sG 'http://127.0.0.1:9090/api/v1/query' \
--data-urlencode 'query=probe_success{job="vinograd_wan"}'
Статус 2026-09-08: шлюз 83.239.50.145 НЕ отвечает на ICMP (probe_success=0, совпадает с алертом UptimeKuma 08:07 MSK). Оборудование 83.239.50.146 отвечает ~13ms. Алерт VinogradRostelecomDown в состоянии FIRE до восстановления канала — это корректное отражение реальной аварии.
tproxy-server (vps03) — метрики WEB Proxy (этап 6, РЕШЕНО ✅)
tproxy-server (Telegram Desktop WEB Proxy) развёрнут на vps03 (77.67.89.154),
admin-эндпоинты на loopback :8081: /healthz, /readyz, /metrics
(Prometheus-формат, 13 счётчиков tproxy_*).
2026-09-08: vps03 подключён к WireGuard (10.8.0.3) — вместо SSH-туннеля. Админ-эндпоинты tproxy остались на loopback, но туннель
tproxy-tunnel.serviceудалён не был (безвреден, оставлен на всякий случай). Prometheus берёт node-метрики vps03 напрямую по WG:10.8.0.3:9100.
- Локальный порт 18081 (не 8081 — тот на bigbox занят ICQ-веб-чатом!)
- Prometheus скрейпит
127.0.0.1:18081(jobtproxy, host=vps03), но через relabel_configs в prometheus.yml лейблinstanceзаменён наvps03:8081, чтобы в Grafana легенды показывали hostname, а не IP туннеля. Аналогично relabel сделан для garage (10.8.0.x:3903→vps01|bigbox|vps02:3903) и node (10.8.0.x:9100→ hostname). - Дашборд: 3 панели tproxy (sessions/streams, traffic /sec, backend errors)
- Алерты: TProxyDown (critical), TProxyBackendErrors (warning)
Подробности — в PLAN.md (этап 6) и EXPERIENCE.md.
Node-дашборды (диски/память/сеть/доступность) — этап 7, РЕШЕНО ✅
На каждую ноду (vps01, vps02, vps03, bigbox) — отдельный дашборд,
grafana/dashboards/nodes/node-<host>.json (uid node-<host>, title "Node ").
Генерируются скриптом /tmp/gen_nodes_dash.py (в git не хранится; при желании
перенести — в EXPERIENCE.md). Файлы дашбордов разложены по подпапкам
(папки в UI Grafana совпадают):
grafana/dashboards/— garage-cluster.json → папка Garagegrafana/dashboards/nodes/— node-*.json → папка nodesgrafana/dashboards/vinogorod/— vinograd-wan.json → папка vinogorod
Панели (все по {host="<host>"}, job=node):
- Availability — stat-панель
up{job="node",host=...}(UP/DOWN) - Disk free (GB) —
node_filesystem_avail_bytes(без tmpfs/overlay/squashfs) - Memory available (GB) —
node_memory_MemAvailable_bytes - Load —
node_load1/5/15 - Net RX/TX (bytes/s) —
rate(node_network_{receive,transmit}_bytes_total[5m]) - Net utilization (%) —
(rx+tx)*8/speed*100
Физические интерфейсы: vps01=eth0, vps02=enp3s0, vps03=ens1, bigbox=eno1. Контейнерные (docker0/veth*/br-*) не включены.
Тонкость node-exporter 1.9: на виртуалках vps01/vps02 node_network_speed_bytes
= -125000 (sysfs speed=-1 → умножается на 125000), поэтому для них скорость
линка захардкожена 125000000 Б/с (1 Gbit/s) в формуле утилизации. На физических
(vps03/bigbox) используется сама метрика node_network_speed_bytes (=1.25e+08).
Катастрофоустойчивость
Проект хранится в двух git-репозиториях — на случай поломки bigbox:
| Репозиторий | Роль | Адрес |
|---|---|---|
| gitverse.ru (облако) | источник истины | git@gitverse.ru:kpa39l/monitoring.git |
| gitea на bigbox | pull-mirror (8h) | https://gitea.nixg.ru/estorozhenko/monitoring |
Порядок работы: правки коммитятся и пушутся в gitverse (источник), gitea подтягивает их mirror'ом (каждые 8ч или вручную mirror-sync). Если bigbox сломается — репозиторий остаётся в облаке gitverse.