Files
monitoring/README.md
T

204 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`. На всех трёх нодах прописано:
```toml
[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).
Проверка вручную:
```bash
# 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_*`). vps03 НЕ в WG-сети, а :8081
слушает ТОЛЬКО loopback — поэтому вместо открытия порта наружу сделан
**SSH-туннель bigbox → vps03**:
```
systemd: tproxy-tunnel.service (bigbox)
ssh -i /home/estorozhenko/.ssh/hostkeyVPS \
-L 127.0.0.1:18081:127.0.0.1:8081 -N root@77.67.89.154
```
- Локальный порт **18081** (не 8081 — тот на bigbox занят ICQ-веб-чатом!)
- Prometheus скрейпит `127.0.0.1:18081` (job `tproxy`, 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.
## Катастрофоустойчивость
Проект хранится в **двух** 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.