refactor(k8s): minimale, flache Manifeste zum Kopieren
Kustomize-Struktur (base/overlays) entfernt. Stattdessen nummerierte Einzeldateien, ausrollbar mit "kubectl apply -f k8s/": 00-namespace, 01-config, 02-storage (SMB-PVs/PVCs Postgres + Medien), 03-postgres (StatefulSet + Service), 04-app (Deployment mit Migrations-initContainer + Service), 05-ingress, 06-worker, 07-networkpolicy. Secrets als secrets.yaml.example (echte secrets.yaml ist gitignored). Images mit Tag latest aus der Gitea-Pipeline. Kurzanleitung in k8s/README.md, Betriebsdoku angepasst. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
c84eb1e740
commit
91791b791f
20 files changed
+332
-494
No files matched your search
+12
-28
@@ -11,13 +11,13 @@ Einmalig einrichten:
|
||||
- ein Personal Access Token mit Scope `package` als Repo-Secret `REGISTRY_TOKEN` hinterlegen (Repo-Einstellungen → Actions → Secrets)
|
||||
- einen Runner mit dem Label `docker-builder` bereitstellen (wie bei Wabenhain)
|
||||
|
||||
Ein Release entsteht dann so: `git tag v0.1.0 && git push origin v0.1.0`, anschließend den Tag im Overlay setzen.
|
||||
Die Manifeste in `k8s/` nutzen den Tag `latest`. Für feste Versionen dort `:latest` durch z. B. `:0.1.0` ersetzen (`git tag v0.1.0 && git push origin v0.1.0`).
|
||||
|
||||
**Manuell:**
|
||||
|
||||
```bash
|
||||
docker build --target runner -t git.encry.de/nick.rosenloecher/artista-modelcamp:0.1.0 .
|
||||
docker build --target tools -t git.encry.de/nick.rosenloecher/artista-modelcamp-tools:0.1.0 .
|
||||
docker build --target runner -t git.encry.de/nick.rosenloecher/artista-modelcamp:latest .
|
||||
docker build --target tools -t git.encry.de/nick.rosenloecher/artista-modelcamp-tools:latest .
|
||||
docker push … # beide Images, immer mit identischem Tag
|
||||
```
|
||||
|
||||
@@ -32,39 +32,23 @@ Der Build braucht Internet für `next/font` (Schriften werden eingebettet), aber
|
||||
|
||||
Eine eigene Sicherung im Cluster gibt es nicht, die SMB-Freigabe wird auf dem NAS gesichert.
|
||||
|
||||
1. **Namespace:** `kubectl create namespace artista` und `kubectl label namespace artista pod-security.kubernetes.io/enforce=restricted`
|
||||
2. **Overlay anpassen** (`k8s/overlays/production/`): Image-Tag, Domain in `kustomization.yaml` (APP_URL) und `ingress.yaml`, `ingressClassName` (`kubectl get ingressclass`), ClusterIssuer (Beispiel `letsencrypt-prod`) und TLS-Secret-Name. Die HTTP→HTTPS-Umleitung erwartet das Manifest in Traefik selbst.
|
||||
3. **SMB-Speicher** (`k8s/overlays/production/smb-volumes.yaml`):
|
||||
1. csi-driver-smb installieren, Befehl steht im Kopf der Datei.
|
||||
2. Auf dem NAS die Ordner `modelcamp-postgres` (leer) und `modelcamp-media` anlegen und `source` in der Datei anpassen.
|
||||
3. SMB-Secret anlegen: `kubectl -n artista create secret generic artista-modelcamp-smb --from-literal=username='…' --from-literal=password='…'`. Empfohlen ist ein eigener NAS-Benutzer, der nur diese Ordner sieht.
|
||||
4. Das NAS muss SMB 3.1.1 mit Verschlüsselung erlauben (`seal`), z. B. Synology unter „SMB-Verschlüsselung für Übertragung“, Windows mit `Set-SmbShare -EncryptData $true`.
|
||||
**Schritt für Schritt zum Kopieren: [k8s/README.md](../k8s/README.md).** Die Manifeste liegen flach in `k8s/` (`00-…` bis `07-…`) und werden mit `kubectl apply -f k8s/` ausgerollt. Die Secrets kommen aus `k8s/secrets.yaml.example` und werden nicht eingecheckt.
|
||||
|
||||
Die Rechte setzen die `mountOptions`, auf SMB wirkt `fsGroup` nicht: Postgres `uid=70`, `0700`/`0600`; Medien `uid=1001`, für die App nur lesbar (`0550`/`0440`).
|
||||
|
||||
**PostgreSQL auf SMB ist eine bewusste Ausnahme.** SMB garantiert Sperren und fsync nicht in jedem Fall wie ein lokales Dateisystem. Bei einem NAS- oder Netzwerkausfall während Schreibvorgängen kann die Datenbank beschädigt werden. Gemildert wird das durch `hard`, `cache=strict`, Verschlüsselung und ein 120 Sekunden langes, sauberes Herunterfahren. Die NAS-Sicherung ist nur mit **atomaren Snapshots** der Freigabe (Btrfs/ZFS) konsistent. Ein Dateikopie-Backup eines laufenden Datenverzeichnisses lässt sich nicht zuverlässig wiederherstellen. Zusätzlicher Schutz bei Bedarf: gelegentlich einen `pg_dump` ziehen (Abschnitt 7).
|
||||
4. **Secret anlegen:** Befehl steht in `k8s/secret.example.yaml`, besser über Sealed Secrets oder den External Secrets Operator.
|
||||
5. **Anwenden:** `kubectl apply -k k8s/overlays/production`. Der initContainer migriert die Datenbank vor dem App-Start.
|
||||
6. **Erstes Admin-Konto:**
|
||||
```bash
|
||||
kubectl -n artista run admin-create --rm -it --restart=Never --labels=artista/db-client=true \
|
||||
--image=git.encry.de/nick.rosenloecher/artista-modelcamp-tools:0.1.0 \
|
||||
--overrides='{"spec":{"containers":[{"name":"admin-create","image":"git.encry.de/nick.rosenloecher/artista-modelcamp-tools:0.1.0","command":["tsx","scripts/create-admin.ts","--email","[email protected]","--name","Dein Name"],"envFrom":[{"configMapRef":{"name":"artista-modelcamp-config"}},{"secretRef":{"name":"artista-modelcamp-secrets"}}]}]}}'
|
||||
```
|
||||
Das einmalige Passwort wird ausgegeben. Bei der ersten Anmeldung unter `/admin` wird die 2FA eingerichtet.
|
||||
Zu PostgreSQL:
|
||||
- **PostgreSQL auf SMB ist eine bewusste Ausnahme.** SMB garantiert Sperren und fsync nicht in jedem Fall wie ein lokales Dateisystem. Bei einem NAS- oder Netzwerkausfall während Schreibvorgängen kann die Datenbank beschädigt werden.
|
||||
- **Gemildert** wird das durch `hard`, `cache=strict`, SMB-Verschlüsselung (`seal`) und ein 120 Sekunden langes, sauberes Herunterfahren. Die Rechte setzen die `mountOptions`, weil `fsGroup` auf SMB nicht wirkt: Postgres `uid=70`, `0700`; Medien `uid=1001`, nur lesbar.
|
||||
- **Sicherung:** Die NAS-Sicherung ist für die laufende Datenbank nur mit **atomaren Snapshots** der Freigabe (Btrfs/ZFS) konsistent. Zusätzlicher Schutz bei Bedarf: gelegentlich einen `pg_dump` ziehen (Abschnitt 7).
|
||||
|
||||
## 3. Update ausrollen
|
||||
|
||||
```bash
|
||||
# Neuen Tag im Overlay setzen und anwenden. Jeder neue App-Pod migriert per
|
||||
# initContainer "migrate" zuerst die Datenbank; scheitert das, startet er nicht
|
||||
# und die alten Pods bleiben aktiv (maxUnavailable: 0).
|
||||
kubectl apply -k k8s/overlays/production
|
||||
kubectl -n artista rollout restart deploy/artista-modelcamp-app
|
||||
kubectl -n artista rollout status deploy/artista-modelcamp-app
|
||||
# Migrationsausgabe bei Bedarf:
|
||||
kubectl -n artista logs deploy/artista-modelcamp-app -c migrate
|
||||
kubectl -n artista logs deploy/artista-modelcamp-app -c migrate # Migrationsausgabe
|
||||
```
|
||||
|
||||
Jeder neue App-Pod migriert per initContainer zuerst die Datenbank. Scheitert das, startet der Pod nicht, und die alten Pods laufen weiter.
|
||||
|
||||
Migrationen sind vorwärtskompatibel zu schreiben (erst Spalten ergänzen, später entfernen), damit alte und neue Pods während des Rollouts parallel laufen können.
|
||||
|
||||
## 4. Stripe
|
||||
|
||||
Reference in new issue
Block a user