diff --git a/EXPERIENCE.md b/EXPERIENCE.md index 542c3f6..efbf394 100644 --- a/EXPERIENCE.md +++ b/EXPERIENCE.md @@ -10,7 +10,7 @@ Самое важное. Если `api_bind_addr` НЕ задан в `[admin]`, Garage слушает admin (включая `/metrics`) на **том же порту, что S3 API** (3900). В этом случае -`Authorization: Bearer ` к `/metrics` на 3900 отвечает +`Authorization: Bearer TOKEN` к `/metrics` на 3900 отвечает `400 Bad request: Unsupported authorization method` — авторизация S3 не понимает Bearer, а admin-роутер не подключён. @@ -30,7 +30,7 @@ admin_token = "..." Если `metrics_token` не задан — `/metrics` доступен **без авторизации**. Если задан — используется как обычный Bearer token: ``` -curl -H "Authorization: Bearer " http://node:3903/metrics +curl -H "Authorization: Bearer TOKEN" http://node:3903/metrics ``` (совпадает с синтаксисом admin_token; для метрик достаточно metrics_token). @@ -60,6 +60,10 @@ docker run --rm \ ``` 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 @@ -69,35 +73,90 @@ sudo ufw allow from 10.8.0.0/24 to any port 3903 proto tcp comment "garage admin ssh vps01 'sudo sed -i "s|^\[admin\]$|[admin]\napi_bind_addr = \"10.8.0.1:3903\"|" /opt/garage/garage.toml' ``` -### 7. Авторизация в веб-поиске не работает напрямую с bigbox +### 7. Docker bridge-сеть НЕ видит WireGuard-интерфейс хоста -SearXNG (127.0.0.1:11436) возвращает пустые результаты из-за блокировок -движков (brave rate-limit, duckduckgo CAPTCHA, startpage timeout). -Документация Garage достаётся напрямую с git.deuxfleurs.fr: +Самое важное при разворачивании стека мониторинга: контейнеры в дефолтной +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): ``` -https://git.deuxfleurs.fr/Deuxfleurs/garage/raw/branch/main-v1/doc/book/reference-manual/configuration.md -https://git.deuxfleurs.fr/Deuxfleurs/garage/raw/branch/main-v1/doc/book/reference-manual/admin-api.md +grafana.nixg.ru { + reverse_proxy 10.8.0.2:3001 +} ``` -Ветка по умолчанию для v2.x — `main-v1` (не `main`). +- 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 " http://10.8.0.1:3903/metrics | head -curl -s -H "Authorization: Bearer " http://10.8.0.2:3903/metrics | head -curl -s -H "Authorization: Bearer " http://10.8.0.4:3903/metrics | head +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 -- [ ] Сделать разные admin_token / metrics_token (сейчас совпадают) \ No newline at end of file +- [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) \ No newline at end of file diff --git a/README.md b/README.md index 23b7217..102bce7 100644 --- a/README.md +++ b/README.md @@ -8,30 +8,49 @@ ``` bigbox (10.8.0.2) ┌─────────────────────────────────────────────────┐ - │ prometheus :9090 ── scrape ──► garage x3 :3903 │ - │ │ (WG admin API) │ - │ ├──► node-exporter :9100 (bigbox) │ - │ └──► 10.8.0.1:3903 (vps01) │ - │ 10.8.0.4:3903 (vps02) │ + │ 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 - vps01 (10.8.0.1) vps02 (10.8.0.4) + │ │ + ▼ 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 | retention 30d (TSDB) | -| Grafana | 3001 | браузер bigbox | 3000 занят gitea → 3001 | -| Loki | 3100 | локально | сбор логов | -| Promtail | — | docker.sock | docker logs garage | -| node-exp | 9100 | WG | на каждой ноде (системные метрики) | +| Сервис | Порт | Доступ | Примечание | +|------------------|--------|---------------------|-------------------------------------| +| 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), пароль — задан пользователем. ## Garage admin API (метрики) @@ -41,18 +60,18 @@ ```toml [admin] api_bind_addr = ":3903" # bigbox 10.8.0.2, vps01 10.8.0.1, vps02 10.8.0.4 -admin_token = "c213de..." -metrics_token = "c213de..." +admin_token = "..." +metrics_token = "..." ``` Проверка метрик: ``` -curl -H "Authorization: Bearer c213de..." http://10.8.0.2:3903/metrics +curl -H "Authorization: Bearer TOKEN" http://10.8.0.2:3903/metrics ``` `/health` возвращает 200 при кворуме (≥2 нод), 503 иначе. -Порты 3903 открыты только для WG-подсети: -- vps01: `ufw allow from 10.8.0.0/24 to any port 3903` +Порты 3903 и 9100 открыты только для WG-подсети: +- vps01: `ufw allow from 10.8.0.0/24 to any port 3903` (и 9100 аналогично) - vps02/bigbox: файрвол не блокирует (policy ACCEPT) ## Запуск @@ -63,6 +82,7 @@ docker compose up -d ``` Пароль Grafana — переменная `GRAFANA_ADMIN_PASSWORD` в `.env` (по умолчанию `admin`). +Пользователь Grafana: `estorozhenko` (сменён пользователем вручную). ## Полезные команды @@ -73,10 +93,17 @@ docker run --rm -v /opt/garage/garage.toml:/etc/garage.toml:ro \ --entrypoint /garage dxflrs/garage:v2.1.0 status # метрики одной ноды (Prometheus-формат) -curl -s -H "Authorization: Bearer " http://10.8.0.2:3903/metrics | head +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) @@ -90,4 +117,13 @@ curl -s -o /dev/null -w "%{http_code}" http://10.8.0.2:3903/health ## Катастрофоустойчивость -Проект хранится в **двух** git-репозиториях (см. ниже) — на случай поломки bigbox. \ No newline at end of file +Проект хранится в **двух** 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. \ No newline at end of file