Files
Artista-Filmcamp/k8s
Nick SzaunigandClaude Opus 5.5 f2b548cb98
Docker-Images bauen und veroeffentlichen / build-and-push (push) Successful in 5m51s
chore(k8s): Images auf CI-Build pinnen statt :latest
App, Migration und Worker zeigen auf sha-<commit> mit
imagePullPolicy IfNotPresent. Damit gibt es ein Rollback per
rollout undo, und ein Neustart zieht nicht mehr ungeprueft das
neueste Image (oder scheitert, wenn Gitea gerade nicht laeuft).
README beschreibt das Ausrollen mit kubectl set image.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-12 05:27:47 +02:00
..

ARTISTA Modelcamp in Kubernetes (RKE2)

Rohe Manifeste wie bei Wabenhain, Nummerierung = Reihenfolge. Voraussetzungen im Cluster (wie bei Wabenhain):

  • Traefik als Ingress-Controller (IngressClass traefik)
  • cert-manager mit dem ClusterIssuer letsencrypt-prod
  • csi-driver-smb für die SMB-Volumes

Prüfen:

kubectl get ingressclass
kubectl get clusterissuer letsencrypt-prod
kubectl get csidrivers | grep smb

Einmalige Vorbereitung

  1. Images: .gitea/workflows/docker-build.yml baut bei jedem Push auf main die Images git.encry.de/nick.rosenloecher/artista-modelcamp:latest und …-tools:latest. Voraussetzung ist das Repo-Secret REGISTRY_TOKEN (Personal Access Token mit package-Scope), wie bei Wabenhain.
  2. csi-driver-smb (falls noch nicht vorhanden):
    helm repo add csi-driver-smb https://raw.githubusercontent.com/kubernetes-csi/csi-driver-smb/master/charts
    helm install csi-driver-smb csi-driver-smb/csi-driver-smb -n kube-system
    
  3. NAS: Die Ordner artista/modelcamp-postgres (leer) und artista/modelcamp-media anlegen und SMB-Verschlüsselung erlauben. nas.example.lan in 03-storage.yaml anpassen.
  4. Domain: modelcamp.example.org in 01-configmap.yaml (APP_URL) und 06-ingress.yaml (2×) ersetzen. Der DNS-Eintrag muss auf den Cluster zeigen, sonst stellt cert-manager kein Zertifikat aus.
  5. Secrets: cp k8s/02-secret.yaml.example k8s/02-secret.yaml und ausfüllen. Die Datei steht in .gitignore, bitte nie mit echten Werten committen.

Deployment (auch für einen kompletten Neuaufbau)

kubectl apply -f k8s/00-namespace.yaml
kubectl apply -f k8s/01-configmap.yaml
kubectl apply -f k8s/02-secret.yaml
kubectl apply -f k8s/03-storage.yaml
kubectl apply -f k8s/04-postgres.yaml
kubectl wait --for=condition=ready pod -l app=artista-modelcamp-postgres -n artista --timeout=180s
kubectl apply -f k8s/05-app-deployment.yaml
kubectl apply -f k8s/06-ingress.yaml
kubectl apply -f k8s/07-worker-cronjob.yaml
kubectl apply -f k8s/08-networkpolicy.yaml

Die Migration läuft automatisch als initContainer vor dem App-Start. Den Stand zeigen:

kubectl rollout status deployment/artista-modelcamp-app -n artista
kubectl get certificate -n artista        # READY muss True werden (meist < 2 Minuten)

Neuaufbau mit kubectl delete namespace artista: Die PersistentVolumes (artista-modelcamp-postgres, artista-modelcamp-media) gehören keinem Namespace und bleiben auf Released stehen. Die Daten auf dem NAS bleiben erhalten (Retain). Damit die neuen Claims sie wieder binden können, vor dem erneuten Anlegen:

kubectl patch pv artista-modelcamp-postgres -p '{"spec":{"claimRef":null}}'
kubectl patch pv artista-modelcamp-media -p '{"spec":{"claimRef":null}}'

Soll die Datenbank wirklich leer neu starten, den Ordner modelcamp-postgres auf dem NAS vorher leeren.

Erstes Admin-Konto

E-Mail und Name ersetzen. Das einmalige Passwort wird ausgegeben, die 2FA richtest du bei der ersten Anmeldung unter /admin ein.

kubectl -n artista run admin-create --rm -i --restart=Never \
  --image=git.encry.de/nick.rosenloecher/artista-modelcamp-tools:latest --labels=db-client=true \
  --overrides='{"spec":{"securityContext":{"runAsNonRoot":true,"runAsUser":1001,"seccompProfile":{"type":"RuntimeDefault"}},"containers":[{"name":"admin-create","image":"git.encry.de/nick.rosenloecher/artista-modelcamp-tools:latest","command":["tsx","scripts/create-admin.ts","--email","[email protected]","--name","Dein Name"],"envFrom":[{"configMapRef":{"name":"artista-modelcamp-config"}},{"secretRef":{"name":"artista-modelcamp-secrets"}}],"securityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}}}]}}'

Bei einem neuen Image (Redeploy)

Die Manifeste sind auf einen Build gepinnt, nicht auf :latest. Den Tag sha-<commit> (7 Zeichen) zeigt der CI-Lauf in der Zusammenfassung. App und Werkzeuge immer mit demselben Tag ausrollen:

TAG=sha-<commit>
kubectl -n artista set image deployment/artista-modelcamp-app \
  migrate=git.encry.de/nick.rosenloecher/artista-modelcamp-tools:$TAG \
  app=git.encry.de/nick.rosenloecher/artista-modelcamp:$TAG
kubectl -n artista set image cronjob/artista-modelcamp-worker \
  worker=git.encry.de/nick.rosenloecher/artista-modelcamp-tools:$TAG
kubectl -n artista rollout status deployment/artista-modelcamp-app

Zurueck auf den vorherigen Stand: kubectl -n artista rollout undo deployment/artista-modelcamp-app (den CronJob dann wieder auf den alten Tag setzen).

Fehlersuche

kubectl -n artista get certificate,certificaterequest,order,challenge   # Zertifikat
kubectl -n artista describe challenge
kubectl -n artista logs deploy/artista-modelcamp-app -c migrate         # Migration
kubectl -n artista logs deploy/artista-modelcamp-app -c app             # App
kubectl -n artista get events --sort-by=.lastTimestamp | tail -20