feat: PostgreSQL als StatefulSet im Kubernetes-Cluster deployen
Backend Image / build-and-push (push) Successful in 3m8s
Frontend Image / build-and-push (push) Successful in 2m54s

Architektur-Entscheidung geaendert: PostgreSQL laeuft jetzt selbst im
Cluster statt auf einer bestehenden externen Instanz. Neu:
deploy/k8s/postgres/ mit StatefulSet (postgres:18-alpine,
volumeClaimTemplates, pg_isready-Probes), headless Service
(apicore-postgres) und Secret-Vorlage. Backend-DATABASE_URL zeigt auf
den neuen In-Cluster-Service. CLAUDE.md/ARCHITECTURE.md aktualisiert:
Backup-Verantwortung liegt jetzt beim Projekt, nicht mehr beim
externen Cluster-/DBA-Betrieb (Backup-CronJob als offener Punkt in
TASKS.md ergaenzt).
This commit is contained in:
Nick Szaunig committed 2026-08-26 17:43:49 +02:00
1 parent 41c82d7dc7
commit 80890a5fc3
7 files changed
+90 -5

No files matched your search

+5 -3
View File
@@ -101,14 +101,16 @@ Fachliche Annahmen, getroffen weil das Lastenheft an der Stelle keine eindeutige
`deploy/k8s/` enthält je Projekt: `deployment.yaml`, `service.yaml`, `ingress.yaml`, sowie `configmap.example.yaml` und `secret.example.yaml` (Platzhalter, keine echten Werte). Backend exponiert `GET /health` (liveness) und `GET /health/ready` (readiness, prüft DB-Verbindung). Beide Projekte je ein schlankes Multi-Stage-Dockerfile (Build-Stage mit vollem `node_modules`, Runtime-Stage mit `npm ci --omit=dev` bzw. Next.js `output: 'standalone'`).
`deploy/k8s/postgres/` enthält das PostgreSQL-`StatefulSet` (ein Replica, `volumeClaimTemplates` für persistente Daten, `postgres:18-alpine`), den zugehörigen headless `Service` (`apicore-postgres`, DNS-Name fürs Backend) sowie `secret.example.yaml` für `POSTGRES_USER`/`POSTGRES_PASSWORD`/`POSTGRES_DB`. `deploy/k8s/backend/secret.example.yaml`s `DATABASE_URL` zeigt auf diesen Service.
## 8. Backup & Restore
**Schema-Migrationen (Reproduzierbarkeit):** Ausschließlich `prisma/migrations/` als Quelle der Wahrheit. Lokal/Entwicklung: `npx prisma migrate dev`. Gegen jede Produktions- oder Staging-Datenbank ausschließlich `npx prisma migrate deploy` (idempotent, wendet nur fehlende Migrationen an, kein Schema-Drift). `prisma db push` wird an keiner Stelle im Code, in Skripten oder im Dockerfile verwendet und ist für Produktions-/Staging-Umgebungen untersagt. `migrate deploy` läuft als eigener Schritt vor dem Rollout (z. B. Kubernetes-`Job` oder manueller Schritt in der Deploy-Pipeline), nicht im `CMD` des Runtime-Images, damit mehrere Pod-Replicas nicht gleichzeitig Migrationen ausführen.
**Datensicherung:** Die PostgreSQL-Instanz selbst ist bestehende Cluster-Infrastruktur (siehe CLAUDE.md, "keine eigene DB-Infrastruktur"); Backup-Ausführung liegt beim Cluster-/DBA-Betrieb. Empfohlene Strategie dort:
**Datensicherung:** Seit der Entscheidung, PostgreSQL selbst im Cluster zu betreiben (siehe CLAUDE.md), liegt die Backup-Verantwortung bei diesem Projekt, nicht mehr bei einem externen Cluster-/DBA-Betrieb. Aktuell **noch nicht umgesetzt** (offener Punkt, siehe TASKS.md) – empfohlene Strategie:
- Tägliches logisches Backup via `pg_dump -Fc` (custom format, komprimiert, für `pg_restore` geeignet), Aufbewahrung nach Retention-Policy des Clusters.
- Kontinuierliches WAL-Archiving/PITR (Point-in-Time Recovery), falls vom Cluster unterstützt, für Wiederherstellung auf einen beliebigen Zeitpunkt zwischen den täglichen Dumps.
- Tägliches logisches Backup via `pg_dump -Fc` (custom format, komprimiert, für `pg_restore` geeignet), z. B. als Kubernetes-`CronJob` gegen den `apicore-postgres`-Service, Ablage auf einem separaten PVC oder Objektspeicher außerhalb des Postgres-eigenen Volumes.
- Kontinuierliches WAL-Archiving/PITR (Point-in-Time Recovery), falls die Storage-Class/das Backup-Tooling das unterstützt, für Wiederherstellung auf einen beliebigen Zeitpunkt zwischen den täglichen Dumps.
- Restore-Test: `pg_restore` eines Dumps in eine isolierte Datenbank, danach `npx prisma migrate deploy` zur Kontrolle, dass der Migrationsstand konsistent ist (`prisma migrate status`).
**Restore-Ablauf (Kurzfassung):** 1) Zielinstanz/-datenbank bereitstellen. 2) `pg_restore` (oder WAL-Replay bis zum Zielzeitpunkt bei PITR). 3) `npx prisma migrate status` prüfen. 4) `npx prisma migrate deploy` falls seit dem Dump neue Migrationen hinzugekommen sind. 5) `GET /health/ready` gegen die wiederhergestellte Instanz aufrufen, um DB-Erreichbarkeit zu bestätigen, bevor Verkehr umgeschaltet wird.