gates / gates (push) Successful in 12m24s
R-232 dated note + a dated check for tonight's sweep; R-934 closed (the disk was pulled 2026-10-23); R-1250 fixed on main, live proof on demo-hp with a real seed; 08 §9 item 5. Evidence audits/dooplex-alarms-2026-10-24/.
152 lines
5.4 KiB
Plaintext
152 lines
5.4 KiB
Plaintext
# ============================================================================
|
|
# postgresql-1 logical backup — 6-hourly pg_dump to HDD5 (rides Restic)
|
|
# ----------------------------------------------------------------------------
|
|
# The shared CNPG cluster `postgresql` (database-system, single instance) had no
|
|
# backup. This CronJob does a LOGICAL backup every 6h:
|
|
# - pg_dumpall --globals-only -> globals.sql (roles/grants; needed for restore)
|
|
# - pg_dump -Fc per database -> <db>.dump (custom format; selective restore)
|
|
# written to hostPath /mnt/5_hdd/backup/postgresql/dumps/<timestamp>/ (HDD5, OFF
|
|
# the DB's own HDD4 disk). The host backup flow (/opt/backup, backup-postgresql.sh)
|
|
# then restic-backs-up that dir in its daily run (7d/4w/6m retention). Local
|
|
# retention here = 3 days. RPO <=6h, no PITR (accepted).
|
|
#
|
|
# Auth: connects to postgresql-rw as the CNPG-managed superuser (secret
|
|
# `postgres-superuser`, keys username/password). Requires enableSuperuserAccess:
|
|
# true on the Cluster (set in postgresql-cluster.yaml). The superuser is the only
|
|
# role that can read every DB + dump globals; per-app roles cannot.
|
|
#
|
|
# Freshness alert: kube_cronjob_status_last_successful_time (KSM) — see
|
|
# mon-system/prometheus-rules.yaml (PostgresqlDumpStale, >12h).
|
|
# ============================================================================
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: postgresql-backup-script
|
|
namespace: database-system
|
|
labels:
|
|
app.kubernetes.io/name: postgresql-backup
|
|
app.kubernetes.io/instance: postgresql-backup
|
|
data:
|
|
pg-backup.sh: |
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
export PGHOST="${PGHOST:-postgresql-rw}" PGPORT="${PGPORT:-5432}"
|
|
TS="$(date +%Y%m%d-%H%M%S)"
|
|
OUT="/backup/dumps/${TS}"
|
|
mkdir -p "${OUT}"
|
|
echo "[pgbackup] ${TS} -> ${OUT}"
|
|
|
|
echo "[pgbackup] globals (roles/grants)"
|
|
pg_dumpall --globals-only > "${OUT}/globals.sql"
|
|
|
|
mapfile -t DBS < <(psql -tAc \
|
|
"SELECT datname FROM pg_database WHERE NOT datistemplate AND datallowconn ORDER BY 1;")
|
|
echo "[pgbackup] databases: ${DBS[*]}"
|
|
for db in "${DBS[@]}"; do
|
|
echo "[pgbackup] pg_dump -Fc ${db}"
|
|
pg_dump -Fc -d "${db}" -f "${OUT}/${db}.dump"
|
|
done
|
|
|
|
touch "${OUT}/SUCCESS"
|
|
echo "[pgbackup] pruning local dumps older than 3 days"
|
|
find /backup/dumps -mindepth 1 -maxdepth 1 -type d -mtime +3 -exec rm -rf {} + || true
|
|
echo "[pgbackup] done"
|
|
ls -lh "${OUT}"
|
|
---
|
|
apiVersion: batch/v1
|
|
kind: CronJob
|
|
metadata:
|
|
name: postgresql-backup
|
|
namespace: database-system
|
|
labels:
|
|
app.kubernetes.io/name: postgresql-backup
|
|
app.kubernetes.io/instance: postgresql-backup
|
|
spec:
|
|
schedule: "0 */6 * * *"
|
|
timeZone: "Europe/Budapest"
|
|
concurrencyPolicy: Forbid
|
|
successfulJobsHistoryLimit: 3
|
|
failedJobsHistoryLimit: 3
|
|
startingDeadlineSeconds: 600
|
|
jobTemplate:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: postgresql-backup
|
|
app.kubernetes.io/instance: postgresql-backup
|
|
spec:
|
|
backoffLimit: 2
|
|
activeDeadlineSeconds: 1800
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: postgresql-backup
|
|
app.kubernetes.io/instance: postgresql-backup
|
|
annotations:
|
|
# postgres image is pinned to the CNPG cluster's version (X.Y)
|
|
match-regex.version-checker.io/pgbackup: '^\d+\.\d+$'
|
|
spec:
|
|
enableServiceLinks: false
|
|
restartPolicy: OnFailure
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 26
|
|
runAsGroup: 26
|
|
fsGroup: 26
|
|
containers:
|
|
- name: pgbackup
|
|
# MUST match the CNPG cluster's Postgres version (pg_dump >= server).
|
|
image: ghcr.io/cloudnative-pg/postgresql:17.2
|
|
imagePullPolicy: IfNotPresent
|
|
command: ["/bin/bash", "/scripts/pg-backup.sh"]
|
|
env:
|
|
- name: PGHOST
|
|
value: postgresql-rw
|
|
- name: PGPORT
|
|
value: "5432"
|
|
- name: PGUSER
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: postgresql-superuser
|
|
key: username
|
|
- name: PGPASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: postgresql-superuser
|
|
key: password
|
|
- name: HOME
|
|
value: /tmp
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 128Mi
|
|
limits:
|
|
cpu: "1"
|
|
memory: 512Mi
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop:
|
|
- ALL
|
|
volumeMounts:
|
|
- name: script
|
|
mountPath: /scripts
|
|
readOnly: true
|
|
- name: backup
|
|
mountPath: /backup
|
|
- name: tmp
|
|
mountPath: /tmp
|
|
volumes:
|
|
- name: script
|
|
configMap:
|
|
name: postgresql-backup-script
|
|
defaultMode: 0755
|
|
- name: backup
|
|
hostPath:
|
|
path: /mnt/5_hdd/backup/postgresql
|
|
type: Directory
|
|
- name: tmp
|
|
emptyDir:
|
|
sizeLimit: 256Mi
|