[cnpg_backup.sh]
#!/bin/bash
set -euo pipefail
# All apps with CNPG are backed up or specify the names of the app deployment. E.g. "nextcloud" or "authentik-my-app-name"
# If the below doesn't work, try `APPS_TO_BACKUP=($(k3s kubectl get pods -A | grep postgresql | awk '{print $1}' | awk -F 'ix-' '{print $2}'))`
mapfile -t APPS_TO_BACKUP < <(k3s kubectl get pods -A | grep cnpg | awk '{print $1}' | awk -F 'ix-' '{print $2}' | sort | uniq | awk NF)
HOURS_TO_KEEP=240
CNPG_REPLICATION_GRACE=10
# Replace with the root folder where you want your backups to be
BACKUP_LOCATION="/mnt/pool0/backups/nas"
for APP_NAME in "${APPS_TO_BACKUP[@]}"; do
:
mkdir -p "$BACKUP_LOCATION/$APP_NAME"
BACKUP_FILE_NAME="$APP_NAME-$(date +%Y-%m-%d-%H-%M).sql.gz"
NAMESPACE="ix-$APP_NAME"
# Scale down deployment to avoid inconsistencies in DB
k3s kubectl scale deploy "$APP_NAME" -n "$NAMESPACE" --replicas=0
# Wait for pods to be scaled down
while true; do k3s kubectl get pods -n "$NAMESPACE" | grep -i -q terminating || break; done
echo "Sleeping for $CNPG_REPLICATION_GRACE seconds to allow replications to finish"
sleep $CNPG_REPLICATION_GRACE
echo "Replication grace period over"
POSTGRES_POD="$APP_NAME-cnpg-main-1"
# Find the correct DB name of the app
POSTGRES_DB=$(k3s kubectl exec -n "$NAMESPACE" -c "postgres" "$POSTGRES_POD" -- psql -t -c "SELECT datname FROM pg_database WHERE datistemplate = false AND datname NOT IN ('postgres', 'template0', 'template1')" | grep -v 'row' | tr -d '[:space:]')
# Dump Postgres DB
# shellcheck disable=SC2016
k3s kubectl exec -n "$NAMESPACE" -c "postgres" "$POSTGRES_POD" -- bash -c 'pg_dump -Fp -d '"$POSTGRES_DB" | gzip > "$BACKUP_LOCATION/$APP_NAME/${BACKUP_FILE_NAME}"
# Scale deployment back up
k3s kubectl scale deploy "$APP_NAME" -n "$NAMESPACE" --replicas=1
# Check if backup was successful and remove old backups
find "$BACKUP_LOCATION/$APP_NAME" -maxdepth 1 -mmin +$((HOURS_TO_KEEP * 60)) -name "$APP_NAME-*" -exec rm -rf '{}' ';'
if [ ! -f "$BACKUP_LOCATION/$APP_NAME/$BACKUP_FILE_NAME" ]; then
echo >&2 "$BACKUP_LOCATION/$APP_NAME/$BACKUP_FILE_NAME does not exist."
exit 1
fi
done
exit 0