homelab-codex-ws/docs/sessions/2026-07-06.md
oskar f0522a85dc feat(kb): frontmatter OKF dla 39 session logow
Session logi zostaja w docs/sessions/ (decyzja z etapu 1). Dodany wylacznie
blok frontmattera: type: session-log, visibility: private, status: active,
updated = data ostatniego commita pliku.

Tresc nietknieta — kazdy plik to +9/-0 linii.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 16:53:57 +02:00

116 lines
5.9 KiB
Markdown

---
okf: "0.1"
type: session-log
visibility: private
status: active
updated: 2026-07-06
links: []
---
# Sesja 2026-07-06 — cutover liveności na Prometheus: recon starego toru + Etap 0 udowodniony w boju
## Cel
Główny projekt: Prometheus jako źródło prawdy liveności floty. Dwa kroki tej sesji:
(1) read-only recon starego toru liveności z dokładnymi punktami przełączenia
i planem etapowym; (2) Etap 0 cutoveru — bojowy dowód end-to-end toru
Prometheus → brain-watchdog → Telegram, którego brakowało od 2026-06-30.
---
## ZROBIONE
### Recon cutoveru — wmergowany (commit `d94bb38`)
Wynik: `docs/infra/prometheus-cutover-recon-2026-07-06.md` (517 linii, read-only,
zero zmian w kodzie). Kluczowe ustalenia:
- **Cutover to podmiana klasyfikacji liveności w JEDNYM miejscu** —
`_prune_stale_world` w `scripts/observer/observer.py:312-323` + neutralizacja
event-driven flipów `:438-446` — a NIE odłączanie rury. Fizycznie nic nie znika.
- **`node_health` wozi też metryki** disk/mem/cpu do panelu i `disk_pressure`
do supervisora → rsync + eventy ZOSTAJĄ w całości.
- **Supervisor-remediacja i executor są CAŁKOWICIE niezależne od liveności węzłów**
— supervisor czyta z `nodes.json` wyłącznie `disk_pressure`. Jedyny konsument
liveności po stronie supervisora to syntetyczne eventy przejść
(`node_offline/stale/online` → alert_only → Telegram).
- **Różnica semantyk**: `up{}` mierzy "host żyje (exporter odpowiada)",
eventowy `node_health` mierzy "node-agent żyje + cały łańcuch SSH/rsync działa".
Cutover ZWĘŻA definicję liveności — padnięty node-agent przy żywym węźle zmienia
werdykt. Do świadomej akceptacji w etapie 2; rozważyć `up{job=node-agent}`.
- **chelsty-infra ma liveność WYŁĄCZNIE z eventów** (Prometheus go nie scrape'uje
po LTE) → cutover MUSI być per-węzeł (`PROM_LIVENESS_NODES`), nigdy globalny.
- **Prometheus po cutoverze = niepilnowany SPOF** (`mem_limit 512m`,
`oom_score_adj 200` — ubijalny przed control-plane) → fail-open na stary tor
obowiązkowy + watchdog na sam Prometheus (mały task przy etapie 3).
- Exportery piha/solaria/lustro istnieją **poza GitOps** (brak definicji w repo)
— rozjazd, osobny wątek.
### Etap 0 cutoveru — DONE, dowód bojowy end-to-end
Tor **Prometheus → brain-watchdog → Telegram udowodniony END-TO-END po raz
pierwszy w produkcji**. Test punktowy na VPS (celowo NIE w repo): tymczasowa
reguła `AlertTestEtap0` (`up{node="vps"}==1`, `for: 0s`) dodana do
`services/fleet-prometheus/rules/` na VPS + reload. Cztery punkty potwierdzenia:
1. **Firing w Prometheusie**: `/api/v1/alerts``AlertTestEtap0` firing, node vps.
2. **Watchdog spollował z PIHA**: log `[prometheus] sent alert: AlertTestEtap0:vps`
— przy okazji widoczne dwa niezależne tory (ping mózgu OK co 60 s + poll
Prometheusa osobno), zgodnie z architekturą A.
3. **Alert doleciał na Telegram** (@okitaialerts_bot): „Prometheus alert:
AlertTestEtap0, Node: vps, Summary: …".
4. **Rollback czysty**: reguła usunięta, reload, firing=0.
Zamyka pending z 2026-06-30 („czy watchdog realnie polluje" — recon 2026-07-02
potwierdził konfigurację, dziś potwierdzone działanie end-to-end). Reguła testowa
NIE trafiła do repo — to diagnostyka, nie architektura; katalog `rules/` ma
nadal tylko `liveness.yml`.
### Realny dowód „czemu cutover" — chelsty NOMINAL-zonk
Panel agents.okit.pl pokazuje **chelsty NOMINAL + Runtime online, mimo że chelsty
jest OFFLINE od 34 dni** (`tailscale status`). U wszystkich węzłów: Last Seen
„Invalid Date", Connectivity/Incidents `undefined`, a status NOMINAL — observer
NIE egzekwuje świeżości `last_seen` (bug TTL wraca, patrz backlog „Observer
staleness"). Cutover na Prometheus `up{}` to naprawia: chelsty nie-scrape'owany →
down, nie fałszywie NOMINAL.
Snapshot panelu potwierdził też dwa zaległe drobiazgi (dopisane do backlogu):
- **Ghosty B wróciły/nieposprzątane** — hash-prefixed kontenery control-plane
widoczne na VPS (wpis „zniknęły" z 2026-07-02 zdezaktualizowany).
- **elasticsearch + diskover w stanie error na PIHA** — usunięte w module 0
(2026-07-02), ale observer wciąż je zna i raportuje.
---
## PLAN — następne etapy cutoveru (osobne sesje)
- **Etap 1 — shadow-read**: observer czyta OBA źródła (eventy I Prometheus
`up{}`), pisze nienaruszające pola `prom_*` w `nodes.json`, loguje rozbieżności,
NIC nie przełącza (parallel-run, fail-open). Realna zmiana w
`observer.py:312-323` → worktree/CC.
- **Etap 2 — analiza**: ≥ 7 dni zgodności → klasyfikacja rozbieżności
(semantyka vs bug) → decyzja mappingu (rekomendacja: `timestamp(up)` jako
prom-last_seen przez istniejące `compute_liveness`).
- **Etap 3 — przełączenie per-węzeł** za flagą `PROM_LIVENESS_NODES`:
najpierw solaria+lustro (najmniejsza szkoda przy pomyłce), potem vps+piha.
**chelsty-infra ZOSTAJE na eventach.** Rollback = wyczyszczenie flagi.
---
## Wnioski
- **Etap 0 zamknął fundamentalną niepewność wiszącą od 2026-06-30**: „czy tor
alertowy Prometheus→watchdog→Telegram w ogóle działa" przestało być wnioskowaniem
z konfiguracji (recon 2026-07-02), a stało się faktem dowiedzionym w produkcji.
Dalsze etapy cutoveru budują na sprawdzonym fundamencie, nie na założeniu.
- **verify-before-fix w reconie obalił założenie architektoniczne**: observer NIE
jest jednym modułem w `services/control-plane/src/` — to `scripts/observer/observer.py`
+ wydzielona maszyna stanów `liveness.py` importowana przez trzy konsumentów.
Bez reconu plan cutoveru celowałby w złe miejsce.
- **Test punktowy (reguła for:0s + rollback) to tani sposób na dowód bojowy toru
alertowego** — bez czekania na realną awarię i bez commitowania diagnostyki do repo.
- Hashe sesji: `d94bb38` (recon cutoveru); Etap 0 = czynność operatorska na
runtime (bez commitu, zgodnie z planem z reconu).