Use Velero CSI Plugin with NetApp SolidFire and NetApp Trident 21.01
tldr
Using CSI Plugin (currently still in beta) Velero v1.5.3 can help protect Kubernetes apps and data on NetApp HCI or SolidFire (meaning, it can schedule and take Trident/SolidFire snapshots as well as backup application settings and data to a S3-compatible provider such as NetApp StorageGRID).
Since this support is currently in beta, on its own Velero is not suitable for enterprise use with SolidFire, but combined with native Trident/SolidFire snapshots it makes manual data protection tasks easier. If you're looking for a non-CSI approach with SolidFire, see this brief post for Velero with Restic and SolidFire.
Install Velero with CSI feature
Check the Trident, Velero, and AWS Provider (for S3-related stuff) documentation. If you're running a more recent Trident CSI, you'll probably need newer versions of various components including, but not limited to, Kubernetes external snapshotter.
$ velero install \
--features=EnableCSI \
--plugins velero/velero-plugin-for-csi:v0.1.2 \
...
I also used AWS S3 plugin and configured --backup-location-config to point to a NetApp StorageGRID bucket. I blogged about that in a recent post so I won't repeat those details in this post.
Significant differences compared to the earlier backup-related post featuring snapshots (that one was about Kasten K10):
- Kubernetes Volume Snapshot v1 (backward compatible with v1beta1)
- Velero v1.5.3 with CSI plugin (currently still in beta) v0.1.2
Backup
Velero CSI plugin can create SolidFire snapshots for you. You can see stuff like this in Velero logs:
time="2021-02-08T06:42:08Z" level=info msg="volumesnapshot class=csi-trident" backup=velero/nginx-backup cmd=/plugins/velero-plugin-for-csi logSource="/go/src/velero-plugin-for-csi/internal/backup/pvc_action.go:112" pluginName=velero-plugin-for-csi
time="2021-02-08T06:42:08Z" level=info msg="Created volumesnapshot nginx-example/velero-nginx-logs-59hqz" backup=velero/nginx-backup cmd=/plugins/velero-plugin-for-csi logSource="/go/src/velero-plugin-for-csi/internal/backup/pvc_action.go:142" pluginName=velero-plugin-for-csi
time="2021-02-08T06:42:08Z" level=info msg="Backing up item" backup=velero/nginx-backup logSource="pkg/backup/item_backupper.go:121" name=velero-nginx-logs-59hqz namespace=nginx-example resource=volumesnapshots.snapshot.storage.k8s.io
time="2021-02-08T06:42:08Z" level=info msg="Executing custom action" backup=velero/nginx-backup logSource="pkg/backup/item_backupper.go:327" name=velero-nginx-logs-59hqz namespace=nginx-example resource=volumesnapshots.snapshot.storage.k8s.io
time="2021-02-08T06:42:08Z" level=info msg="Executing VolumeSnapshotBackupItemAction" backup=velero/nginx-backup cmd=/plugins/velero-plugin-for-csi logSource="/go/src/velero-plugin-for-csi/internal/backup/volumesnapshot_action.go:58" pluginName=velero-plugin-for-csi
Seen from kubectl (not necessarily from the same run):
$ kubectl get volumesnapshot -n nginx-example
NAME READYTOUSE SOURCEPVC SOURCESNAPSHOTCONTENT RESTORESIZE SNAPSHOTCLASS SNAPSHOTCONTENT CREATIONTIME AGE
velero-nginx-logs-59hqz true nginx-logs 1Gi csi-trident snapcontent-1f2caa8a-543a-42fd-bcaf-a38c0e713faf 18m 18m
And also on SolidFire:
PS > Get-SFSnapshot
SnapshotID : 408
VolumeID : 192
Name : snapshot-1f2caa8a-543a-42fd-bcaf-a38c0e713faf
Checksum : 0xf2a1e04b664428f8
EnableRemoteReplication : False
ExpirationReason : None
ExpirationTime :
RemoteStatuses :
Status : done
SnapshotUUID : b122e0e9-8a47-4697-b74b-3f636dce00b8
TotalSize : 1073741824
GroupID : 0
GroupSnapshotUUID : 00000000-0000-0000-0000-000000000000
CreateTime : 2021-02-08T06:42:08Z
InstanceCreateTime : 2021-02-08T06:42:08Z
VolumeName : pvc-2f361c68-cfef-41ae-83b3-01990187d061
InstanceSnapshotUUID : b122e0e9-8a47-4697-b74b-3f636dce00b8
VirtualVolumeID :
Attributes :
SnapMirrorLabel :
Application backup according to Velero:
$ velero backup describe nginx-backup
Name: nginx-backup
Namespace: velero
Labels: velero.io/storage-location=default
Annotations: velero.io/source-cluster-k8s-gitversion=v1.19.7
velero.io/source-cluster-k8s-major-version=1
velero.io/source-cluster-k8s-minor-version=19
Phase: Completed
Errors: 0
Warnings: 0
Namespaces:
Included: *
Excluded: <none>
Resources:
Included: *
Excluded: <none>
Cluster-scoped: auto
Label selector: app=nginx
Storage Location: default
Velero-Native Snapshot PVs: auto
TTL: 720h0m0s
Hooks: <none>
Backup Format Version: 1.1.0
Started: 2021-02-08 06:42:03 +0000 UTC
Completed: 2021-02-08 06:42:13 +0000 UTC
Expiration: 2021-03-10 06:42:03 +0000 UTC
Total items to be backed up: 10
Items backed up: 10
Velero-Native Snapshots: <none included>
CSI Volume Snapshots: 2 included (specify --details for more information)
If we get the details of those CSI snapshots, we might see something like this:
CSI Volume Snapshots:
Snapshot Content Name: snapcontent-17c33032-f85c-4ad0-b0cd-6b77ecc75bc1
Storage Snapshot ID: pvc-b2d964f9-dbb5-414a-bb7d-7033d099ce27/snapshot-17c33032-f85c-4ad0-b0cd-6b77ecc75bc1
Snapshot Size (bytes): 1073741824
Ready to use: true
Snapshot Content Name: snapcontent-1f2caa8a-543a-42fd-bcaf-a38c0e713faf
Storage Snapshot ID: pvc-2f361c68-cfef-41ae-83b3-01990187d061/snapshot-1f2caa8a-543a-42fd-bcaf-a38c0e713faf
Snapshot Size (bytes): 1073741824
Ready to use: true
I haven't discovered a way to use snapshot information (or data) from Velero backups. It could be that Velero expects they're available (to read or mount) which is not the case with SolidFire snapshots (they need to be cloned before they can be used), or it could be that it simply isn't smart about non-vSAN snapshots. Either way, it's not a deal breaker for non-enterprise users as we shall see later.
Restore
If you nuke an app (or the namespace that contains it) but the volume remains, on restore volume and its snapshot causes a warning like this:
$ velero restore describe nginx-backup-20210208063937
Name: nginx-backup-20210208063937
Namespace: velero
Labels: <none>
Annotations: <none>
Phase: Completed
Started: 2021-02-08 06:39:37 +0000 UTC
Completed: 2021-02-08 06:39:40 +0000 UTC
Warnings:
Velero: <none>
Cluster: could not restore, volumesnapshotcontents.snapshot.storage.k8s.io "snapcontent-bcd021f1-0ce2-412b-8324-efad9ede4598" already exists. Warning: the in-cluster version is different than the backed-up version.
could not restore, persistentvolumes "pvc-0b51d0a1-5028-41b9-9773-885bf59ea2c4" already exists. Warning: the in-cluster version is different than the backed-up version.
If you delete an app, Velero 1.5.3 with CSI plugin recreates resources such as namespace, service, PVC, and Trident CSI responds to that by assigning a new PV (although the old one remains, in the Released state). velero restore allows you to --exclude-resources such as persistentvolumes,volumesnapshotcontents but I couldn't get this to behave the way I expected and/or consistently.
Some of these problems are known issues and I noticed consistency in certain problems (some of which I could duplicate and find in Velero issues on Github).
If an app, PVC and PV are all deleted, velero restore can re-create everything from scratch, but I did not make sure if the backup content from PV was properly restored to new PV. It's supposed to be, but obviously we'd want to know that before using it in production. In some cases kubectl reported the PVC was Bound but the PV wasn't even created.
One of the reasons I didn't verify restores was if we delete an app and its PVC, Trident CSI leaves the PV in Released state, and it should have at least one snapshot, too (assuming we used CSI snapshots). That means we can always get to our data (either reuse the volume, or clone the snapshot and import it to Kubernetes): if Velero correctly restored only service, deployment and other resources excluding PV data, that in itself should be quite helpful because SolidFire snapshots, clones and remote replicas deliver good data protection.
In fact we can download Velero backup manifest and see what's in it.
$ tar fzvx nginx-backup-data.tar.gz
metadata/version
resources/persistentvolumes/v1-preferredversion/cluster/pvc-bff0a51f-1430-4beb-96d4-1fe668031b66.json
resources/persistentvolumes/cluster/pvc-bff0a51f-1430-4beb-96d4-1fe668031b66.json
resources/persistentvolumeclaims/v1-preferredversion/namespaces/nginx-example/nginx-logs.json
resources/persistentvolumeclaims/namespaces/nginx-example/nginx-logs.json
resources/pods/v1-preferredversion/namespaces/nginx-example/nginx-deployment-66689547d-7k26g.json
resources/pods/namespaces/nginx-example/nginx-deployment-66689547d-7k26g.json
resources/services/v1-preferredversion/namespaces/nginx-example/my-nginx.json
resources/services/namespaces/nginx-example/my-nginx.json
resources/endpoints/v1-preferredversion/namespaces/nginx-example/my-nginx.json
resources/endpoints/namespaces/nginx-example/my-nginx.json
resources/namespaces/v1-preferredversion/cluster/nginx-example.json
resources/namespaces/cluster/nginx-example.json
resources/replicasets.apps/v1-preferredversion/namespaces/nginx-example/nginx-deployment-66689547d.json
resources/replicasets.apps/namespaces/nginx-example/nginx-deployment-66689547d.json
From file names (pvc-bff0a51f-1430-4beb-96d4-1fe668031b66.json) it's easy to tell PV name, and if we look inside of these files we can find other useful details:
"resources":{"requests":{"storage":"1Gi"}},
"storageClassName":"solidfire-silver",
"volumeMode":"Filesystem",
"volumeName":"pvc-bff0a51f-1430-4beb-96d4-1fe668031b66"},
"status":{"accessModes":["ReadWriteOnce"],"capacity":{"storage":"1Gi"},"phase":"Bound"}}
With that we can easily find which volume (or snapshot) can be used to restore data from a storage-side backup (SolidFire snapshot or existing volume, which can be cloned).
This approach is currently used by some users who have similar problems (example: create a PVC first, followed by a Velero restore).
Conclusion
Velero's CSI feature, even in beta, is useful because it can schedule your Trident CSI snapshots and at the same time backup application settings to a remote location (similar to Rancher snapshots I wrote about here).
While Velero currently isn't production-ready for use with CSI storage (at least not with NetApp SolidFire), there may be situations where division of labor (or automation, as the case may be) can be put in place so that both Velero and NetApp Trident/SolidFire (snapshot, clone, import) features are used to make the job of data protection easier.
Additional investigation is required to better understand (or maybe TFM is clear and it's just me?) backup and restore behavior in various situations:
- Backup with and without CSI support
- Backup with and without Restic support
- Restore with CSI support when PVC is, and is not, deleted
- Restore with CSI support when PVC and PV are, and aren't, deleted
- The use of Velero exclude and include options
- The effect of "freeze" (quiesce) options
- The use of other Velero options and optimal approaches for various backup and restore scenarios
Video demo
Find it here.
Notes
- Kubernetes v1.19.7
- Kubernetes Volume Snapshot v1
- NetApp Trident 21.01
- NetApp SolidFire 12.2 as Trident back-end
- Velero 1.5.3
- Velero CSI v0.1.2 (beta)
- Velero AWS plugin v1.1.0
- NetApp StorageGRID 11.4