feat(cluster): Logical Replication wird beim Join automatisch eingerichtet

Bisher war der zweite Node nach dem Join zwar im Cluster registriert und
in der UI sichtbar, replizierte aber keine einzige geteilte Tabelle —
dafuer musste jemand manuell `edgeguard-ctl cluster-setup-standby`
ausfuehren. Wer das uebersah, merkte es erst beim Failover: der neue
Primary stand ohne Domains, Backends, Firewall-Regeln und WireGuard-Keys
da. Das ist jetzt Teil des Join-Vorgangs.

Beide Seiten muessen dafuer vorbereitet sein:

1) Primary, beim Erzeugen des Join-Tokens: ein frisch installierter
   Single-Node hat weder Replikations-Rolle noch PUBLICATION noch
   wal_level=logical. Ohne das liefe das spaetere CREATE SUBSCRIPTION in
   ein 404. Der Token wird deshalb erst ausgegeben, nachdem die
   Publisher-Seite steht — inklusive des einmaligen PG-Restarts
   (wal_level ist ein postmaster-Parameter), der bewusst hier passiert,
   solange der Admin danebensteht und noch kein Peer Traffic erwartet.

   WICHTIG dabei: setupReplicationPrimary rotiert bei jedem Lauf das
   Replikations-Passwort (ALTER ROLE … PASSWORD). Auf einem Cluster mit
   bereits angebundenem Subscriber wuerde ein zweiter Token-Klick dessen
   Connection-String ungueltig machen und die Replikation still
   anhalten. Deshalb laeuft die Initialisierung nur, wenn PUBLICATION
   und Secret nicht bereits existieren.

2) Neuer Node, nach erfolgreichem Join: cluster-setup-standby laeuft
   detached (die Initialkopie dauert je nach Datenmenge Minuten), der
   Wizard pollt GET /setup/replication-status und zeigt running/done/
   failed an. Schlaegt es fehl, steht das manuelle Kommando inkl.
   Primary-Host direkt daneben statt nur einer Fehlermeldung.

Beides braucht root (psql als postgres, pg_hba, PG-Restart), die API
laeuft als unprivilegierter edgeguard → Aufruf via sudo mit gepinnten
Regeln. Das einzige variable Argument (Primary-Host) wird vorher gegen
Hostname/IP-Syntax geprueft; der Aufruf laeuft ohne Shell. Test dafuer
liegt bei.

Ausserdem zwei Doku-Korrekturen: architecture.md behauptete,
cluster-join richte die Replikation gleich mit ein (tut es nicht,
clusterjoin.Join macht nur Cert + Registrierung), und der Hinweistext
von cluster-join verwies noch auf "PG-Basebackup + KeyDB, Phase 3.5" —
beides laut Doku laengst verworfen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
noroot
2026-09-11 11:40:44 +02:00
parent bb19562bc1
commit 808f6fc055
10 changed files with 429 additions and 11 deletions

View File

@@ -339,7 +339,14 @@ curl -fsSL https://get.edgeguard.netcell-it.de | sudo bash -s -- \
--token <cluster-join-token>
```
`edgeguard-ctl cluster-join` führt aus: TLS-Cert-Pull via mTLS (CSR→issue-cert), Node-Registrierung in `ha_nodes` (`autoRegister`), Setup als **Logical-Replication-Subscriber** (`cluster-setup-standby`: `CREATE SUBSCRIPTION … copy_data=true`, Initialkopie der geteilten Tabellen), Config-Regeneration, Service-Start. _(Kein `pg_basebackup`, kein KeyDB-Setup — beides war nur im ursprünglichen Entwurf.)_
`edgeguard-ctl cluster-join` führt aus: TLS-Cert-Pull via mTLS (CSR→issue-cert) und Node-Registrierung in `ha_nodes` (`autoRegister`)**mehr nicht**. Die Logical Replication ist ein eigener Schritt (`cluster-setup-standby`: `CREATE SUBSCRIPTION … copy_data=true`, Initialkopie der geteilten Tabellen, Master-Key-Sync, Config-Regeneration). _(Kein `pg_basebackup`, kein KeyDB-Setup — beides war nur im ursprünglichen Entwurf.)_
**Join über den Setup-Wizard (empfohlener Weg) macht beides automatisch:**
1. Auf dem Primary erzeugt `POST /cluster/join-tokens` den Token — und stellt dabei vorher via `cluster-init-replication` sicher, dass die Publisher-Seite steht (Replikations-Rolle + Secret, `wal_level=logical`, `pg_hba`, PUBLICATION). Ein frisch installierter Single-Node hat das alles noch nicht; ohne diesen Schritt liefe das spätere `CREATE SUBSCRIPTION` in ein 404. Idempotent; der einmalige PG-Restart (`wal_level` ist ein postmaster-Parameter) passiert bewusst hier, solange noch kein zweiter Node Traffic erwartet.
2. Auf dem neuen Node startet `POST /setup/join-cluster` nach erfolgreichem Join `cluster-setup-standby` detached (via `sudo`, da root nötig). Fortschritt pollbar über `GET /setup/replication-status` (`running`/`done`/`failed`); der Wizard zeigt ihn an und gibt bei Fehlschlag das manuelle Kommando aus.
Der reine CLI-Pfad (`cluster-join`) bleibt der manuelle Weg und erfordert `cluster-setup-standby` weiterhin explizit.
---