8.2 KiB
Опыт эксплуатации: мониторинг 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] отдельный адрес:
[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
- Развернуть стек (docker compose up -d) в /opt/monitoring
- Node-exporter на всех 3 хостах (10.8.0.x:9100)
- Дашборд Garage в Grafana (provisioning + JSON)
up{job="garage"}в Prometheus, Grafana :3001- Логи garage через promtail → Loki → Grafana
- Опубликовать Grafana: grafana.nixg.ru через caddy на vps02
- Mirror репозитория мониторинга в gitea (estorozhenko/monitoring)
- Сделать разные admin_token / metrics_token (сейчас совпадают)
- Поменять пароль Grafana с дефолтного (сейчас: пользователь estorozhenko, пароль сменён пользователем вручную через UI)