feat(k8s): Sicherung und Hintergrund-Jobs lauffaehig machen
- Werkzeug-Image wabenhain-tools (Dockerfile "AS tools", Muster wie artista-modelcamp-tools): Im App-Image fehlten tsconfig.json und Pakete wie stripe, Bestandsabgleich und Bestellfreigabe brachen mit "Cannot find module" ab. Die CI baut es neben dem App-Image. - Datenbank-Sicherung: PV auf der Storage Box (Customer/Wabenhain), der Unterordner db-backup entsteht per subPath. Vorher blieb der PVC ohne StorageClass haengen. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
b246c9ff4e
commit
f28e5e9d84
3 files changed
+85
-12
No files matched your search
@@ -77,6 +77,16 @@ jobs:
|
|||||||
type=sha,format=short
|
type=sha,format=short
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
|
|
||||||
|
- name: Metadaten Werkzeuge
|
||||||
|
id: meta-tools
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY_PUSH }}/${{ steps.image.outputs.name }}-tools
|
||||||
|
tags: |
|
||||||
|
type=raw,value=latest,enable={{is_default_branch}}
|
||||||
|
type=sha,format=short
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
|
||||||
# Ein einzelnes Image traegt beide Prisma-Client-Varianten (Postgres +
|
# Ein einzelnes Image traegt beide Prisma-Client-Varianten (Postgres +
|
||||||
# MySQL, waehlt zur Laufzeit per DATABASE_PROVIDER, siehe
|
# MySQL, waehlt zur Laufzeit per DATABASE_PROVIDER, siehe
|
||||||
# src/lib/prisma.ts) UND die Migrations-/Seed-Tools (siehe Dockerfile-
|
# src/lib/prisma.ts) UND die Migrations-/Seed-Tools (siehe Dockerfile-
|
||||||
@@ -86,8 +96,22 @@ jobs:
|
|||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
target: runner
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
# Werkzeug-Image fuer die CronJobs (Dockerfile "AS tools"); nutzt die
|
||||||
|
# gemeinsamen Build-Stufen aus dem Cache des ersten Builds.
|
||||||
|
- name: Werkzeuge bauen und pushen
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
target: tools
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta-tools.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta-tools.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
+20
@@ -52,6 +52,26 @@ RUN pnpm add --save-prod \
|
|||||||
@prisma/client@^7.9.1 @prisma/adapter-pg@^7.9.1 \
|
@prisma/client@^7.9.1 @prisma/adapter-pg@^7.9.1 \
|
||||||
@prisma/adapter-mariadb@^7.9.1 mariadb@^3.5.3
|
@prisma/adapter-mariadb@^7.9.1 mariadb@^3.5.3
|
||||||
|
|
||||||
|
# --- Werkzeuge (CronJobs) -------------------------------------------------
|
||||||
|
# Eigenes Image <repo>-tools fuer die Skripte unter scripts/, die als
|
||||||
|
# CronJob laufen (Bestandsabgleich mit ApiCore, Freigabe haengender
|
||||||
|
# Bestellungen), nach dem Muster von artista-modelcamp-tools. Das runner-
|
||||||
|
# Image enthaelt nur den Standalone-Output: dort fehlen tsconfig.json (der
|
||||||
|
# Pfad-Alias "@/") und Pakete wie stripe, die Skripte brechen dort mit
|
||||||
|
# "Cannot find module" ab. Steht VOR runner, damit ein Build ohne --target
|
||||||
|
# weiterhin das App-Image liefert.
|
||||||
|
FROM base AS tools
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 --ingroup nodejs nextjs
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/src ./src
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/scripts ./scripts
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/prisma ./prisma
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/prisma.config.ts /app/package.json /app/tsconfig.json ./
|
||||||
|
ENV PATH="/app/node_modules/.bin:${PATH}"
|
||||||
|
USER 1001
|
||||||
|
CMD ["tsx", "scripts/apicore-stock-sync.ts"]
|
||||||
|
|
||||||
# --- Runtime --------------------------------------------------------------
|
# --- Runtime --------------------------------------------------------------
|
||||||
FROM base AS runner
|
FROM base AS runner
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|||||||
+41
-12
@@ -8,9 +8,9 @@
|
|||||||
# ausserdem einer zehnjaehrigen Aufbewahrungspflicht (§ 147 AO) — ein
|
# ausserdem einer zehnjaehrigen Aufbewahrungspflicht (§ 147 AO) — ein
|
||||||
# Datenverlust ist hier nicht nur aergerlich, sondern ein Rechtsproblem.
|
# Datenverlust ist hier nicht nur aergerlich, sondern ein Rechtsproblem.
|
||||||
#
|
#
|
||||||
# Diese Sicherung liegt bewusst NUR im Cluster. Sie schuetzt gegen
|
# Diese Sicherung liegt auf derselben Storage Box wie die Datenbank. Sie
|
||||||
# Volume-Verlust und Bedienfehler, nicht gegen den Ausfall des gesamten
|
# schuetzt gegen Volume-Verlust und Bedienfehler, nicht gegen den Ausfall
|
||||||
# Clusters oder Standorts. Fuer eine vollstaendige Absicherung die
|
# der Storage Box oder des Standorts. Fuer eine vollstaendige Absicherung die
|
||||||
# erzeugten .sql.gz-Dateien zusaetzlich regelmaessig aus dem Cluster
|
# erzeugten .sql.gz-Dateien zusaetzlich regelmaessig aus dem Cluster
|
||||||
# herausziehen (Beispielbefehl siehe k8s/README.md, Abschnitt "Sicherung
|
# herausziehen (Beispielbefehl siehe k8s/README.md, Abschnitt "Sicherung
|
||||||
# und Wiederherstellung").
|
# und Wiederherstellung").
|
||||||
@@ -20,6 +20,33 @@
|
|||||||
# pg_dump-Aufruf unten ersetzen durch:
|
# pg_dump-Aufruf unten ersetzen durch:
|
||||||
# mysqldump -h wabenhain-mysql -u wabenhain -p"$PGPASSWORD" \
|
# mysqldump -h wabenhain-mysql -u wabenhain -p"$PGPASSWORD" \
|
||||||
# --single-transaction --routines wabenhain | gzip -9 > "$file.partial"
|
# --single-transaction --routines wabenhain | gzip -9 > "$file.partial"
|
||||||
|
# Ziel ist die Storage Box wie bei den uebrigen Wabenhain-Volumes. Das PV
|
||||||
|
# zeigt auf den vorhandenen Ordner Customer/Wabenhain; der Unterordner
|
||||||
|
# db-backup entsteht ueber subPath beim ersten Lauf.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: wabenhain-db-backup
|
||||||
|
spec:
|
||||||
|
capacity:
|
||||||
|
storage: 10Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
persistentVolumeReclaimPolicy: Retain
|
||||||
|
storageClassName: ""
|
||||||
|
mountOptions: ["vers=3.0", "uid=70", "gid=70", "dir_mode=0700", "file_mode=0600", "noperm"]
|
||||||
|
csi:
|
||||||
|
driver: smb.csi.k8s.io
|
||||||
|
volumeHandle: wabenhain-db-backup
|
||||||
|
volumeAttributes:
|
||||||
|
source: //u652065.your-storagebox.de/backup/Server/Disks/Customer/Wabenhain
|
||||||
|
nodeStageSecretRef:
|
||||||
|
name: smb-credentials
|
||||||
|
namespace: wabenhain
|
||||||
|
claimRef:
|
||||||
|
namespace: wabenhain
|
||||||
|
name: wabenhain-db-backup
|
||||||
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
@@ -28,7 +55,8 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
# storageClassName: "dein-storage-class"
|
storageClassName: ""
|
||||||
|
volumeName: wabenhain-db-backup
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
# Eine gzip-komprimierte Sicherung dieses Datenbestandes liegt im
|
# Eine gzip-komprimierte Sicherung dieses Datenbestandes liegt im
|
||||||
@@ -136,6 +164,7 @@ spec:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: backup
|
- name: backup
|
||||||
mountPath: /backup
|
mountPath: /backup
|
||||||
|
subPath: db-backup
|
||||||
# Nur lesend: dieser Job darf Belege sichern, niemals aendern.
|
# Nur lesend: dieser Job darf Belege sichern, niemals aendern.
|
||||||
- name: invoices
|
- name: invoices
|
||||||
mountPath: /invoices
|
mountPath: /invoices
|
||||||
@@ -209,17 +238,17 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
restartPolicy: OnFailure
|
restartPolicy: OnFailure
|
||||||
# Gleiche Kennung wie der App-Container (Dockerfile: adduser --uid
|
# Gleiche Kennung wie der App-Container (Dockerfile: adduser --uid
|
||||||
# 1001 nextjs) — dasselbe Image, derselbe Nutzer.
|
# 1001 nextjs) — beide Images legen denselben Nutzer an.
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsUser: 1001
|
runAsUser: 1001
|
||||||
runAsGroup: 1001
|
runAsGroup: 1001
|
||||||
containers:
|
containers:
|
||||||
- name: release-stale-orders
|
- name: release-stale-orders
|
||||||
# DASSELBE Image und derselbe Tag wie in 05-app-deployment.yaml.
|
# Werkzeug-Image (Dockerfile "AS tools") mit DEMSELBEN Tag wie
|
||||||
# Beide zusammen aktualisieren: der Lauf nutzt denselben
|
# das App-Image in 05-app-deployment.yaml. Beide zusammen
|
||||||
# Prisma-Client wie die App und muss deshalb zum selben
|
# aktualisieren: der Lauf nutzt denselben Prisma-Client wie die
|
||||||
# Datenbankschema passen.
|
# App und muss deshalb zum selben Datenbankschema passen.
|
||||||
image: git.encry.de/nick.rosenloecher/wabenhain:latest
|
image: git.encry.de/nick.rosenloecher/wabenhain-tools:latest
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
# Braucht DATABASE_URL, DATABASE_PROVIDER und STRIPE_SECRET_KEY
|
# Braucht DATABASE_URL, DATABASE_PROVIDER und STRIPE_SECRET_KEY
|
||||||
# — die stehen bereits in denselben beiden Quellen wie fuer die
|
# — die stehen bereits in denselben beiden Quellen wie fuer die
|
||||||
@@ -278,8 +307,8 @@ spec:
|
|||||||
runAsGroup: 1001
|
runAsGroup: 1001
|
||||||
containers:
|
containers:
|
||||||
- name: apicore-stock
|
- name: apicore-stock
|
||||||
# DASSELBE Image und derselbe Tag wie in 05-app-deployment.yaml.
|
# Werkzeug-Image mit demselben Tag wie in 05-app-deployment.yaml.
|
||||||
image: git.encry.de/nick.rosenloecher/wabenhain:latest
|
image: git.encry.de/nick.rosenloecher/wabenhain-tools:latest
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
# Braucht DATABASE_URL, DATABASE_PROVIDER, APICORE_API_URL und
|
# Braucht DATABASE_URL, DATABASE_PROVIDER, APICORE_API_URL und
|
||||||
# APICORE_API_KEY — dieselben Quellen wie die App.
|
# APICORE_API_KEY — dieselben Quellen wie die App.
|
||||||
|
|||||||
Reference in new issue
Block a user