# Wabenhain in Kubernetes Rohe Manifeste, mit `kubectl apply -f k8s/` einzeln oder als Ordner anwendbar. Nummerierung = empfohlene Reihenfolge. ## Einmalige Vorbereitung 1. **Gitea Actions**: `.gitea/workflows/docker-build.yml` baut bei jedem Push auf `main` zwei Image-Tags in der Gitea-Container-Registry: - `//wabenhain:latest` (+ `:sha-`, `:vX.Y.Z` bei Tags) — das schlanke Laufzeit-Image fuer `05-app-deployment.yaml`. - `//wabenhain:migrate-` — enthaelt zusaetzlich die Prisma-CLI/tsx, fuer `04-migrate-job.yaml`. Voraussetzung: ein Repo-/Org-Secret `REGISTRY_TOKEN` in Gitea anlegen (Personal Access Token mit `package`-Scope, unter Benutzereinstellungen → Anwendungen → Access Tokens erzeugen, dann unter Repo-Einstellungen → Actions → Secrets als `REGISTRY_TOKEN` hinterlegen). Der automatisch von Gitea Actions bereitgestellte `GITEA_TOKEN` reicht dafuer aktuell NICHT aus (fehlendes Package-Write-Recht, Stand heute). 2. **Ein Docker-Image ist Provider-uebergreifend**: Prisma generiert den Client Provider-spezifisch — ein `.next/standalone`-Build kann seinen generierten Client nicht zur Laufzeit wechseln. Deshalb generiert `scripts/generate-prisma-clients.mjs` (Teil von `pnpm build`, laeuft also automatisch bei jedem Image-Build) BEIDE Varianten ins selbe Image; die Wahl zwischen ihnen passiert zur Laufzeit ueber `DATABASE_PROVIDER`, siehe `src/lib/prisma.ts`. Ein Image reicht also fuer Postgres UND MySQL — nur `DATABASE_PROVIDER`/`DATABASE_URL` in `01-configmap.yaml`/ `02-secret.yaml` muessen zur tatsaechlich gewaehlten Datenbank passen. 3. `k8s/02-secret.example.yaml` nach `k8s/02-secret.yaml` kopieren (per `.gitignore` ausgeschlossen — NIE mit echten Werten committen) und ausfuellen. Alternativ direkt per `kubectl create secret`, siehe Kommentar in der Beispieldatei. 4. `01-configmap.yaml`: `DATABASE_PROVIDER` (postgresql/mysql) und `NEXT_PUBLIC_SITE_URL` (echte Domain) anpassen. 5. In `04-migrate-job.yaml` und `05-app-deployment.yaml` die `image:`-Platzhalter (`git.example.com/OWNER/wabenhain:...`) durch die tatsaechliche Registry/Owner/Tag aus Schritt 1 ersetzen. In `06-ingress.yaml` `shop.example.com` durch die echte Domain ersetzen (zweimal: `host:` und `tls.hosts`). ## Deployment ```bash kubectl apply -f k8s/00-namespace.yaml kubectl apply -f k8s/01-configmap.yaml kubectl apply -f k8s/02-secret.yaml # Nur EINE der beiden Datenbanken anwenden, passend zu DATABASE_PROVIDER: kubectl apply -f k8s/03-postgres.yaml # kubectl apply -f k8s/03-mysql.yaml kubectl wait --for=condition=ready pod -l app=wabenhain-postgres -n wabenhain --timeout=120s # Migrationen + Seed (Admin-Konto, Beispieldaten) — vor jedem neuen # Image-Tag erneut ausfuehren: kubectl delete job wabenhain-migrate -n wabenhain --ignore-not-found kubectl apply -f k8s/04-migrate-job.yaml kubectl wait --for=condition=complete job/wabenhain-migrate -n wabenhain --timeout=120s kubectl apply -f k8s/05-app-deployment.yaml kubectl apply -f k8s/06-ingress.yaml ``` ## Bei einem neuen Image (Redeploy) ```bash kubectl delete job wabenhain-migrate -n wabenhain --ignore-not-found kubectl apply -f k8s/04-migrate-job.yaml kubectl wait --for=condition=complete job/wabenhain-migrate -n wabenhain --timeout=120s kubectl rollout restart deployment/wabenhain-app -n wabenhain ``` ## Bekannte Grenzen dieser Manifeste - **`replicas: 1`** in `05-app-deployment.yaml`, bewusst nicht mehr: das Login-/2FA-/Checkout-Rate-Limiting (`lib/rate-limit.ts`) haelt seinen Zustand im Prozessspeicher, nicht in einem gemeinsamen Store. Mehrere Replicas wuerden das Limit unbemerkt proportional aufweichen. Fuer horizontale Skalierung zuerst `lib/rate-limit.ts` auf Redis o.ae. umstellen. - Kein `HorizontalPodAutoscaler`, kein `PodDisruptionBudget`, keine `NetworkPolicy` — je nach Cluster/Anforderungen ergaenzen. - Die Postgres-/MySQL-StatefulSets sind Single-Instance ohne Replikation/ Backup-Automation. Fuer produktiven Betrieb einen Managed-Datenbank-Dienst oder einen dedizierten DB-Operator (z.B. CloudNativePG) in Erwaegung ziehen — `DATABASE_URL` in `02-secret.yaml` einfach auf den externen Endpunkt zeigen lassen, `03-postgres.yaml`/`03-mysql.yaml` dann nicht anwenden.