Add Ansible-driven DR bootstrap (#9) + PVC capture in backups
restore-k8s-apps.sh's own header explicitly scoped out fresh-cluster
provisioning ("assumes the target cluster/namespaces/PVCs already
exist"). This adds exactly that missing piece as an Ansible playbook
rather than another bash script — a better fit for "provision a target
into a working state" than for the actual data-restore logic, which stays
in restore-k8s-apps.sh unchanged and is just invoked as the final step.
dr-bootstrap.yml, given an app name + a backup archive:
1. Checks the target's environment (disk/mem/cpu) against k3s minimums
before touching anything
2. Installs k3s only if not already present (checked, not assumed)
3. Creates the namespace, PVC(s), Secret, and Deployments/Services/
Ingress from the backup's captured manifests — sanitized first
(sanitize_k8s_manifest.py strips resourceVersion/uid/status/
volumeName, the same class of bug as the earlier Secret-apply fix,
generalized) since a raw `kubectl get -o yaml` dump can't be
reapplied to a different cluster as-is
4. Hands off to the existing, already-validated restore-k8s-apps.sh for
the actual data population
backup-k8s-apps.sh gets a small but necessary addition: PVC specs were
never captured at all before (only Deployment/Service/ConfigMap/Ingress),
so there was nothing for a fresh-cluster bootstrap to provision the PVC
from. Captured with the same label selector as the existing manifests
capture, so it stays in lockstep automatically.
Verified for real, not just syntax-checked: ran the full playbook against
the standby VM (freshly installed k3s, empty namespace) using a live n8n
backup. Namespace/PVCs/Secret/Deployments provisioned from nothing, data
restored, pod healthy, and the workflow count in the restored Postgres DB
(11) matched the real source server exactly.
This commit is contained in:
@@ -306,6 +306,19 @@ for app in $ALL_APPS; do
|
||||
&& { echo "✅"; rm -f "$APP_DIR/manifests.err"; } \
|
||||
|| { echo "⚠️ FAILED (see manifests.err)"; ERRORS+=("$app:manifests:$(tr '\n' ' ' < "$APP_DIR/manifests.err" | cut -c1-200)"); }
|
||||
|
||||
# ---- 1b. PVC specs — NOT covered by the manifests capture above, and
|
||||
# needed to provision a namespace from scratch on a fresh/DR
|
||||
# cluster (restore-k8s-apps.sh assumes the PVC already exists;
|
||||
# this is what actually creates it there). Same label selector
|
||||
# as the manifests capture, so this stays in lockstep with
|
||||
# whatever PVCs are actually labeled as ours — no separate
|
||||
# per-app name table to keep in sync. ----
|
||||
echo -n " 💾 PVC specs ... "
|
||||
kubectl get pvc -n "$ns" -l owner=ameni-boukattaya -o yaml \
|
||||
> "$APP_DIR/pvc.yaml" 2>"$APP_DIR/pvc.err" \
|
||||
&& { echo "✅"; rm -f "$APP_DIR/pvc.err"; } \
|
||||
|| { echo "⚠️ FAILED (see pvc.err)"; ERRORS+=("$app:pvc_spec:$(tr '\n' ' ' < "$APP_DIR/pvc.err" | cut -c1-200)"); }
|
||||
|
||||
# ---- 2. Secret (plaintext, encryption-at-rest deferred) ----
|
||||
echo -n " 🔑 Secret ($secret_name) ... "
|
||||
kubectl get secret "$secret_name" -n "$ns" -o yaml \
|
||||
|
||||
Reference in New Issue
Block a user