refactor: Kubernetes-Ressourcen und Images heissen artista-filmcamp
Docker-Images bauen und veroeffentlichen / build-and-push (push) Successful in 4m39s
Docker-Images bauen und veroeffentlichen / build-and-push (push) Successful in 4m39s
Alle Ressourcen tragen den Praefix artista-filmcamp- (Deployment, Service, StatefulSet, CronJobs, PVCs, ConfigMap, Secret, Ingress, NetworkPolicies, Middleware) und liegen im Namespace artista. Die Images heissen wieder <owner>/artista-filmcamp und <owner>/artista-filmcamp-tools, passend zum Repo. DATABASE_URL-Host, Backup-Host und Betriebsdoku entsprechend angepasst. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
c18c628131
commit
f9349144ea
11 files changed
+73
-73
No files matched your search
@@ -29,11 +29,11 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Image-Namen ermitteln
|
- name: Image-Namen ermitteln
|
||||||
# Fester Produktname "artista-modelcamp" unabhaengig vom Repo-Namen;
|
# Fester Produktname "artista-filmcamp" unabhaengig vom Repo-Namen;
|
||||||
# nur der Besitzer kommt aus Gitea, in Kleinbuchstaben (OCI-Vorgabe):
|
# nur der Besitzer kommt aus Gitea, in Kleinbuchstaben (OCI-Vorgabe):
|
||||||
# "Nick.Rosenloecher" -> "nick.rosenloecher/artista-modelcamp".
|
# "Nick.Rosenloecher" -> "nick.rosenloecher/artista-filmcamp".
|
||||||
id: image
|
id: image
|
||||||
run: echo "name=$(echo '${{ gitea.repository_owner }}' | tr '[:upper:]' '[:lower:]')/artista-modelcamp" >> "$GITEA_OUTPUT"
|
run: echo "name=$(echo '${{ gitea.repository_owner }}' | tr '[:upper:]' '[:lower:]')/artista-filmcamp" >> "$GITEA_OUTPUT"
|
||||||
|
|
||||||
- name: Docker Buildx einrichten
|
- name: Docker Buildx einrichten
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
#
|
#
|
||||||
# Zwei Images aus einem Build:
|
# Zwei Images aus einem Build:
|
||||||
# docker build --target runner -t <registry>/artista-modelcamp:<tag> .
|
# docker build --target runner -t <registry>/artista-filmcamp:<tag> .
|
||||||
# docker build --target tools -t <registry>/artista-modelcamp-tools:<tag> .
|
# docker build --target tools -t <registry>/artista-filmcamp-tools:<tag> .
|
||||||
#
|
#
|
||||||
# runner: der Next.js-Server (standalone), sonst nichts.
|
# runner: der Next.js-Server (standalone), sonst nichts.
|
||||||
# tools: Prisma-CLI + tsx fuer den kontrollierten Migrationsschritt
|
# tools: Prisma-CLI + tsx fuer den kontrollierten Migrationsschritt
|
||||||
|
|||||||
+12
-12
@@ -16,8 +16,8 @@ Ein Release entsteht dann so: `git tag v0.1.0 && git push origin v0.1.0`, anschl
|
|||||||
**Manuell:**
|
**Manuell:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build --target runner -t git.encry.de/nick.rosenloecher/artista-modelcamp:0.1.0 .
|
docker build --target runner -t git.encry.de/nick.rosenloecher/artista-filmcamp:0.1.0 .
|
||||||
docker build --target tools -t git.encry.de/nick.rosenloecher/artista-modelcamp-tools:0.1.0 .
|
docker build --target tools -t git.encry.de/nick.rosenloecher/artista-filmcamp-tools:0.1.0 .
|
||||||
docker push … # beide Images, immer mit identischem Tag
|
docker push … # beide Images, immer mit identischem Tag
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -35,8 +35,8 @@ Der Build braucht Internet für `next/font` (Schriften werden eingebettet), aber
|
|||||||
5. **Migration** (siehe Abschnitt 3), danach das erste Admin-Konto:
|
5. **Migration** (siehe Abschnitt 3), danach das erste Admin-Konto:
|
||||||
```bash
|
```bash
|
||||||
kubectl -n artista run admin-create --rm -it --restart=Never --labels=artista/db-client=true \
|
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 \
|
--image=git.encry.de/nick.rosenloecher/artista-filmcamp-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-config"}},{"secretRef":{"name":"artista-secrets"}}]}]}}'
|
--overrides='{"spec":{"containers":[{"name":"admin-create","image":"git.encry.de/nick.rosenloecher/artista-filmcamp-tools:0.1.0","command":["tsx","scripts/create-admin.ts","--email","[email protected]","--name","Dein Name"],"envFrom":[{"configMapRef":{"name":"artista-filmcamp-config"}},{"secretRef":{"name":"artista-filmcamp-secrets"}}]}]}}'
|
||||||
```
|
```
|
||||||
Das einmalige Passwort wird ausgegeben. Bei der ersten Anmeldung unter `/admin` wird die 2FA eingerichtet.
|
Das einmalige Passwort wird ausgegeben. Bei der ersten Anmeldung unter `/admin` wird die 2FA eingerichtet.
|
||||||
|
|
||||||
@@ -47,10 +47,10 @@ Der Build braucht Internet für `next/font` (Schriften werden eingebettet), aber
|
|||||||
kubectl apply -k k8s/overlays/production
|
kubectl apply -k k8s/overlays/production
|
||||||
# 2. Migration bewusst starten und abwarten
|
# 2. Migration bewusst starten und abwarten
|
||||||
JOB=migrate-$(date +%Y%m%d%H%M)
|
JOB=migrate-$(date +%Y%m%d%H%M)
|
||||||
kubectl -n artista create job $JOB --from=cronjob/artista-migrate
|
kubectl -n artista create job $JOB --from=cronjob/artista-filmcamp-migrate
|
||||||
kubectl -n artista wait --for=condition=complete job/$JOB --timeout=5m
|
kubectl -n artista wait --for=condition=complete job/$JOB --timeout=5m
|
||||||
# 3. Rollout beobachten
|
# 3. Rollout beobachten
|
||||||
kubectl -n artista rollout status deploy/artista-app
|
kubectl -n artista rollout status deploy/artista-filmcamp-app
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
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.
|
||||||
@@ -71,7 +71,7 @@ Migrationen sind vorwärtskompatibel zu schreiben (erst Spalten ergänzen, spät
|
|||||||
|
|
||||||
## 6. Worker
|
## 6. Worker
|
||||||
|
|
||||||
Der CronJob `artista-worker` läuft alle 10 Minuten und kümmert sich um:
|
Der CronJob `artista-filmcamp-worker` läuft alle 10 Minuten und kümmert sich um:
|
||||||
- abgelaufene Reservierungen, vorher mit Rückfrage bei Stripe
|
- abgelaufene Reservierungen, vorher mit Rückfrage bei Stripe
|
||||||
- hängende Einzüge
|
- hängende Einzüge
|
||||||
- fällige Raten
|
- fällige Raten
|
||||||
@@ -83,18 +83,18 @@ Ein fehlgeschlagener Lauf erscheint als fehlgeschlagener Job (`kubectl -n artist
|
|||||||
|
|
||||||
## 7. Sicherung und Wiederherstellung
|
## 7. Sicherung und Wiederherstellung
|
||||||
|
|
||||||
- **Sicherung:** Der CronJob `artista-db-backup` erstellt täglich um 3:15 Uhr einen Dump im `pg_dump`-Custom-Format nach `artista-db-backup` und bewahrt ihn 30 Tage auf.
|
- **Sicherung:** Der CronJob `artista-filmcamp-db-backup` erstellt täglich um 3:15 Uhr einen Dump im `pg_dump`-Custom-Format nach `artista-filmcamp-db-backup` und bewahrt ihn 30 Tage auf.
|
||||||
- **Aus dem Cluster sichern (regelmäßig):**
|
- **Aus dem Cluster sichern (regelmäßig):**
|
||||||
```bash
|
```bash
|
||||||
POD=$(kubectl -n artista get pod -l app.kubernetes.io/name=artista-postgres -o name | head -1)
|
POD=$(kubectl -n artista get pod -l app.kubernetes.io/name=artista-filmcamp-postgres -o name | head -1)
|
||||||
kubectl -n artista exec $POD -- pg_dump -U artista -d artista --format=custom > artista-$(date +%F).dump
|
kubectl -n artista exec $POD -- pg_dump -U artista -d artista --format=custom > artista-$(date +%F).dump
|
||||||
```
|
```
|
||||||
- **Wiederherstellen:**
|
- **Wiederherstellen:**
|
||||||
1. App stoppen: `kubectl -n artista scale deploy/artista-app --replicas=0` und den Worker-CronJob pausieren: `kubectl -n artista patch cronjob artista-worker -p '{"spec":{"suspend":true}}'`
|
1. App stoppen: `kubectl -n artista scale deploy/artista-filmcamp-app --replicas=0` und den Worker-CronJob pausieren: `kubectl -n artista patch cronjob artista-filmcamp-worker -p '{"spec":{"suspend":true}}'`
|
||||||
2. Einspielen: `kubectl -n artista exec -i $POD -- pg_restore -U artista -d artista --clean --if-exists < artista-YYYY-MM-DD.dump`
|
2. Einspielen: `kubectl -n artista exec -i $POD -- pg_restore -U artista -d artista --clean --if-exists < artista-YYYY-MM-DD.dump`
|
||||||
3. Migration laufen lassen (Abschnitt 3), App wieder hochskalieren, Worker fortsetzen.
|
3. Migration laufen lassen (Abschnitt 3), App wieder hochskalieren, Worker fortsetzen.
|
||||||
4. Abgleich: Zahlungen, die nach dem Sicherungszeitpunkt eingingen, im Stripe-Dashboard prüfen. Stripe stellt Webhooks bis zu drei Tage erneut zu (Dashboard → Webhooks → „Erneut senden“).
|
4. Abgleich: Zahlungen, die nach dem Sicherungszeitpunkt eingingen, im Stripe-Dashboard prüfen. Stripe stellt Webhooks bis zu drei Tage erneut zu (Dashboard → Webhooks → „Erneut senden“).
|
||||||
- **Medien:** Das Volume `artista-media` separat sichern, z. B. mit Volume-Snapshots oder der Sicherung des Speichersystems.
|
- **Medien:** Das Volume `artista-filmcamp-media` separat sichern, z. B. mit Volume-Snapshots oder der Sicherung des Speichersystems.
|
||||||
- **Wiederherstellung üben:** mindestens einmal vor dem Live-Verkauf in einen Test-Namespace.
|
- **Wiederherstellung üben:** mindestens einmal vor dem Live-Verkauf in einen Test-Namespace.
|
||||||
|
|
||||||
## 8. Stornierung und Erstattung
|
## 8. Stornierung und Erstattung
|
||||||
@@ -108,7 +108,7 @@ Die Software trifft keine Storno-Entscheidung, sie setzt sie nur nachvollziehbar
|
|||||||
|
|
||||||
## 9. Medien
|
## 9. Medien
|
||||||
|
|
||||||
Dateien (jpg, png, webp, avif, mp4, webm) in das Volume `artista-media` kopieren:
|
Dateien (jpg, png, webp, avif, mp4, webm) in das Volume `artista-filmcamp-media` kopieren:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
kubectl -n artista cp villa-aussen.jpg <app-pod>:/app/media/villa-aussen.jpg # Volume ist im App-Pod read-only → einen Hilfs-Pod mit Schreibzugriff nutzen
|
kubectl -n artista cp villa-aussen.jpg <app-pod>:/app/media/villa-aussen.jpg # Volume ist im App-Pod read-only → einen Hilfs-Pod mit Schreibzugriff nutzen
|
||||||
|
|||||||
+15
-15
@@ -3,11 +3,11 @@
|
|||||||
# PostgreSQL — beliebig viele Replikate moeglich.
|
# PostgreSQL — beliebig viele Replikate moeglich.
|
||||||
#
|
#
|
||||||
# Migrationen laufen NICHT beim Start, sondern als eigener, kontrollierter
|
# Migrationen laufen NICHT beim Start, sondern als eigener, kontrollierter
|
||||||
# Schritt (jobs.yaml, CronJob "artista-migrate", siehe docs/BETRIEB.md).
|
# Schritt (jobs.yaml, CronJob "artista-filmcamp-migrate", siehe docs/BETRIEB.md).
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-app
|
name: artista-filmcamp-app
|
||||||
spec:
|
spec:
|
||||||
replicas: 2
|
replicas: 2
|
||||||
revisionHistoryLimit: 5
|
revisionHistoryLimit: 5
|
||||||
@@ -16,11 +16,11 @@ spec:
|
|||||||
rollingUpdate: { maxSurge: 1, maxUnavailable: 0 }
|
rollingUpdate: { maxSurge: 1, maxUnavailable: 0 }
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/name: artista-app
|
app.kubernetes.io/name: artista-filmcamp-app
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: artista-app
|
app.kubernetes.io/name: artista-filmcamp-app
|
||||||
artista/db-client: "true"
|
artista/db-client: "true"
|
||||||
spec:
|
spec:
|
||||||
automountServiceAccountToken: false
|
automountServiceAccountToken: false
|
||||||
@@ -36,16 +36,16 @@ spec:
|
|||||||
whenUnsatisfiable: ScheduleAnyway
|
whenUnsatisfiable: ScheduleAnyway
|
||||||
labelSelector:
|
labelSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/name: artista-app
|
app.kubernetes.io/name: artista-filmcamp-app
|
||||||
containers:
|
containers:
|
||||||
- name: app
|
- name: app
|
||||||
image: artista-modelcamp
|
image: artista-filmcamp
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: 3000
|
containerPort: 3000
|
||||||
envFrom:
|
envFrom:
|
||||||
- configMapRef: { name: artista-config }
|
- configMapRef: { name: artista-filmcamp-config }
|
||||||
- secretRef: { name: artista-secrets }
|
- secretRef: { name: artista-filmcamp-secrets }
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet: { path: /api/health/ready, port: http }
|
httpGet: { path: /api/health/ready, port: http }
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
@@ -76,7 +76,7 @@ spec:
|
|||||||
mountPath: /tmp
|
mountPath: /tmp
|
||||||
volumes:
|
volumes:
|
||||||
- name: media
|
- name: media
|
||||||
persistentVolumeClaim: { claimName: artista-media }
|
persistentVolumeClaim: { claimName: artista-filmcamp-media }
|
||||||
- name: next-cache
|
- name: next-cache
|
||||||
emptyDir: { sizeLimit: 512Mi }
|
emptyDir: { sizeLimit: 512Mi }
|
||||||
- name: tmp
|
- name: tmp
|
||||||
@@ -85,10 +85,10 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-app
|
name: artista-filmcamp-app
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app.kubernetes.io/name: artista-app
|
app.kubernetes.io/name: artista-filmcamp-app
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
port: 80
|
port: 80
|
||||||
@@ -102,11 +102,11 @@ spec:
|
|||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: NetworkPolicy
|
kind: NetworkPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-app-ingress
|
name: artista-filmcamp-app-ingress
|
||||||
spec:
|
spec:
|
||||||
podSelector:
|
podSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/name: artista-app
|
app.kubernetes.io/name: artista-filmcamp-app
|
||||||
policyTypes: ["Ingress"]
|
policyTypes: ["Ingress"]
|
||||||
ingress:
|
ingress:
|
||||||
- from:
|
- from:
|
||||||
@@ -121,9 +121,9 @@ spec:
|
|||||||
apiVersion: policy/v1
|
apiVersion: policy/v1
|
||||||
kind: PodDisruptionBudget
|
kind: PodDisruptionBudget
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-app
|
name: artista-filmcamp-app
|
||||||
spec:
|
spec:
|
||||||
minAvailable: 1
|
minAvailable: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/name: artista-app
|
app.kubernetes.io/name: artista-filmcamp-app
|
||||||
@@ -10,7 +10,7 @@ metadata:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-config
|
name: artista-filmcamp-config
|
||||||
data:
|
data:
|
||||||
APP_ENV: "production"
|
APP_ENV: "production"
|
||||||
APP_URL: "https://modelcamp.example.org"
|
APP_URL: "https://modelcamp.example.org"
|
||||||
@@ -33,7 +33,7 @@ data:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-media
|
name: artista-filmcamp-media
|
||||||
spec:
|
spec:
|
||||||
accessModes: ["ReadWriteMany"]
|
accessModes: ["ReadWriteMany"]
|
||||||
# storageClassName: longhorn
|
# storageClassName: longhorn
|
||||||
@@ -46,11 +46,11 @@ spec:
|
|||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: NetworkPolicy
|
kind: NetworkPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-postgres-access
|
name: artista-filmcamp-postgres-access
|
||||||
spec:
|
spec:
|
||||||
podSelector:
|
podSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/name: artista-postgres
|
app.kubernetes.io/name: artista-filmcamp-postgres
|
||||||
policyTypes: ["Ingress"]
|
policyTypes: ["Ingress"]
|
||||||
ingress:
|
ingress:
|
||||||
- from:
|
- from:
|
||||||
|
|||||||
+13
-13
@@ -2,12 +2,12 @@
|
|||||||
# Als SUSPENDIERTER CronJob definiert, damit Kustomize das Image mit der
|
# Als SUSPENDIERTER CronJob definiert, damit Kustomize das Image mit der
|
||||||
# App gleichzieht. Er laeuft nie von selbst, sondern bewusst vor jedem
|
# App gleichzieht. Er laeuft nie von selbst, sondern bewusst vor jedem
|
||||||
# Rollout:
|
# Rollout:
|
||||||
# kubectl -n artista create job migrate-$(date +%Y%m%d%H%M) --from=cronjob/artista-migrate
|
# kubectl -n artista create job migrate-$(date +%Y%m%d%H%M) --from=cronjob/artista-filmcamp-migrate
|
||||||
# kubectl -n artista wait --for=condition=complete job/migrate-… --timeout=5m
|
# kubectl -n artista wait --for=condition=complete job/migrate-… --timeout=5m
|
||||||
apiVersion: batch/v1
|
apiVersion: batch/v1
|
||||||
kind: CronJob
|
kind: CronJob
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-migrate
|
name: artista-filmcamp-migrate
|
||||||
spec:
|
spec:
|
||||||
suspend: true
|
suspend: true
|
||||||
schedule: "0 0 1 1 *"
|
schedule: "0 0 1 1 *"
|
||||||
@@ -28,10 +28,10 @@ spec:
|
|||||||
seccompProfile: { type: RuntimeDefault }
|
seccompProfile: { type: RuntimeDefault }
|
||||||
containers:
|
containers:
|
||||||
- name: migrate
|
- name: migrate
|
||||||
image: artista-modelcamp-tools
|
image: artista-filmcamp-tools
|
||||||
command: ["prisma", "migrate", "deploy"]
|
command: ["prisma", "migrate", "deploy"]
|
||||||
envFrom:
|
envFrom:
|
||||||
- secretRef: { name: artista-secrets }
|
- secretRef: { name: artista-filmcamp-secrets }
|
||||||
resources:
|
resources:
|
||||||
requests: { cpu: 50m, memory: 128Mi }
|
requests: { cpu: 50m, memory: 128Mi }
|
||||||
limits: { memory: 512Mi }
|
limits: { memory: 512Mi }
|
||||||
@@ -47,7 +47,7 @@ spec:
|
|||||||
apiVersion: batch/v1
|
apiVersion: batch/v1
|
||||||
kind: CronJob
|
kind: CronJob
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-worker
|
name: artista-filmcamp-worker
|
||||||
spec:
|
spec:
|
||||||
schedule: "*/10 * * * *"
|
schedule: "*/10 * * * *"
|
||||||
timeZone: "Europe/Berlin"
|
timeZone: "Europe/Berlin"
|
||||||
@@ -72,11 +72,11 @@ spec:
|
|||||||
seccompProfile: { type: RuntimeDefault }
|
seccompProfile: { type: RuntimeDefault }
|
||||||
containers:
|
containers:
|
||||||
- name: worker
|
- name: worker
|
||||||
image: artista-modelcamp-tools
|
image: artista-filmcamp-tools
|
||||||
command: ["tsx", "scripts/worker.ts"]
|
command: ["tsx", "scripts/worker.ts"]
|
||||||
envFrom:
|
envFrom:
|
||||||
- configMapRef: { name: artista-config }
|
- configMapRef: { name: artista-filmcamp-config }
|
||||||
- secretRef: { name: artista-secrets }
|
- secretRef: { name: artista-filmcamp-secrets }
|
||||||
resources:
|
resources:
|
||||||
requests: { cpu: 50m, memory: 192Mi }
|
requests: { cpu: 50m, memory: 192Mi }
|
||||||
limits: { memory: 512Mi }
|
limits: { memory: 512Mi }
|
||||||
@@ -91,7 +91,7 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-db-backup
|
name: artista-filmcamp-db-backup
|
||||||
spec:
|
spec:
|
||||||
accessModes: ["ReadWriteOnce"]
|
accessModes: ["ReadWriteOnce"]
|
||||||
# storageClassName: smb-backup
|
# storageClassName: smb-backup
|
||||||
@@ -102,7 +102,7 @@ spec:
|
|||||||
apiVersion: batch/v1
|
apiVersion: batch/v1
|
||||||
kind: CronJob
|
kind: CronJob
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-db-backup
|
name: artista-filmcamp-db-backup
|
||||||
spec:
|
spec:
|
||||||
schedule: "15 3 * * *"
|
schedule: "15 3 * * *"
|
||||||
timeZone: "Europe/Berlin"
|
timeZone: "Europe/Berlin"
|
||||||
@@ -131,7 +131,7 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: PGPASSWORD
|
- name: PGPASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef: { name: artista-secrets, key: DB_PASSWORD }
|
secretKeyRef: { name: artista-filmcamp-secrets, key: DB_PASSWORD }
|
||||||
command: ["/bin/sh", "-c"]
|
command: ["/bin/sh", "-c"]
|
||||||
args:
|
args:
|
||||||
- |
|
- |
|
||||||
@@ -139,7 +139,7 @@ spec:
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
target="/backup/artista-$(date -u +%Y-%m-%d_%H%M).dump"
|
target="/backup/artista-$(date -u +%Y-%m-%d_%H%M).dump"
|
||||||
# Custom-Format: komprimiert, selektiv wiederherstellbar.
|
# Custom-Format: komprimiert, selektiv wiederherstellbar.
|
||||||
pg_dump --host=artista-postgres --username=artista --dbname=artista \
|
pg_dump --host=artista-filmcamp-postgres --username=artista --dbname=artista \
|
||||||
--format=custom --file="${target}.partial"
|
--format=custom --file="${target}.partial"
|
||||||
mv "${target}.partial" "${target}"
|
mv "${target}.partial" "${target}"
|
||||||
find /backup -name 'artista-*.dump.partial' -mtime +1 -delete
|
find /backup -name 'artista-*.dump.partial' -mtime +1 -delete
|
||||||
@@ -156,4 +156,4 @@ spec:
|
|||||||
mountPath: /backup
|
mountPath: /backup
|
||||||
volumes:
|
volumes:
|
||||||
- name: backup
|
- name: backup
|
||||||
persistentVolumeClaim: { claimName: artista-db-backup }
|
persistentVolumeClaim: { claimName: artista-filmcamp-db-backup }
|
||||||
@@ -10,5 +10,5 @@ resources:
|
|||||||
- jobs.yaml
|
- jobs.yaml
|
||||||
labels:
|
labels:
|
||||||
- pairs:
|
- pairs:
|
||||||
app.kubernetes.io/part-of: artista-modelcamp
|
app.kubernetes.io/part-of: artista-filmcamp
|
||||||
includeSelectors: false
|
includeSelectors: false
|
||||||
@@ -12,17 +12,17 @@
|
|||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: StatefulSet
|
kind: StatefulSet
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-postgres
|
name: artista-filmcamp-postgres
|
||||||
spec:
|
spec:
|
||||||
serviceName: artista-postgres
|
serviceName: artista-filmcamp-postgres
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/name: artista-postgres
|
app.kubernetes.io/name: artista-filmcamp-postgres
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: artista-postgres
|
app.kubernetes.io/name: artista-filmcamp-postgres
|
||||||
spec:
|
spec:
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsNonRoot: true
|
runAsNonRoot: true
|
||||||
@@ -42,7 +42,7 @@ spec:
|
|||||||
value: artista
|
value: artista
|
||||||
- name: POSTGRES_PASSWORD
|
- name: POSTGRES_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef: { name: artista-secrets, key: DB_PASSWORD }
|
secretKeyRef: { name: artista-filmcamp-secrets, key: DB_PASSWORD }
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
# Ab PostgreSQL 18 liegt PGDATA unter /var/lib/postgresql/18/docker.
|
# Ab PostgreSQL 18 liegt PGDATA unter /var/lib/postgresql/18/docker.
|
||||||
- name: data
|
- name: data
|
||||||
@@ -73,10 +73,10 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-postgres
|
name: artista-filmcamp-postgres
|
||||||
spec:
|
spec:
|
||||||
clusterIP: None
|
clusterIP: None
|
||||||
selector:
|
selector:
|
||||||
app.kubernetes.io/name: artista-postgres
|
app.kubernetes.io/name: artista-filmcamp-postgres
|
||||||
ports:
|
ports:
|
||||||
- port: 5432
|
- port: 5432
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: artista
|
name: artista-filmcamp
|
||||||
annotations:
|
annotations:
|
||||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
@@ -18,7 +18,7 @@ spec:
|
|||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- modelcamp.example.org
|
- modelcamp.example.org
|
||||||
secretName: artista-tls
|
secretName: artista-filmcamp-tls
|
||||||
rules:
|
rules:
|
||||||
- host: modelcamp.example.org
|
- host: modelcamp.example.org
|
||||||
http:
|
http:
|
||||||
@@ -27,7 +27,7 @@ spec:
|
|||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: artista-app
|
name: artista-filmcamp-app
|
||||||
port:
|
port:
|
||||||
name: http
|
name: http
|
||||||
---
|
---
|
||||||
@@ -36,10 +36,10 @@ spec:
|
|||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-http-redirect
|
name: artista-filmcamp-http-redirect
|
||||||
annotations:
|
annotations:
|
||||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||||
traefik.ingress.kubernetes.io/router.middlewares: artista-redirect-https@kubernetescrd
|
traefik.ingress.kubernetes.io/router.middlewares: artista-artista-filmcamp-redirect-https@kubernetescrd
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: traefik
|
ingressClassName: traefik
|
||||||
rules:
|
rules:
|
||||||
@@ -50,14 +50,14 @@ spec:
|
|||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: artista-app
|
name: artista-filmcamp-app
|
||||||
port:
|
port:
|
||||||
name: http
|
name: http
|
||||||
---
|
---
|
||||||
apiVersion: traefik.io/v1alpha1
|
apiVersion: traefik.io/v1alpha1
|
||||||
kind: Middleware
|
kind: Middleware
|
||||||
metadata:
|
metadata:
|
||||||
name: redirect-https
|
name: artista-filmcamp-redirect-https
|
||||||
spec:
|
spec:
|
||||||
redirectScheme:
|
redirectScheme:
|
||||||
scheme: https
|
scheme: https
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ images:
|
|||||||
# Gebaut von .gitea/workflows/docker-build.yml: Git-Tag "v0.1.0" pushen
|
# Gebaut von .gitea/workflows/docker-build.yml: Git-Tag "v0.1.0" pushen
|
||||||
# ergibt Image-Tag "0.1.0" (Alternativen: "sha-<kurz>", "latest").
|
# ergibt Image-Tag "0.1.0" (Alternativen: "sha-<kurz>", "latest").
|
||||||
# Beide Images immer mit identischem Tag ausrollen.
|
# Beide Images immer mit identischem Tag ausrollen.
|
||||||
- name: artista-modelcamp
|
- name: artista-filmcamp
|
||||||
newName: git.encry.de/nick.rosenloecher/artista-modelcamp
|
newName: git.encry.de/nick.rosenloecher/artista-filmcamp
|
||||||
newTag: "0.1.0"
|
newTag: "0.1.0"
|
||||||
- name: artista-modelcamp-tools
|
- name: artista-filmcamp-tools
|
||||||
newName: git.encry.de/nick.rosenloecher/artista-modelcamp-tools
|
newName: git.encry.de/nick.rosenloecher/artista-filmcamp-tools
|
||||||
newTag: "0.1.0"
|
newTag: "0.1.0"
|
||||||
|
|
||||||
patches:
|
patches:
|
||||||
- target: { kind: ConfigMap, name: artista-config }
|
- target: { kind: ConfigMap, name: artista-filmcamp-config }
|
||||||
patch: |-
|
patch: |-
|
||||||
- op: replace
|
- op: replace
|
||||||
path: /data/APP_URL
|
path: /data/APP_URL
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# VORLAGE — nicht mit echten Werten ins Repository einchecken.
|
# VORLAGE — nicht mit echten Werten ins Repository einchecken.
|
||||||
# Anlegen z. B. per:
|
# Anlegen z. B. per:
|
||||||
# kubectl -n artista create secret generic artista-secrets \
|
# kubectl -n artista create secret generic artista-filmcamp-secrets \
|
||||||
# --from-literal=DB_PASSWORD='…' \
|
# --from-literal=DB_PASSWORD='…' \
|
||||||
# --from-literal=DATABASE_URL='postgresql://artista:…@artista-postgres:5432/artista' \
|
# --from-literal=DATABASE_URL='postgresql://artista:…@artista-filmcamp-postgres:5432/artista' \
|
||||||
# --from-literal=APP_SECRET="$(openssl rand -base64 48)" \
|
# --from-literal=APP_SECRET="$(openssl rand -base64 48)" \
|
||||||
# --from-literal=BETTER_AUTH_SECRET="$(openssl rand -base64 48)" \
|
# --from-literal=BETTER_AUTH_SECRET="$(openssl rand -base64 48)" \
|
||||||
# --from-literal=STRIPE_SECRET_KEY='sk_test_…' \
|
# --from-literal=STRIPE_SECRET_KEY='sk_test_…' \
|
||||||
@@ -12,13 +12,13 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
name: artista-secrets
|
name: artista-filmcamp-secrets
|
||||||
namespace: artista
|
namespace: artista
|
||||||
type: Opaque
|
type: Opaque
|
||||||
stringData:
|
stringData:
|
||||||
DB_PASSWORD: "<starkes-passwort>"
|
DB_PASSWORD: "<starkes-passwort>"
|
||||||
# Passwort URL-kodiert einsetzen, falls Sonderzeichen enthalten sind.
|
# Passwort URL-kodiert einsetzen, falls Sonderzeichen enthalten sind.
|
||||||
DATABASE_URL: "postgresql://artista:<starkes-passwort>@artista-postgres:5432/artista"
|
DATABASE_URL: "postgresql://artista:<starkes-passwort>@artista-filmcamp-postgres:5432/artista"
|
||||||
APP_SECRET: "<mind-32-zeichen-zufall>"
|
APP_SECRET: "<mind-32-zeichen-zufall>"
|
||||||
BETTER_AUTH_SECRET: "<anderer-mind-32-zeichen-zufall>"
|
BETTER_AUTH_SECRET: "<anderer-mind-32-zeichen-zufall>"
|
||||||
STRIPE_SECRET_KEY: "<sk_test_… oder sk_live_…>"
|
STRIPE_SECRET_KEY: "<sk_test_… oder sk_live_…>"
|
||||||
|
|||||||
Reference in new issue
Block a user