Velero is the most popular tool for backing up and restoring Kubernetes cluster resources and persistent volumes. However, there may be situations where you need to restore Velero backup data without using Velero itself. For example, if Velero is not installed and configured correctly, or if more fine-grained restore control is required. In this post, we will explore how to do this when either Restic or Kopia was used by Velero to store the persistent volume (PV) data. We will be focusing on File System Backup using Velero version 1.11.0.
Restore Velero Backup Data with Restic
Restic is a backup program that can be used to back up and restore data. Velero can use Restic as an underlying tool to back up and restore persistent volume data. Let’s take a look at how we can use Restic to restore Velero backup data.
First, we need to identify the PVs that were backed up. In our test environment, we have 3 PVs, one is in test1 namespace and two in test2 namespace. We can use “kubectl get pvc –A” command to list PVCs in those namespaces:
$ kubectl get pvc -A NAMESPACE NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test1 mysql-data-disk1 Bound pvc-a0a58f73-4d7f-47d4-b92d-aa2a5642f7bd 1Gi RWO csi-hostpath-sc 6m25s test2 mysql-data-disk2 Bound pvc-ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47 1Gi RWO csi-hostpath-sc 6m42s test2 mysql-data-disk3 Bound pvc-0dd5e766-f358-419f-a214-7e2b85368709 1Gi RWO csi-hostpath-sc 6m42s
Next, we will run a couple of backups using the Restic uploader and see which objects are created on the target. We can do this by running “velero backup create” command with “–default-volumes-to-fs-backup” flag and specifying the namespaces to include in the backup:
$ velero backup create backup1 --default-volumes-to-fs-backup --include-namespaces test1,test2 $ velero backup create backup2 --default-volumes-to-fs-backup --include-namespaces test1,test2
On the target, we can see that a Restic repository was created for each namespace in “restic/<NAMESPACE>” and that there are snapshots present at “restic/<NAMESPACE>/snapshots” prefix.
$ aws s3 ls --recursive s3://mybucket | grep restic | awk '{print $4}' restic/test1/config ... restic/test1/snapshots/9c930f4d53ddd8c8ed4e119eeba8cb74fa90b3b49a1efb243f01d50d42aee174 restic/test1/snapshots/c51476a9678767089871616a2c98ed6a13c318ca4c0c4738e4df5329a0be1c7e ... restic/test2/config ... restic/test2/snapshots/13ab195139bbb634178d8acf6235fdb3026ef7749425f601ec01a0793da4972f restic/test2/snapshots/6aedee93c1fa2f7c7600292101353df7197ff9008bd552fb62429a0bd48a3a3b restic/test2/snapshots/bf4b58e1b60e02ea17550323447dd98e1ec60d12f173372481934b29bf86d610 restic/test2/snapshots/ce0c3c68c060c1e07c38d58d368804bf2389d7711048a5da288f1f3ab25d38ee
To get the list of snapshots for a specific namespace, we can use the Restic CLI. First, we need to set the AWS credentials to the ones that provide read-only access so we don’t inadvertently corrupt the repository. The repository password is by default set to “static-passw0rd” but can be changed. If “velero-repo-credentials” secret exists in the Velero namespace, get the repository password from “repository-password” key. We can then use the “restic snapshots” command to list the snapshots for the test2 namespace:
export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXX export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX $ cat restic-password static-passw0rd $ restic -p restic-password -r s3:s3.amazonaws.com/mybucket/restic/test2 snapshots repository f36a56ea opened (version 2, compression level auto) created new cache in /home/myuser/.cache/restic ID Time Host Tags Paths ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ce0c3c68 2023-07-13 16:08:29 velero backup=backup1,backup-uid=17d0cb28-c6fb-4849-bc34-614be8b02eab,ns=test2,pod=mysql-deployment2-776cc9bb8c-cbtt8,pod-uid=f21fb5fa-7f0a-41c3-b34b-7dace80555b1,pvc-uid=ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47,volume=mysql-data2 /host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47/mount 13ab1951 2023-07-13 16:08:39 velero backup=backup1,backup-uid=17d0cb28-c6fb-4849-bc34-614be8b02eab,ns=test2,pod=mysql-deployment2-776cc9bb8c-cbtt8,pod-uid=f21fb5fa-7f0a-41c3-b34b-7dace80555b1,pvc-uid=0dd5e766-f358-419f-a214-7e2b85368709,volume=mysql-data3 /host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-0dd5e766-f358-419f-a214-7e2b85368709/mount bf4b58e1 2023-07-13 16:56:35 velero backup=backup2,backup-uid=cecaf1af-8cd0-4a86-9cbc-e6c6812bc668,ns=test2,pod=mysql-deployment2 -776cc9bb8c-cbtt8,pod-uid=f21fb5fa-7f0a-41c3-b34b-7dace80555b1,pvc-uid=ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47,volume=mysql-data2 /host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47/mount 6aedee93 2023-07-13 16:56:39 velero pod-uid=f21fb5fa-7f0a-41c3-b34b-7dace80555b1,pvc-uid=0dd5e766-f358-419f-a214-7e2b85368709,volume=mysql-data3,backup=backup2,backup-uid=cecaf1af-8cd0-4a86-9cbc-e6c6812bc668,ns=test2,pod=mysql-deployment2-776cc9bb8c-cbtt8 /host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-0dd5e766-f358-419f-a214-7e2b85368709/mount
For each entry in the output, we can see the Velero backup name, PVC, and pod information. To restore one of these backups, we can use the “restic restore“ command, specifying the snapshot ID and target directory:
$ restic -p restic-password -r s3:s3.amazonaws.com/mybucket/restic/test2 restore ce0c3c68 --target restic_restore
repository f36a56ea opened (version 2, compression level auto)
restoring <Snapshot ce0c3c68 of [/host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47/mount] at 2023-07-13 20:08:29.888414931 +0000 UTC by root@velero> to restic_restore
After running the restore command, we can verify that the files were correctly restored by listing the contents of the restore target directory:
$ cd host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47/mount $ find . . ./mysql ./mysql/client-cert.pem ./mysql/ib_logfile1 ./mysql/ibdata1 ./mysql/mysql.sock ./mysql/server-cert.pem ./mysql/auto.cnf ./mysql/mysql ./mysql/mysql/time_zone_transition_type.frm ...
For more restore options see the Restic reference guide.
Restore Velero Backup Data with Kopia
Kopia is another tool that can be used to back up and restore data. Like Restic, Velero can use Kopia as an underlying tool to backup and restore persistent volume data. Let’s take a look at how we can use Kopia to restore Velero backup data.
First, we need to identify the objects created on the backup target when using Kopia as an uploader. Repeating the same test with Kopia produces files on the backup target with a similar structure as for Restic, with one repository per namespace:
2023-07-13 17:32:00 30 kopia/test1/kopia.blobcfg 2023-07-13 17:32:00 1075 kopia/test1/kopia.repository 2023-07-13 17:32:38 1638603 kopia/test1/p3cd8f09c4a983ccdcc46ee897a0df00f-sf6d58fcead1c49d511e 2023-07-13 17:32:22 21533338 kopia/test1/pad73ca1e8c11f292cabd9b485cecd2cc-sf6d58fcead1c49d511e ... 2023-07-13 17:32:40 30 kopia/test2/kopia.blobcfg 2023-07-13 17:32:40 1075 kopia/test2/kopia.repository 2023-07-13 17:32:44 24232396 kopia/test2/p0ddb521ca63b16cf927da6ec827e0bf1-sfcda7a530c4d9a0e11e 2023-07-13 17:33:01 21533338 kopia/test2/p39abaad7b2d64041a206a145339b6c7f-sfcda7a530c4d9a0e11e …
We can connect to the repository by using the Kopia CLI “repository connect“ command and providing our repository password. Make sure to use the read-only access-key so the repository does not accidentally get corrupted. Once connected, we can use the “kopia snapshot list” command to list the snapshots. PVC ID can be found as part of the source path:
$ kopia repository connect s3 --bucket=mybucket --access-key=XXXXXXXXXXXXX --secret-access-key=XXXXXXXXXXXXX --prefix=kopia/test1/ Enter password to open repository: static-passw0rd $ kopia snapshot list --all -l default@default:/host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-0dd5e766-f358-419f-a214-7e2b85368709/mount 2023-07-13 17:33:19 EDT k89d638fbdb3ac7ef7612f07a9da91e2e 0 B drwxr-xr-x files:0 dirs:2 (latest-2) 2023-07-13 17:48:00 EDT k89d638fbdb3ac7ef7612f07a9da91e2e 0 B drwxr-xr-x files:0 dirs:2 (latest-1,hourly-1,daily-1,weekly-1,monthly-1,annual-1) default@default:/host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47/mount 2023-07-13 17:32:43 EDT k2dc092f82bba74df45503df9d67ae208 219.5 MB drwxr-xr-x files:284 dirs:5 (latest-2) 2023-07-13 17:47:58 EDT k2dc092f82bba74df45503df9d67ae208 219.5 MB drwxr-xr-x files:284 dirs:5 (latest-1,hourly-1,daily-1,weekly-1,monthly-1,annual-1)
To restore PV data from a snapshot, we can use the “kopia snapshot restore” command, specifying the snapshot ID and path we are restoring:
$ kopia snapshot restore k2dc092f82bba74df45503df9d67ae208 host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47/mount Restoring to local filesystem (/home/myuser/kopia_restore/host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47/mount) with parallelism=8... Processed 83 (193.5 MB) of 289 (219.5 MB) 191.5 MB/s (88.2%) remaining 0s. Processed 184 (219 MB) of 289 (219.5 MB) 108.5 MB/s (99.8%) remaining 0s. Processed 290 (219.5 MB) of 289 (219.5 MB) 63.4 MB/s (100.0%) remaining 0s. Processed 290 (219.5 MB) of 289 (219.5 MB) 63.2 MB/s (100.0%) remaining 0s. Restored 284 files, 5 directories and 1 symbolic links (219.5 MB).
After running the restore command, we can see that our files were successfully restored:
$ cd host_pods/f21fb5fa-7f0a-41c3-b34b-7dace80555b1/volumes/kubernetes.io~csi/pvc-ae0b9b84-f9dd-4c57-8732-ab8ecb6aaa47/mount $ find . . ./mysql ./mysql/client-cert.pem ./mysql/ib_logfile1 ./mysql/ibdata1 ./mysql/mysql.sock ./mysql/server-cert.pem ./mysql/auto.cnf ./mysql/mysql ./mysql/mysql/time_zone_transition_type.frm …
For more restore options see the Kopia reference guide.
Conclusion
By running these tests, we demonstrated that it is possible to restore PVC data from a Velero backup when either Restic or Kopia was used to store the PVC data. This workflow provides a data recovery alternative in situations where Velero may not be available or more fine-grained restore control is required. For safety, we always want to use read-only credentials when accessing data directly.
CloudCasa offers both Velero management as a service as well as affordable open source support for customers adopting Velero. We provide value to existing Velero users by offering services that enhance the user experience and accessibility of it, such as an easy-to-use UI, a guided recovery path, monitoring and alerting, and support for multi-cluster and multi-cloud environments.
If you use Velero for backups today, we’d love to demonstrate how we can make your life easier. Sign up for the CloudCasa for Velero plan to get both CloudCasa features and commercial support for Velero.