Losing your main server is scary, but a real recovery test is the only way to know your backups actually work. This guide provides a full Kubernetes disaster recovery drill with Velero and Longhorn.
This guide is not about setting up backups; it is the actual test. We will break the old cluster, set up new servers, and bring everything back with proof it worked. If you plan to set up backups, you can check this guide on backing up K3s with Velero.
What the Cluster Looked Like Before the Crash
Before we break anything, here is the setup we are protecting. A small and real-world K3s cluster with:
- One main K3s server node, which stores all cluster data.
- Two or three worker nodes running the app.
- Longhorn installed to copy storage across the workers, following our Longhorn on K3s with NVMe setup guide.
- Velero installed with an S3-style storage bucket to hold backups.
- A small test app, a web app with a database, using storage from Longhorn.
This is why teams test Kubernetes disaster recovery with Velero and Longhorn together. The main server holds the cluster's memory, Velero holds the app files and settings, and Longhorn holds the real data on disk. You need all three to come back safely. None of them can protect you alone.
Prerequisites and Tools You Need
For the Kubernetes disaster recovery with Velero and Longhorn drill, you will need:
- Root or sudo access on all servers.
- At least one new master server and two new worker servers, on the same network as, or reachable from, the old cluster's DNS/load balancer.
- A remote, S3-compatible bucket that survived the disaster. This is where your etcd snapshot, Velero backups, and Longhorn backups already live.
kubectl and helm installed on your workstation.
- The Velero CLI matching the server version.
- A basic understanding of Linux systemd services is helpful, since K3s runs as a systemd unit.
If you are rebuilding for real, not just practicing, use fresh, clean servers instead of reusing the old ones. Using dedicated servers for hosting gives you steady CPU, RAM, and NVMe storage for both the main server and the Longhorn copies.
Step 1: Take the Backups You Will Restore From
If you already run scheduled backups, skip to Step 2. If not, take fresh ones now so the drill has something real to restore.
Save an etcd snapshot: On the master node, run:
sudo k3s etcd-snapshot save --name pre-disaster-snapshot
Push it to S3 so it survives even if the whole server disappears:
sudo k3s etcd-snapshot save \ --name pre-disaster-snapshot \ --s3 \ --s3-bucket=k3s-dr-backups \ --s3-endpoint=s3.amazonaws.com \ --s3-region=us-east-1 \ --s3-access-key="$AWS_ACCESS_KEY" \ --s3-secret-key="$AWS_SECRET_KEY"
List snapshots to confirm it:
sudo k3s etcd-snapshot ls
Take a Velero backup with the commands below:
velero backup create pre-disaster-backup --waitvelero backup describe pre-disaster-backup
Take a Longhorn backup: Open the Longhorn UI or use kubectl and run a backup for each volume. Or create a full Longhorn System Backup so you can restore the whole storage state in one shot:
kubectl apply -f - <<EOFapiVersion: longhorn.io/v1beta2kind: SystemBackupmetadata: name: pre-disaster-system-backupspec: volumeBackupPolicy: IfNotPresentEOF
Check that it is finished:
kubectl get systembackup pre-disaster-system-backup -n longhorn-system
At this point, you have everything you need to run a real Kubernetes disaster recovery test with Velero and Longhorn. Write down the exact time of each backup. You will compare this to when your restore finishes to measure your RPO and RTO.
Step 2: Break the Main Server on Purpose
To make the test real, actually turn off the main server:
sudo systemctl stop k3ssudo /usr/local/bin/k3s-uninstall.sh
If you want to be extra sure, boot into a rescue image and wipe the disk. Or just turn the server off and leave it off for the rest of the test. Do not touch the worker nodes yet. We will rebuild the whole cluster from scratch anyway.
Step 3: Prepare New Servers for the Rebuild
At this point, you must set up new servers to replace the old ones. Give each Longhorn copy its own NVMe or SSD disk, since Longhorn works best with fast local disks, not shared network storage.
If you need servers fast, PerLod's Dedicated Server is the quickest way to get real CPU, RAM, and NVMe you fully control, with no wait for cloud setup.
For this drill, we use three new machines:
new-master-1: Will become the master node.
new-worker-1 and new-worker-2: Will run the application pods and Longhorn replicas.
Make sure all three can reach each other over the network, and update your DNS record or load balancer to point at the new master node IP once it is ready.
Step 4: Restore etcd on the New Master Node
This is the main part of the Kubernetes disaster recovery drill with Velero and Longhorn: get Kubernetes running again before touching your apps.
First, you must copy the etcd snapshot to new-master-1, or pull it directly from S3 during the restore.
Install K3s in a stopped state so it does not try to form a cluster before the restore:
curl -sfL https://get.k3s.io | INSTALL_K3S_CHANNEL=stable INSTALL_K3S_SKIP_START=true sh -
This installs the current stable K3s release line with the matching embedded etcd version.
Restore from the local snapshot file:
sudo k3s server \ --cluster-init \ --cluster-reset \ --cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/pre-disaster-snapshot \ --token="$OLD_CLUSTER_TOKEN"
Or restore straight from S3 if you did not copy the file locally:
sudo k3s server \ --cluster-init \ --cluster-reset \ --cluster-reset-restore-path=pre-disaster-snapshot \ --etcd-s3 \ --etcd-s3-bucket=k3s-dr-backups \ --etcd-s3-endpoint=s3.amazonaws.com \ --etcd-s3-region=us-east-1 \ --etcd-s3-access-key="$AWS_ACCESS_KEY" \ --etcd-s3-secret-key="$AWS_SECRET_KEY" \ --token="$OLD_CLUSTER_TOKEN"
Once the reset process finishes, K3s exits by itself. Start it normally as a service:
Confirm the cluster is alive and remembers the old state:
sudo k3s kubectl get nodessudo k3s kubectl get namespaces
You should see the old namespaces already listed, because etcd holds the full Kubernetes object database, even though the actual Pods are not running yet.
Now join the two new workers using the same server URL and token:
curl -sfL https://get.k3s.io | INSTALL_K3S_CHANNEL=stable K3S_URL=https://new-master-1:6443 K3S_TOKEN="$OLD_CLUSTER_TOKEN" sh -
Run this on both new-worker-1 and new-worker-2.
Step 5: Restore Namespaces and Resources with Velero
The etcd restore already brings back most of the cluster's data. But in most real disasters, you start etcd fresh, a clean --cluster-init with no snapshot, and let Velero bring back all your app files and settings. Either way, this step checks that Velero can put everything back correctly.
Install Velero on the new cluster, pointing at the same backup storage location:
velero install \ --provider aws \ --plugins velero/velero-plugin-for-aws:v1.11.0 \ --bucket k3s-dr-backups \ --backup-location-config region=us-east-1,s3Url=https://s3.amazonaws.com \ --secret-file ./credentials-velero \ --use-node-agent
Check the backup storage location is reachable and set it to read-only so nothing overwrites your backup while restoring:
kubectl get backupstoragelocation -n velerokubectl patch backupstoragelocation default \ --namespace velero \ --type merge \ --patch '{"spec":{"accessMode":"ReadOnly"}}'
List the available backups and restore the last one:
velero backup getvelero restore create --from-backup pre-disaster-backup --wait
Watch the restore progress and confirm it finished without errors:
velero restore describe pre-disaster-backup-<timestamp>kubectl get pods -A
Switch the backup storage location back to read-write once the restore is confirmed:
kubectl patch backupstoragelocation default \ --namespace velero \ --type merge \ --patch '{"spec":{"accessMode":"ReadWrite"}}'
This is where a Kubernetes disaster recovery drill with Velero and Longhorn really shows up. You find out fast if your labels, settings, passwords, and app files come back the way you expect.
Step 6: Restore Longhorn Volumes on the New Cluster
Pods will come back from Velero, but they will not have data yet because Longhorn volumes need their own restore step.
Install Longhorn on the new cluster with Helm, matching the setup guide:
helm repo add longhorn https://charts.longhorn.iohelm repo updatehelm install longhorn longhorn/longhorn \ --namespace longhorn-system \ --create-namespace \ --version 1.10.2
Point Longhorn at the same backup target used before:
kubectl -n longhorn-system patch setting.longhorn.io backup-target \ --type merge \ --patch '{"value":"s3://longhorn-dr-backups@us-east-1/"}'kubectl -n longhorn-system patch setting.longhorn.io backup-target-credential-secret \ --type merge \ --patch '{"value":"longhorn-backup-secret"}'
If you took a full System Backup earlier, restore everything at once with a SystemRestore resource:
kubectl apply -f - <<EOFapiVersion: longhorn.io/v1beta2kind: SystemRestoremetadata: name: post-disaster-restorespec: systemBackup: pre-disaster-system-backupEOF
If you backed up individual volumes instead, restore each one by creating a new volume from its backup:
kubectl apply -f - <<EOFapiVersion: longhorn.io/v1beta1kind: Volumemetadata: name: app-data-restored namespace: longhorn-systemspec: size: "20Gi" numberOfReplicas: 3 fromBackup: "s3://longhorn-dr-backups@us-east-1/?backup=backup-xxxx&volume=app-data"EOF
Then re-point the application's PersistentVolumeClaim to the restored volume, or restore the PVC/PV objects through Velero and let Longhorn's CSI driver bind them automatically.
Check volume health once restored:
kubectl get volumes.longhorn.io -n longhorn-systemkubectl get pvc -A
Restart any pods that were stuck waiting for storage:
kubectl rollout restart deployment -n <your-app-namespace>
Step 7: Reissue Certificates and Fix Networking
New servers usually mean new security certificates. K3s makes its own internal certificates again on its own when you run a fresh --cluster-init, so you usually don't need to fix those. Here is what you do need to check:
- If you use cert-manager for your app's HTTPS, its saved certificates come back through the Velero restore. But you may need new ones if the DNS check now points to a different IP address.
- Update your DNS records or load balancer to point to the new server IPs.
- If you use your own private certificate authority, copy its key files onto the new servers before starting anything that needs them.
- Run
kubectl get certificate -A and kubectl describe certificate <name> to check that cert-manager made new certificates for anything that expired or pointed to an old IP.
A good Kubernetes disaster recovery plan with Velero and Longhorn should always note which certificates fix themselves and which ones need manual work after a DNS change.
Step 8: Validate RPO and RTO
Getting pods to Running is not the finish line. You must check that your data is really correct, and time how long the whole recovery took.
Check application data matches what you expect from the last backup:
kubectl exec -it <app-pod> -- <command to check data, e.g. a row count or file checksum>
Compare this with the note you took before the drill or the backup time to calculate your real RPO.
To calculate your RTO, compare the time you shut down the old cluster in Step 2 with the time your app became fully healthy again:
kubectl get pods -A -o widekubectl top nodes
Run your normal smoke tests: Load the app in a browser, hit its health endpoint, check that background jobs resume:
curl -I https://your-app.example.com/health
Write down both numbers. If your RTO is too slow for your business, try keeping backup servers ready, or turn Steps 3 to 7 into scripts to cut down manual work. This full test is the only sure way to know your Kubernetes disaster recovery plan with Velero and Longhorn really meets your goals.
Conclusion
A backup you have never restored is just a guess. By breaking your main server on purpose and rebuilding it on new servers, you get real proof that your Kubernetes disaster recovery plan with Velero and Longhorn works. Also, you get real RPO and RTO numbers you can share with your team.
We hope you enjoy this guide. For more information on the restore workflow and the read-only backup storage location pattern, you can check the Velero disaster recovery documentation.