diff --git a/docs/sessions/2026-06-22.md b/docs/sessions/2026-06-22.md new file mode 100644 index 0000000..a41516f --- /dev/null +++ b/docs/sessions/2026-06-22.md @@ -0,0 +1,131 @@ +# Sesja 2026-06-22 — decyzja: Prometheus jako źródło prawdy dla liveness floty + +## Cel + +Rozstrzygnięcie architektoniczne: czym zastąpić obecną rurę wykrywania liveness +floty `node-agent → rsync/ssh → observer` (warstwa sensoryczno-transportowa będąca +przyczyną większości nawracających awarii). Plus precondition infrastrukturalny pod +nowy serwis na VPS (swap). + +--- + +## DECYZJA: Prometheus (pull, `up{}`) zastępuje WYKRYWANIE liveness + +### Co zastępujemy (warstwa sensoryczno-transportowa) + +Prometheus pull + metryka `up{}` przejmuje rolę dotychczasowej rury: +- **node-agent** jako shipper eventów, +- **rsync/ssh** transport, +- pliki eventów, +- observer **prune/checkpoint**, +- egzekwowanie **TTL** liveness. + +To była przyczyna większości nawracających awarii: +- `uid 1004 != 1000` — strict ownership check OpenSSH wywalał shipping, +- ślepy ssh-mount (LUSTRO, `/root/.ssh` vs `/home/homelab/.ssh`), +- bloat (~242k eventów na VPS), +- race `prune` ↔ `checkpoint` w observerze, +- `NOMINAL`-bez-TTL (martwy node pokazywany jako zdrowy). + +Pull eliminuje całą warstwę push: brak kluczy, brak ownership, brak event-store +do prune'owania, brak ręcznego TTL — `up==0` przez czas `for:` jest stanem prawdy. + +### Świadoma granica zakresu — co ZOSTAJE + +Prometheus zastępuje **wykrywanie**, NIE cały system. Nietknięte: +- **supervisor** — remediacja (`container_restart` / `redeploy`), +- **observer / panel** `agents.okit.pl` — do przepięcia na źródło Prometheus (OTWARTE, + największy znak zapytania przy cutoverze), +- **ha-diag-agent** — logika domenowa HA (diff `system_health`, encje `unavailable`, + WS heartbeat) — Prometheus tego nie widzi, +- historia incydentów / lifecycle, +- out-of-band watchdog. + +### BEZ Alertmanagera — świadoma decyzja + +Jeden kanał Telegram (`@okitaialerts_bot`). Rolę dostarczania przejmuje **brain-watchdog**: +dochodzi mu **drugie wejście** — odpytanie Prometheus `/api/v1/alerts` — obok obecnego +pingu mózgu. Reguły alertowe z histerezą (`for:`) po stronie Prometheusa; watchdog +pozostaje cienki (odczyt `firing` + Telegram). Nie wprowadzamy osobnego Alertmanagera, +żeby nie mnożyć kanałów ani komponentu do utrzymania. + +> Uwaga: ta decyzja **zastępuje** wcześniejszy szkic z sesji 2026-06-17 +> (blackbox_exporter + Alertmanager). Wybrano pull `up{}` + watchdog jako tor alertu. + +--- + +## Osobny fleet-Prometheus pod GitOps — NIE adopcja domowego instance + +Stawiamy **osobny** Prometheus floty, zarządzany przez GitOps. NIE adoptujemy domowego +instance na PIHA. + +Powód — domowy prom na PIHA to liability nie wart adopcji: +- LAN-only (scrape `192.168.31.x`), mija nody tylko-Tailscale (VPS, chelsty), +- poza repo (`/home/pi/monitoring/prometheus.yml`, konfigurowany ręcznie), +- bez alertingu (`alerting:` i `rule_files:` puste), +- sekrety plaintext w configu (long-lived token HAOS + bearer watchtower — do rotacji). + +Adopcja = dziedziczenie liability (migracja, ekstrakcja sekretów) **plus** blast-radius +na działający monitoring bezpieczeństwa domu (crowdsec / fail2ban / haos) za znikomą +wygraną. Osobny instance izoluje flotę od domu. + +## Placement: VPS + +- Host: VPS (`ubuntu-4gb-hel1-1`, `100.95.58.48`). +- Out-of-band zachowane: **watchdog na PIHA pilnuje VPS z innej maszyny** — Prometheus + na VPS nie jest sędzią własnej śmierci. +- VPS ma już `node_exporter` (role: metrics-exporter) = pierwszy target floty gotowy. + +--- + +## ZROBIONE w tej sesji + +### Swap 4 GB na VPS — precondition pod Prometheusa + +- `/swapfile` aktywny i **trwały** (wpis w `/etc/fstab`). +- `vm.swappiness=10` ustawione na żywo i w `/etc/sysctl.conf`. +- **Weryfikacja**: `free -h` → `Swap: 4.0Gi (0B used)`; `/proc/swaps` zawiera `/swapfile`. +- Powód: VPS ma 3.7 GB RAM, wcześniej `swap=0` — przyczyna OOM 2026-06-01. Prometheus + jest RAM-głodny; swap to bufor bezpieczeństwa. +- ⚠️ To **host-level one-off** — nie czysto GitOps-owalne, wykonane świadomie gotowcem. + Zapisane jako celowy host-state w `hosts/vps/host.yaml`, żeby przy odtwarzaniu VPS + nie zniknęło cicho (wzorzec jak uid/grupy po 8-dniowej awarii). + +--- + +## Plan następnych kroków (OTWARTE — NIE realizowane w tej sesji) + +Kolejność = priorytet: + +1. **Scaffold serwisu `fleet-prometheus` pod GitOps** — worktree `task/fleet-prometheus`, + wzorzec `services/vikunja/`: `docker-compose.yml` + `env.example` + `service.yaml` + + `README.md` + `healthcheck.sh`. Rejestracja w `hosts/vps/services.yaml` + + `inventory/topology.yaml`. Exposure: `tailscale-internal`. Pusty scrape na start + (self + lokalny `node_exporter` VPS). +2. **Inwentaryzacja nodów floty `100.x`** do scrape (osobny krok). +3. **Container-layer exporter** (cAdvisor lub lekki docker-state) — brakujący klocek; + `node_exporter` nie widzi kontenerów. +4. **Reguły liveness** (`up==0 for: 5m`) w Prometheusie. +5. **brain-watchdog: drugie wejście** — odpyt Prometheus `firing` → Telegram, bez + ruszania działającego toru `token → chat_id`. +6. **Rotacja tokenu HAOS** w domowym prom (plaintext). +7. **Przepięcie observer / panel `agents.okit.pl`** na Prometheus jako źródło — + największy znak zapytania przy cutoverze. +8. **Parallel-run** obok rury eventowej; **cutover dopiero** gdy Prometheus-truth się + udowodni. + +--- + +## Wnioski + +- Klasa awarii (push shipping: klucze, ownership, bloat, race, TTL) znika nie przez + kolejny fix, lecz przez zmianę modelu transportu na **pull** — Prometheus widzi + martwy target jako `up==0`, bez warstwy dostarczania do zepsucia. +- Granica zakresu trzymana świadomie: Prometheus = **wykrywanie**, nie remediacja ani + logika domenowa HA. Zastępujemy sensor, nie mózg. +- Osobny instance > adopcja: nie dziedziczy się liability ani blast-radius na monitoring + bezpieczeństwa domu dla wygody współdzielenia. +- BEZ Alertmanagera: cienki watchdog z drugim wejściem zamiast nowego komponentu — + jeden kanał Telegram pozostaje jeden. +- Swap = precondition, nie cel — odblokowuje RAM-ciasny VPS pod nowy serwis; + udokumentowany jako celowy host-state, nie ukryta ręczna zmiana.