vps cluster docs

0006. Backups run from the host with restic, not from inside the cluster

Context

Before this, there were no backups at all. The realistic loss scenarios, in order of likelihood, were: an accidental kubectl delete pvc (every dynamic PV was reclaim Delete), a bad migration or bad deployment, etcd corruption, filesystem corruption on /, and losing the VM.

The instinct is to run backups as a Kubernetes workload, because that is where the state looks like it lives. That instinct is wrong for the cases that matter most: a cluster that is broken — bad etcd, a wedged API server, a CrashLooping database — is exactly when you need the backup, and it is exactly when an in-cluster CronJob will not run. A backup system that shares a failure domain with the thing it protects is not a backup system.

Decision

Backups are driven from the host by systemd timers, dumping through each application’s own tools, then handed to restic.

Alternatives rejected

Consequences

Evidence

ansible/roles/backup/ (scripts, units, defaults), ansible/files/backup-targets.yaml, docs/backups.md, docs/runbooks/restore-*.md, and scripts/pull-backups.sh.