mirror of
https://gitverse.ru/kpa39l/monitoring.git
synced 2026-09-29 09:55:09 +00:00
first_commit
This commit is contained in:
+14
@@ -0,0 +1,14 @@
|
|||||||
|
# Данные и кэши — не в git
|
||||||
|
prometheus-data/
|
||||||
|
grafana-data/
|
||||||
|
loki-data/
|
||||||
|
promtail-data/
|
||||||
|
|
||||||
|
# env с паролями
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
|
||||||
|
# временное
|
||||||
|
*.tmp
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
# Опыт эксплуатации: мониторинг 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 <metrics_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"
|
||||||
|
```
|
||||||
|
На 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. Авторизация в веб-поиске не работает напрямую с bigbox
|
||||||
|
|
||||||
|
SearXNG (127.0.0.1:11436) возвращает пустые результаты из-за блокировок
|
||||||
|
движков (brave rate-limit, duckduckgo CAPTCHA, startpage timeout).
|
||||||
|
Документация Garage достаётся напрямую с git.deuxfleurs.fr:
|
||||||
|
```
|
||||||
|
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
|
||||||
|
```
|
||||||
|
Ветка по умолчанию для v2.x — `main-v1` (не `main`).
|
||||||
|
|
||||||
|
## Проверка результата
|
||||||
|
|
||||||
|
```
|
||||||
|
# все три ноды отдают метрики:
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
## Что осталось сделать / 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 (сейчас совпадают)
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# План работ: мониторинг Garage-кластера
|
||||||
|
|
||||||
|
## Цель
|
||||||
|
Вывести статус кластера Garage (vps01, bigbox, vps02) в браузер через Grafana,
|
||||||
|
с Prometheus-метриками и сбором логов (Loki). Без трейсов (до них «не доросли»).
|
||||||
|
|
||||||
|
## Этап 1. Метрики Garage (выполнено ✅)
|
||||||
|
|
||||||
|
1. Понять, как Garage v2.1 отдаёт метрики.
|
||||||
|
→ Найдено: admin API на отдельном порту `[admin] api_bind_addr`; `/metrics` в
|
||||||
|
Prometheus-формате; `metrics_token` опционален.
|
||||||
|
2. Добавить в `/opt/garage/garage.toml` на **трёх** нодах:
|
||||||
|
```toml
|
||||||
|
[admin]
|
||||||
|
api_bind_addr = "<WG-IP>:3903"
|
||||||
|
metrics_token = "<token>"
|
||||||
|
```
|
||||||
|
- bigbox: 10.8.0.2:3903 (файл — estorozhenko)
|
||||||
|
- vps01: 10.8.0.1:3903 (файл — root, sudo)
|
||||||
|
- vps02: 10.8.0.4:3903 (файл — root, sudo)
|
||||||
|
3. Открыть порт 3903 для WG-подсети на vps01 (ufw); на vps02/bigbox не требуется.
|
||||||
|
4. Перезапустить ноды по очереди: vps02 → vps01 → bigbox (пауза ~8с).
|
||||||
|
5. Проверить: `curl -H "Authorization: Bearer <token>" http://<ip>:3903/metrics` → 200.
|
||||||
|
|
||||||
|
**Результат:** все 3 ноды отдают метрики, кластер HEALTHY.
|
||||||
|
|
||||||
|
## Этап 2. Стек мониторинга на bigbox (в работе 🔄)
|
||||||
|
|
||||||
|
- [x] Создать `/opt/monitoring/` с docker-compose.yml, prometheus.yml, alerts.yml
|
||||||
|
- [x] Prometheus: таргеты garage x3 (:3903), health x3, node-exporters, self
|
||||||
|
- [ ] Node-exporter на 3 хостах (10.8.0.x:9100)
|
||||||
|
- [ ] Запустить `docker compose up -d`
|
||||||
|
- [ ] Проверить Prometheus :9090 (`up{job="garage"}`, targets)
|
||||||
|
- [ ] Grafana :3001: datasource Prometheus, дашборд Garage, alerts
|
||||||
|
|
||||||
|
## Этап 3. Логи (после метрик 🔄)
|
||||||
|
|
||||||
|
- [ ] Promtail (docker.sock) → Loki :3100 → Grafana
|
||||||
|
- [ ] Логи garage со всех нод (сейчас promtail только на bigbox)
|
||||||
|
|
||||||
|
## Этап 4. Git + катастрофоустойчивость (в работе 🔄)
|
||||||
|
|
||||||
|
- [x] MD-файлы: README.md, EXPERIENCE.md, PLAN.md
|
||||||
|
- [ ] git init в /opt/monitoring, первый коммит
|
||||||
|
- [ ] remote: git@gitverse.ru:kpa39l/monitoring.git (master)
|
||||||
|
- [ ] `git push -u origin master`
|
||||||
|
- [ ] В gitea: pull mirror репозитория из gitverse
|
||||||
|
- [ ] В gitea: добавить estorozhenko с полными правами (на случай поломки bigbox)
|
||||||
|
|
||||||
|
## Этап 5. Полировка (TODO)
|
||||||
|
|
||||||
|
- [ ] Разные admin_token / metrics_token (`openssl rand -base64 32`)
|
||||||
|
- [ ] Дашборд: статус нод, занятость диска, блоки, репликация
|
||||||
|
- [ ] Уведомления алертов (например, в Telegram/почту)
|
||||||
|
|
||||||
|
## Риски / заметки
|
||||||
|
|
||||||
|
- Перезапуск нод кластера безопасен, но делать по очереди.
|
||||||
|
- Scratch-образ garage → для CLI-команд нужен `--entrypoint /garage` + монтирование meta.
|
||||||
|
- Интернет с bigbox частично ограничен; документация — через git.deuxfleurs.fr (ветка main-v1).
|
||||||
|
- Port 3000 занят gitea → Grafana на 3001.
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# Monitoring stack — Garage cluster (vps01 + bigbox + vps02)
|
||||||
|
|
||||||
|
Стек мониторинга для S3-кластера Garage (репликация RF=3, WireGuard 10.8.0.0/24).
|
||||||
|
Расположен на **bigbox** в `/opt/monitoring`.
|
||||||
|
|
||||||
|
## Архитектура
|
||||||
|
|
||||||
|
```
|
||||||
|
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) │
|
||||||
|
│ │
|
||||||
|
│ 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)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Сервисы и порты
|
||||||
|
|
||||||
|
| Сервис | Порт | Доступ | Примечание |
|
||||||
|
|-----------|-----------|--------------------|--------------------------------|
|
||||||
|
| Prometheus| 9090 | локально/WG | retention 30d (TSDB) |
|
||||||
|
| Grafana | 3001 | браузер bigbox | 3000 занят gitea → 3001 |
|
||||||
|
| Loki | 3100 | локально | сбор логов |
|
||||||
|
| Promtail | — | docker.sock | docker logs garage |
|
||||||
|
| node-exp | 9100 | WG | на каждой ноде (системные метрики) |
|
||||||
|
|
||||||
|
## 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 = "c213de..."
|
||||||
|
metrics_token = "c213de..."
|
||||||
|
```
|
||||||
|
|
||||||
|
Проверка метрик:
|
||||||
|
```
|
||||||
|
curl -H "Authorization: Bearer c213de..." 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`
|
||||||
|
- vps02/bigbox: файрвол не блокирует (policy ACCEPT)
|
||||||
|
|
||||||
|
## Запуск
|
||||||
|
|
||||||
|
```
|
||||||
|
cd /opt/monitoring
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Пароль Grafana — переменная `GRAFANA_ADMIN_PASSWORD` в `.env` (по умолчанию `admin`).
|
||||||
|
|
||||||
|
## Полезные команды
|
||||||
|
|
||||||
|
```
|
||||||
|
# статус кластера
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
## Алерты (prometheus/alerts.yml)
|
||||||
|
|
||||||
|
| Алерт | Условие | Severity |
|
||||||
|
|--------------------|--------------------------------|----------|
|
||||||
|
| GarageNodeDown | `up{job="garage"} == 0` (2м) | critical |
|
||||||
|
| GarageNoQuorum | `<2` нод up (2м) | critical |
|
||||||
|
| GarageResyncErrors | `garage_block_resync_error_count > 0` (10м) | warning |
|
||||||
|
| GarageNodeUnstable | RPC health down (5м) | warning |
|
||||||
|
|
||||||
|
## Катастрофоустойчивость
|
||||||
|
|
||||||
|
Проект хранится в **двух** git-репозиториях (см. ниже) — на случай поломки bigbox.
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
groups:
|
||||||
|
- name: garage
|
||||||
|
rules:
|
||||||
|
- alert: GarageNodeDown
|
||||||
|
expr: up{job="garage"} == 0
|
||||||
|
for: 2m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
summary: "Garage node {{ $labels.instance }} is down"
|
||||||
|
|
||||||
|
- alert: GarageNoQuorum
|
||||||
|
expr: (count(up{job="garage"} == 1) < 2)
|
||||||
|
for: 2m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
summary: "Garage cluster lost quorum (<2 nodes up)"
|
||||||
|
|
||||||
|
- alert: GarageResyncErrors
|
||||||
|
expr: garage_block_resync_error_count > 0
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
summary: "Garage resync errors on {{ $labels.instance }}"
|
||||||
|
|
||||||
|
- alert: GarageNodeUnstable
|
||||||
|
expr: garage_rpc_node_health_is_up == 0
|
||||||
|
for: 5m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
summary: "Garage RPC health of some node is down"
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# Monitoring stack: Prometheus + Grafana + Loki + Promtail
|
||||||
|
# Garage cluster (vps01, bigbox, vps02) metrics via WG admin API :3903
|
||||||
|
# Logs: docker logs of garage containers via promtail (docker driver)
|
||||||
|
|
||||||
|
services:
|
||||||
|
prometheus:
|
||||||
|
image: prom/prometheus:v2.53.0
|
||||||
|
container_name: prometheus
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||||
|
- ./prometheus-data:/prometheus
|
||||||
|
command:
|
||||||
|
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||||
|
- '--storage.tsdb.retention.time=30d'
|
||||||
|
- '--storage.tsdb.path=/prometheus'
|
||||||
|
ports:
|
||||||
|
- "9090:9090"
|
||||||
|
networks:
|
||||||
|
- monitoring
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana:11.1.0
|
||||||
|
container_name: grafana
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- GF_SECURITY_ADMIN_USER=admin
|
||||||
|
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:-admin}
|
||||||
|
- GF_USERS_ALLOW_SIGN_UP=false
|
||||||
|
- GF_SERVER_ROOT_URL=http://localhost:3001
|
||||||
|
volumes:
|
||||||
|
- ./grafana-data:/var/lib/grafana
|
||||||
|
- ./grafana/provisioning:/etc/grafana/provisioning:ro
|
||||||
|
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
|
||||||
|
ports:
|
||||||
|
- "3001:3000"
|
||||||
|
depends_on:
|
||||||
|
- prometheus
|
||||||
|
networks:
|
||||||
|
- monitoring
|
||||||
|
|
||||||
|
loki:
|
||||||
|
image: grafana/loki:3.1.0
|
||||||
|
container_name: loki
|
||||||
|
restart: unless-stopped
|
||||||
|
command: -config.file=/etc/loki/local-config.yaml
|
||||||
|
volumes:
|
||||||
|
- ./loki-config.yaml:/etc/loki/local-config.yaml:ro
|
||||||
|
- ./loki-data:/loki
|
||||||
|
ports:
|
||||||
|
- "3100:3100"
|
||||||
|
networks:
|
||||||
|
- monitoring
|
||||||
|
|
||||||
|
promtail:
|
||||||
|
image: grafana/promtail:3.1.0
|
||||||
|
container_name: promtail
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./promtail-config.yaml:/etc/promtail/config.yaml:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
command: -config.file=/etc/promtail/config.yaml
|
||||||
|
depends_on:
|
||||||
|
- loki
|
||||||
|
networks:
|
||||||
|
- monitoring
|
||||||
|
|
||||||
|
networks:
|
||||||
|
monitoring:
|
||||||
|
driver: bridge
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 1,
|
||||||
|
"id": null,
|
||||||
|
"links": [],
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"datasource": { "type": "prometheus", "uid": "Prometheus" },
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": { "mode": "thresholds" },
|
||||||
|
"mappings": [
|
||||||
|
{ "options": { "0": { "color": "red", "text": "DOWN" }, "1": { "color": "green", "text": "UP" } }, "type": "value" }
|
||||||
|
],
|
||||||
|
"thresholds": { "mode": "absolute", "steps": [ { "color": "red", "value": null }, { "color": "green", "value": 1 } ] }
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": { "h": 8, "w": 6, "x": 0, "y": 0 },
|
||||||
|
"id": 1,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "background",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false },
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "11.1.0",
|
||||||
|
"targets": [
|
||||||
|
{ "datasource": { "type": "prometheus", "uid": "Prometheus" }, "expr": "up{job=\"garage\"}", "legendFormat": "{{ instance }}", "refId": "A" }
|
||||||
|
],
|
||||||
|
"title": "Garage nodes up",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": { "type": "prometheus", "uid": "Prometheus" },
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": { "mode": "palette-classic" },
|
||||||
|
"custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } },
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": { "h": 8, "w": 6, "x": 6, "y": 0 },
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true },
|
||||||
|
"tooltip": { "mode": "multi", "sort": "none" }
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{ "datasource": { "type": "prometheus", "uid": "Prometheus" }, "expr": "node_filesystem_avail_bytes{fstype!~\"tmpfs|overlay|squashfs\"} / 1024 / 1024 / 1024", "legendFormat": "{{ instance }}", "refId": "A" }
|
||||||
|
],
|
||||||
|
"title": "Node disk free (GB)",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": { "type": "prometheus", "uid": "Prometheus" },
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": { "mode": "palette-classic" },
|
||||||
|
"custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } },
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 },
|
||||||
|
"id": 3,
|
||||||
|
"options": {
|
||||||
|
"legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true },
|
||||||
|
"tooltip": { "mode": "multi", "sort": "none" }
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{ "datasource": { "type": "prometheus", "uid": "Prometheus" }, "expr": "garage_block_count", "legendFormat": "blocks {{ instance }}", "refId": "A" },
|
||||||
|
{ "datasource": { "type": "prometheus", "uid": "Prometheus" }, "expr": "garage_block_resync_queue_length", "legendFormat": "resync queue {{ instance }}", "refId": "B" }
|
||||||
|
],
|
||||||
|
"title": "Garage blocks",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": { "type": "prometheus", "uid": "Prometheus" },
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": { "mode": "thresholds" },
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 1 } ] }
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 },
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true },
|
||||||
|
"tooltip": { "mode": "multi", "sort": "none" }
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{ "datasource": { "type": "prometheus", "uid": "Prometheus" }, "expr": "garage_rpc_node_health_is_up", "legendFormat": "{{ instance }}", "refId": "A" }
|
||||||
|
],
|
||||||
|
"title": "Garage RPC node health",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": { "type": "prometheus", "uid": "Prometheus" },
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": { "mode": "palette-classic" },
|
||||||
|
"custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } },
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 },
|
||||||
|
"id": 5,
|
||||||
|
"options": {
|
||||||
|
"legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true },
|
||||||
|
"tooltip": { "mode": "multi", "sort": "none" }
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{ "datasource": { "type": "prometheus", "uid": "Prometheus" }, "expr": "rate(garage_api_s3_request_counter[5m])", "legendFormat": "{{ instance }} {{ api_endpoint }}", "refId": "A" }
|
||||||
|
],
|
||||||
|
"title": "S3 requests /sec",
|
||||||
|
"type": "timeseries"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "30s",
|
||||||
|
"schemaVersion": 39,
|
||||||
|
"tags": [ "garage" ],
|
||||||
|
"templating": { "list": [] },
|
||||||
|
"time": { "from": "now-6h", "to": "now" },
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "browser",
|
||||||
|
"title": "Garage Cluster",
|
||||||
|
"uid": "garage-cluster",
|
||||||
|
"version": 1,
|
||||||
|
"weekStart": ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
providers:
|
||||||
|
- name: 'garage-dashboards'
|
||||||
|
orgId: 1
|
||||||
|
folder: 'Garage'
|
||||||
|
type: file
|
||||||
|
disableDeletion: false
|
||||||
|
updateIntervalSeconds: 30
|
||||||
|
options:
|
||||||
|
path: /var/lib/grafana/dashboards
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
- name: Prometheus
|
||||||
|
type: prometheus
|
||||||
|
access: proxy
|
||||||
|
url: http://prometheus:9090
|
||||||
|
isDefault: true
|
||||||
|
editable: true
|
||||||
|
|
||||||
|
- name: Loki
|
||||||
|
type: loki
|
||||||
|
access: proxy
|
||||||
|
url: http://loki:3100
|
||||||
|
isDefault: false
|
||||||
|
editable: true
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
evaluation_interval: 15s
|
||||||
|
external_labels:
|
||||||
|
monitor: 'garage-cluster'
|
||||||
|
|
||||||
|
rule_files:
|
||||||
|
- /etc/prometheus/alerts.yml
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
# Garage node metrics (admin API on WG)
|
||||||
|
- job_name: 'garage'
|
||||||
|
metrics_path: /metrics
|
||||||
|
scheme: http
|
||||||
|
authorization:
|
||||||
|
type: Bearer
|
||||||
|
credentials: c213debe864061cefe501f7791d557b6dba701710b41791b4a4a0fb036690d1d
|
||||||
|
static_configs:
|
||||||
|
- targets: ['10.8.0.1:3903', '10.8.0.2:3903', '10.8.0.4:3903']
|
||||||
|
labels:
|
||||||
|
cluster: garage
|
||||||
|
|
||||||
|
# Health check for each node (returns 200 if quorum OK)
|
||||||
|
- job_name: 'garage_health'
|
||||||
|
metrics_path: /health
|
||||||
|
scheme: http
|
||||||
|
static_configs:
|
||||||
|
- targets: ['10.8.0.1:3903', '10.8.0.2:3903', '10.8.0.4:3903']
|
||||||
|
labels:
|
||||||
|
cluster: garage
|
||||||
|
|
||||||
|
# Node exporter on each host (system metrics)
|
||||||
|
- job_name: 'node'
|
||||||
|
static_configs:
|
||||||
|
- targets: ['10.8.0.2:9100']
|
||||||
|
labels:
|
||||||
|
host: bigbox
|
||||||
|
- targets: ['10.8.0.1:9100']
|
||||||
|
labels:
|
||||||
|
host: vps01
|
||||||
|
- targets: ['10.8.0.4:9100']
|
||||||
|
labels:
|
||||||
|
host: vps02
|
||||||
|
|
||||||
|
# Prometheus self
|
||||||
|
- job_name: 'prometheus'
|
||||||
|
static_configs:
|
||||||
|
- targets: ['localhost:9090']
|
||||||
Reference in New Issue
Block a user