feat: Backend migriert die Datenbank beim Start selbst statt ueber Job
Kein separater Kubernetes-Job mehr. Dockerfile-CMD fuehrt jetzt `npm run migrate:deploy` aus, bevor `node dist/main.js` startet - Tabellen werden beim ersten Verbinden automatisch angelegt. Sicher bei mehreren gleichzeitig startenden Pod-Replicas (replicas: 2), da Prisma migrate deploy einen DB-seitigen Advisory-Lock nutzt. deployment.yaml bekommt eine startupProbe (failureThreshold 30 x periodSeconds 10 = bis zu 5 Min), damit liveness/readiness den Container waehrend der Migration nicht neu starten. ARCHITECTURE.md entsprechend aktualisiert, migrate-job.yaml entfernt.
This commit is contained in:
1 parent
a6e5b0331f
commit
76a9e9c3a4
4 files changed
+18
-31
No files matched your search
+1
-1
@@ -105,7 +105,7 @@ Fachliche Annahmen, getroffen weil das Lastenheft an der Stelle keine eindeutige
|
|||||||
|
|
||||||
## 8. Backup & Restore
|
## 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, nicht im `CMD` des Runtime-Images, damit mehrere Pod-Replicas nicht gleichzeitig Migrationen ausführen: `deploy/k8s/backend/migrate-job.yaml` ist ein Kubernetes-`Job`, der dasselbe Backend-Image mit überschriebenem `command` (`npm run migrate:deploy`) nutzt – kein separates Migrations-Image. Reihenfolge und `kubectl`-Befehle stehen als Kommentar in der Datei.
|
**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. Der Backend-Container führt `migrate deploy` selbst beim Start aus, bevor der Server Verbindungen annimmt (Dockerfile-`CMD`: `npm run migrate:deploy && node dist/main.js`) – kein separater Kubernetes-`Job`. Bei `replicas: 2` starten mehrere Pods potenziell gleichzeitig; das ist unproblematisch, da Prisma für `migrate deploy` einen datenbankseitigen Advisory-Lock nutzt – eine Instanz wendet die Migrationen an, die anderen warten kurz und finden danach nichts mehr zu tun. `deploy/k8s/backend/deployment.yaml` hat dafür eine `startupProbe` mit großzügigem `failureThreshold`, damit liveness/readiness den Container nicht neu starten, während die (beim allerersten Deploy ggf. länger laufende) Migration noch durchläuft.
|
||||||
|
|
||||||
**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:
|
**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:
|
||||||
|
|
||||||
|
|||||||
@@ -16,11 +16,14 @@ RUN npm ci --omit=dev
|
|||||||
COPY --from=builder /app/dist ./dist
|
COPY --from=builder /app/dist ./dist
|
||||||
COPY --from=builder /app/generated ./generated
|
COPY --from=builder /app/generated ./generated
|
||||||
# schema.prisma, migrations/ und prisma.config.ts: noetig fuer
|
# schema.prisma, migrations/ und prisma.config.ts: noetig fuer
|
||||||
# `npm run migrate:deploy` (siehe deploy/k8s/backend/migrate-job.yaml), das
|
# `npm run migrate:deploy`, das der Container beim Start selbst ausfuehrt
|
||||||
# dasselbe Image mit ueberschriebenem command nutzt statt eines eigenen
|
# (siehe CMD unten), bevor der Server Verbindungen annimmt.
|
||||||
# Migrations-Images.
|
|
||||||
COPY --from=builder /app/prisma ./prisma
|
COPY --from=builder /app/prisma ./prisma
|
||||||
COPY --from=builder /app/prisma.config.ts ./prisma.config.ts
|
COPY --from=builder /app/prisma.config.ts ./prisma.config.ts
|
||||||
EXPOSE 3001
|
EXPOSE 3001
|
||||||
USER node
|
USER node
|
||||||
CMD ["node", "dist/main.js"]
|
# migrate deploy ist idempotent und nutzt einen DB-seitigen Advisory-Lock,
|
||||||
|
# daher unproblematisch bei mehreren gleichzeitig startenden Pod-Replicas:
|
||||||
|
# eine Instanz wendet die Migrationen an, die anderen warten kurz und finden
|
||||||
|
# danach nichts mehr zu tun.
|
||||||
|
CMD ["sh", "-c", "npm run migrate:deploy && node dist/main.js"]
|
||||||
@@ -24,6 +24,16 @@ spec:
|
|||||||
name: apicore-backend-config
|
name: apicore-backend-config
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: apicore-backend-secret
|
name: apicore-backend-secret
|
||||||
|
# Container fuehrt beim Start selbst `prisma migrate deploy` aus,
|
||||||
|
# bevor der Server Verbindungen annimmt (siehe Dockerfile CMD) -
|
||||||
|
# startupProbe gibt dafuer bis zu 5 Minuten Zeit, ohne dass
|
||||||
|
# liveness/readiness in der Zwischenzeit einen Neustart ausloesen.
|
||||||
|
startupProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health/ready
|
||||||
|
port: 3001
|
||||||
|
failureThreshold: 30
|
||||||
|
periodSeconds: 10
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /health
|
path: /health
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
# Job statt Teil des Deployment-CMD: laeuft einmalig vor dem Rollout, damit
|
|
||||||
# nicht mehrere Backend-Pod-Replicas gleichzeitig Migrationen ausfuehren
|
|
||||||
# (siehe ARCHITECTURE.md Abschnitt 8). Jobs sind unveraenderlich, daher vor
|
|
||||||
# jedem Deploy mit neuem Image-Tag zuerst loeschen:
|
|
||||||
#
|
|
||||||
# kubectl delete job apicore-backend-migrate --ignore-not-found
|
|
||||||
# kubectl apply -f deploy/k8s/backend/migrate-job.yaml
|
|
||||||
# kubectl wait --for=condition=complete job/apicore-backend-migrate --timeout=120s
|
|
||||||
# kubectl apply -f deploy/k8s/backend/deployment.yaml
|
|
||||||
apiVersion: batch/v1
|
|
||||||
kind: Job
|
|
||||||
metadata:
|
|
||||||
name: apicore-backend-migrate
|
|
||||||
spec:
|
|
||||||
backoffLimit: 2
|
|
||||||
ttlSecondsAfterFinished: 3600
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
restartPolicy: Never
|
|
||||||
containers:
|
|
||||||
- name: migrate
|
|
||||||
image: git.encry.de/nick.rosenloecher/apicore-backend:latest
|
|
||||||
command: ["npm", "run", "migrate:deploy"]
|
|
||||||
envFrom:
|
|
||||||
- secretRef:
|
|
||||||
name: apicore-backend-secret
|
|
||||||
Reference in new issue
Block a user