Files
monitoring/EXPERIENCE.md
T

162 lines
8.2 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.
# Опыт эксплуатации: мониторинг Garage v2.1 через Prometheus
> Дата: 2026-08-30
> Ситуация: кластер Garage v2.1 (RF=3) на vps01 + bigbox + vps02, WireGuard 10.8.0.0/24.
> Задача: вывести статус кластера в браузер (Grafana + Prometheus + Loki).
## Ключевые находки / грабли
### 1. Admin API Garage v2.1 слушает ОТДЕЛЬНЫЙ порт (`[admin] api_bind_addr`)
Самое важное. Если `api_bind_addr` НЕ задан в `[admin]`, Garage слушает admin
(включая `/metrics`) на **том же порту, что S3 API** (3900). В этом случае
`Authorization: Bearer TOKEN` к `/metrics` на 3900 отвечает
`400 Bad request: Unsupported authorization method` — авторизация S3 не понимает
Bearer, а admin-роутер не подключён.
**Решение:** добавить в `[admin]` отдельный адрес:
```toml
[admin]
api_bind_addr = "10.8.0.2:3903" # свой WG-IP на каждой ноде
metrics_token = "..."
admin_token = "..."
```
После рестарта ноды `/metrics` и `/health` доступны на `:3903`.
### 2. `metrics_token` НЕ обязателен
Если `metrics_token` не задан — `/metrics` доступен **без авторизации**.
Если задан — используется как обычный Bearer token:
```
curl -H "Authorization: Bearer TOKEN" http://node:3903/metrics
```
(совпадает с синтаксисом admin_token; для метрик достаточно metrics_token).
### 3. Docker-образ `dxflrs/garage:v2.1.0` — scratch без shell
- Нет `/bin/sh`, нет `ls`, `docker exec garage ls` — не работает.
- CLI-бинарь лежит по пути `/garage` внутри образа, а НЕ в PATH.
- Поэтому проверка статуса через docker run:
```
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
```
(без монтирования `meta` будет ошибка "Unable to read node key").
### 4. Перезапуск нод кластера — безопасно, но по очереди
`docker compose restart garage` на всех трёх нодах прошёл **без потери кворума**
и без пересборки layout — кластер остался HEALTHY (layout version 1 сохранился).
Порядок: внешние (vps02, vps01) → bigbox. Пауза ~8с между рестартами.
### 5. UFW на vps01 режет новые порты
Порт 3903 на vps01 был закрыт UFW (в отличие от 3901, открытого для Anywhere).
Пришлось:
```
sudo ufw allow from 10.8.0.0/24 to any port 3903 proto tcp comment "garage admin metrics"
```
Аналогично пришлось открыть 9100 (node-exporter):
```
sudo ufw allow from 10.8.0.0/24 to any port 9100 proto tcp
```
На vps02 файрвол — nftables с policy ACCEPT, порт не блокировался.
### 6. Конфиг garage.toml на vps01/vps02 принадлежит root
Правка через SSH требует sudo (python не может писать напрямую):
```
ssh vps01 'sudo sed -i "s|^\[admin\]$|[admin]\napi_bind_addr = \"10.8.0.1:3903\"|" /opt/garage/garage.toml'
```
### 7. Docker bridge-сеть НЕ видит WireGuard-интерфейс хоста
Самое важное при разворачивании стека мониторинга: контейнеры в дефолтной
bridge-сети (docker compose networks) **не имеют доступа к WG-подсети 10.8.0.0/24**
хоста. Prometheus не мог достать 10.8.0.x:3903, blackbox — тем более.
**Решение:** prometheus и blackbox-exporter запущены с `network_mode: host`.
Они видят и WG-интерфейс, и друг друга через 127.0.0.1. Grafana, Loki, Promtail
остались в bridge-сети (им WG не нужен).
### 8. `/health` Garage возвращает ТЕКСТ, а не метрику
`curl http://node:3903/health` → `Garage is fully operational` (текст, HTTP 200).
Нельзя использовать как metrics-таргет: Prometheus пытается распарсить текст
как float → `strconv.ParseFloat: parsing "is"`.
**Решение:** health-проверка через **blackbox-exporter** (module http_2xx,
probe_success). В prometheus.yml job `garage_health` с `params: module: [http_2xx]`,
relabel `__address__` → `127.0.0.1:9115`.
### 9. node-exporter — ставится apt'ом
Ubuntu (bigbox): `prometheus-node-exporter` 1.7.0; Debian 13 (vps01/vps02):
1.9.0. Работает сразу как systemd-сервис на :9100 (*:9100, все интерфейсы — WG
виден). На vps01 дополнительно открыть 9100 в ufw (см. п.5).
### 10. Права на volume-каталоги мониторинга
Контейнеры запускаются от не-root UID, а каталоги создавались от root:
- prometheus: UID **65534** (nobody) → `chown 65534:65534 prometheus-data`
- loki: UID **10001** → `chown 10001:10001 loki-data`
- grafana: UID **472** → `chown 472:472 grafana-data`
Иначе: prometheus падает с `Unable to create mmap-ed active query log`,
loki — `mkdir /loki/rules: permission denied`.
### 11. Caddy на vps02 — docker, host network, конфиг /opt/caddy/Caddyfile
Grafana опубликована как `grafana.nixg.ru` (DNS → 87.242.100.206 = vps02):
```
grafana.nixg.ru {
reverse_proxy 10.8.0.2:3001
}
```
- Caddy в docker (`network_mode: host`), конфиг смонтирован из /opt/caddy/Caddyfile.
- Перезагрузка: `docker exec caddy caddy reload --config /etc/caddy/Caddyfile`
- Сертификат Let's Encrypt выпускается автоматически (http-01), но первые ~30с
после reload соединение может падать — это нормально.
- В логах caddy много ошибок renew для старых доменов — они имеют
уже выпущенные сертификаты в caddy_data, работает всё.
## Проверка результата
```
# все три ноды отдают метрики:
curl -s -H "Authorization: Bearer TOKEN" http://10.8.0.1:3903/metrics | head
curl -s -H "Authorization: Bearer TOKEN" http://10.8.0.2:3903/metrics | head
curl -s -H "Authorization: Bearer TOKEN" http://10.8.0.4:3903/metrics | head
# → HTTP 200, ~90-110 КБ текста в Prometheus-формате
# кластер HEALTHY:
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: все таргеты UP (10/10):
curl http://127.0.0.1:9090/api/v1/targets
# garage x3, garage_health x3, node x3, prometheus self
# Grafana наружу:
curl -sk https://grafana.nixg.ru/api/health # → 200
# логи garage в Loki:
curl -G "http://127.0.0.1:3100/loki/api/v1/query_range" \
--data-urlencode 'query={container="garage"}' --data-urlencode 'limit=3'
```
## Что осталось сделать / TODO
- [x] Развернуть стек (docker compose up -d) в /opt/monitoring
- [x] Node-exporter на всех 3 хостах (10.8.0.x:9100)
- [x] Дашборд Garage в Grafana (provisioning + JSON)
- [x] `up{job="garage"}` в Prometheus, Grafana :3001
- [x] Логи garage через promtail → Loki → Grafana
- [x] Опубликовать Grafana: grafana.nixg.ru через caddy на vps02
- [x] Mirror репозитория мониторинга в gitea (estorozhenko/monitoring)
- [ ] Сделать разные admin_token / metrics_token (сейчас совпадают)
- [ ] Поменять пароль Grafana с дефолтного (сейчас: пользователь estorozhenko,
пароль сменён пользователем вручную через UI)