5.8 KiB
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_worldwscripts/observer/observer.py:312-323+ neutralizacja event-driven flipów:438-446— a NIE odłączanie rury. Fizycznie nic nie znika. node_healthwozi też metryki disk/mem/cpu do panelu idisk_pressuredo 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.jsonwyłączniedisk_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)", eventowynode_healthmierzy "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:
- Firing w Prometheusie:
/api/v1/alerts→AlertTestEtap0firing, node vps. - 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. - Alert doleciał na Telegram (@okitaialerts_bot): „Prometheus alert: AlertTestEtap0, Node: vps, Summary: …".
- 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 polaprom_*wnodes.json, loguje rozbieżności, NIC nie przełącza (parallel-run, fail-open). Realna zmiana wobserver.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ącecompute_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/— toscripts/observer/observer.py- wydzielona maszyna stanów
liveness.pyimportowana przez trzy konsumentów. Bez reconu plan cutoveru celowałby w złe miejsce.
- wydzielona maszyna stanów
- 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).