juntekim.com/mist_infra/scripts/backup_k8s_storage_to_s3.sh
Jun-te Kim adf255e574 save
2025-12-14 01:45:23 +00:00

119 lines
3 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
# -----------------------------
# Config
# -----------------------------
NAMESPACE="default"
PG_ENABLED=true
PG_SECRET_NAME="postgres-secret"
PG_POD_SELECTOR="app=postgres"
K8S_STORAGE_ROOT="/k8s_storage"
# NEVER touch Postgres raw data
TAR_EXCLUDES=(
"$K8S_STORAGE_ROOT/postgres"
)
BACKUP_ROOT="/tmp/k8s-backups"
DATE="$(date -u +%Y-%m-%d_%H-%M-%S)"
BACKUP_DIR="$BACKUP_ROOT/$DATE"
mkdir -p "$BACKUP_DIR"
echo "=== Backup started at $(date -u) ==="
# -----------------------------
# Postgres pg_dump (SAFE)
# -----------------------------
if [[ "$PG_ENABLED" == "true" ]]; then
echo "=== Postgres pg_dump enabled ==="
POSTGRES_POD=$(kubectl get pods \
-n "$NAMESPACE" \
-l "$PG_POD_SELECTOR" \
-o jsonpath='{.items[*].metadata.name}' | awk '{print $1}')
if [[ -z "$POSTGRES_POD" ]]; then
echo "❌ No Postgres pod found"
kubectl get pods -n "$NAMESPACE"
exit 1
fi
POSTGRES_USER=$(kubectl get secret "$PG_SECRET_NAME" \
-n "$NAMESPACE" \
-o jsonpath='{.data.POSTGRES_USER}' | base64 -d)
POSTGRES_DB=$(kubectl get secret "$PG_SECRET_NAME" \
-n "$NAMESPACE" \
-o jsonpath='{.data.POSTGRES_DB}' | base64 -d)
echo "Dumping database: $POSTGRES_DB"
kubectl exec -n "$NAMESPACE" "$POSTGRES_POD" -- \
pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" \
> "$BACKUP_DIR/postgres.sql"
echo "✔ pg_dump complete ($(du -h "$BACKUP_DIR/postgres.sql" | cut -f1))"
fi
# -----------------------------
# Normalise permissions (EXCLUDING POSTGRES)
# -----------------------------
echo "=== Normalising permissions (excluding Postgres) ==="
sudo find "$K8S_STORAGE_ROOT" \
-mindepth 1 \
-maxdepth 1 \
! -name postgres \
-exec chmod -R a+rX {} \; || true
# -----------------------------
# Build tar exclude args
# -----------------------------
TAR_EXCLUDE_ARGS=()
for path in "${TAR_EXCLUDES[@]}"; do
TAR_EXCLUDE_ARGS+=(--exclude="$path")
done
# -----------------------------
# Archive k8s storage (SAFE)
# -----------------------------
echo "=== Archiving k8s storage ==="
tar \
--ignore-failed-read \
--warning=no-file-changed \
-czf "$BACKUP_DIR/k8s_storage_$DATE.tar.gz" \
"${TAR_EXCLUDE_ARGS[@]}" \
"$K8S_STORAGE_ROOT"
echo "✔ k8s_storage archived ($(du -h "$BACKUP_DIR/k8s_storage_$DATE.tar.gz" | cut -f1))"
# -----------------------------
# Upload to S3
# -----------------------------
S3_BUCKET="s3://mist-backups/$DATE"
aws s3 cp "$BACKUP_DIR" "$S3_BUCKET" --recursive
echo "✔ Uploaded to $S3_BUCKET"
# -----------------------------
# Restore instructions
# -----------------------------
echo ""
echo "========================================"
echo "=== RESTORE GUIDE"
echo "========================================"
echo ""
echo "Restore volumes:"
echo " sudo tar -xzf k8s_storage_$DATE.tar.gz -C /"
echo ""
echo "Restore Postgres:"
echo " kubectl exec -n $NAMESPACE -i $POSTGRES_POD -- \\"
echo " psql -U $POSTGRES_USER $POSTGRES_DB < postgres.sql"
echo ""
echo "=== Backup completed successfully ==="