--- apiVersion: v1 kind: PersistentVolumeClaim metadata: annotations: # Never let ArgoCD prune this PVC: it holds the DB backups. argocd.argoproj.io/sync-options: Prune=false name: reddit-intel-backups namespace: reddit-intel spec: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi --- apiVersion: batch/v1 kind: CronJob metadata: name: reddit-intel-db-backup namespace: reddit-intel labels: app: reddit-intel spec: schedule: "0 3 * * *" timeZone: "Europe/Madrid" concurrencyPolicy: Forbid successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 3 jobTemplate: spec: backoffLimit: 2 activeDeadlineSeconds: 600 template: metadata: labels: app: reddit-intel-db-backup spec: restartPolicy: Never containers: - name: backup image: keinos/sqlite3:latest command: - /bin/sh - -c - | set -eu STAMP=$(date +%Y%m%d) DEST="/backups/reddit-intel-${STAMP}.db" echo "Backing up /data/reddit-intel.db -> ${DEST}" sqlite3 -cmd ".timeout 30000" /data/reddit-intel.db ".backup '${DEST}'" RESULT=$(sqlite3 "${DEST}" "PRAGMA integrity_check;") if [ "${RESULT}" != "ok" ]; then echo "Integrity check FAILED: ${RESULT}" rm -f "${DEST}" exit 1 fi echo "Integrity check ok" # Retention: keep the 7 most recent backups for f in $(ls -1t /backups/reddit-intel-*.db | tail -n +8); do echo "Pruning old backup ${f}" rm -f "${f}" done ls -lh /backups/ volumeMounts: # NOT readOnly: the source DB runs in WAL mode and sqlite readers # must be able to touch the -shm/-wal sidecar files. The job only # ever reads the DB (.backup); it never modifies application data. - name: data mountPath: /data - name: backups mountPath: /backups volumes: - name: data persistentVolumeClaim: claimName: reddit-intel-data - name: backups persistentVolumeClaim: claimName: reddit-intel-backups