apiVersion: v1 kind: PersistentVolumeClaim metadata: name: application-metier-postgres-backups namespace: application-metier spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 20Gi --- apiVersion: batch/v1 kind: CronJob metadata: name: application-metier-postgres-backup namespace: application-metier spec: schedule: "17 2 * * *" concurrencyPolicy: Forbid successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 3 jobTemplate: spec: backoffLimit: 2 ttlSecondsAfterFinished: 86400 template: metadata: labels: app.kubernetes.io/name: application-metier app.kubernetes.io/component: backup spec: restartPolicy: Never securityContext: runAsNonRoot: true runAsUser: 70 runAsGroup: 70 seccompProfile: type: RuntimeDefault fsGroup: 70 containers: - name: pg-dump image: postgres:17.10-alpine imagePullPolicy: IfNotPresent command: ["sh", "-ec"] args: - | umask 077 stamp="$(date -u +%Y%m%dT%H%M%SZ)" target="/backups/application-metier-${stamp}.dump" tmp="${target}.tmp.$$" cleanup() { rm -f "$tmp" } trap cleanup EXIT pg_dump --format=custom --no-owner --no-acl --file="$tmp" "$DATABASE_URL" test -s "$tmp" mv "$tmp" "$target" trap - EXIT ls -lh "$target" find /backups -type f -name 'application-metier-*.dump' -mtime +14 -delete env: - name: DATABASE_URL valueFrom: secretKeyRef: name: application-metier-secrets key: DATABASE_URL resources: requests: cpu: 25m memory: 64Mi limits: cpu: 500m memory: 256Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] volumeMounts: - name: backups mountPath: /backups volumes: - name: backups persistentVolumeClaim: claimName: application-metier-postgres-backups