feat(researchowl): daily SQLite backup CronJob + 5Gi backups PVC
Online-safe sqlite3 .backup at 03:00 Europe/Madrid, integrity check, 7-day retention. Data PVC mounted RW (WAL -shm requirement) but only read. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
---
|
||||
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: researchowl-backups
|
||||
namespace: researchowl
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
# DB is ~220MB and growing; 7 daily copies ≈ 1.6Gi, so 2Gi would fill up.
|
||||
storage: 5Gi
|
||||
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: researchowl-db-backup
|
||||
namespace: researchowl
|
||||
labels:
|
||||
app: researchowl
|
||||
spec:
|
||||
schedule: "0 3 * * *"
|
||||
timeZone: "Europe/Madrid"
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 3
|
||||
jobTemplate:
|
||||
spec:
|
||||
backoffLimit: 2
|
||||
activeDeadlineSeconds: 600
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: researchowl-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/researchowl-${STAMP}.db"
|
||||
echo "Backing up /data/researchowl.db -> ${DEST}"
|
||||
sqlite3 -cmd ".timeout 30000" /data/researchowl.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/researchowl-*.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
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "500m"
|
||||
volumes:
|
||||
# Same RWO local-path PVC as the bot: the PV's node affinity pins this
|
||||
# pod to the node where the data lives, so co-mounting is safe.
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: researchowl-data
|
||||
- name: backups
|
||||
persistentVolumeClaim:
|
||||
claimName: researchowl-backups
|
||||
Reference in New Issue
Block a user