Tech ONTAP Blogs
Tech ONTAP Blogs
NetApp Trident Protect enables you to back up and restore KubeVirt virtual machines (VMs) running on OpenShift Virtualization or KubeVirt. You can protect all VMs across one or more namespaces at once or use the newly introduced includedVirtualMachines field to target specific VMs by name. Trident Protect automatically collects all dependent VM resources during backup, and during restore, you can recover the entire archive or selectively restore individual VMs.
Trident Protect supports two ways to define which KubeVirt VMs to protect. You choose one mode when you define a VM application in Trident Protect:
|
Mode |
Field |
Description |
|
Namespace-based |
includedNamespaces |
Protect all matching resources in one or more namespaces. Use a labelSelector on the namespace entry to control which VMs are included dynamically. |
|
VM-scoped |
includedVirtualMachines |
Protect specific KubeVirt VMs by namespace and name. Use this mode when VMs are spread across namespaces or when you do not want to protect all namespace resources. |
You must specify exactly one field (includedNamespaces or includedVirtualMachines) in the ApplicationSpec. You cannot use both in the same application. For details, see the Trident Protect documentation.
In this blog post, we’ll show you examples for both application definition modes, and how to restore VM selectively.
We demonstrate the use of Trident Protect resource transformations on an OpenShift cluster which has NetApp Trident and Trident Protect version 26.06 already installed and configured. Resource transformations are supported starting with Trident Protect 26.06.
As virtual machines, we have deployed three oVirt VMs in two namespaces.
$ kubectl get vm -A
NAMESPACE NAME AGE STATUS READY
pu-vm1 pu-vm1 30d Running True
pu-vm1 pu-vm1a 30d Running True
pu-vm2 pu-vm2 20d Running True
An appVault custom resource (CR) is configured to store the data and metadata backups as well.
$ tridentctl-protect get appvault
+------------------------------------+----------+-----------+-------+---------+--------+
| NAME | PROVIDER | STATE | ERROR | MESSAGE | AGE |
+------------------------------------+----------+-----------+-------+---------+--------+
| bucket-azure-b8lteoiumb-unca86uqsh | Azure | Available | | | 84d23h |
+------------------------------------+----------+-----------+-------+---------+--------+
We want to protect only the two VMs pu-vm1 and pu-vm2 out of the three VMs in the two namespaces. An easy way to achieve this is to create a Trident Protect application using the includedVirtualMachines field in the app definition.
The Trident Protect CLI tridentctl-protect has introduced a new flag --virtual-machines that can be used to select specific VM in one or more namespaces:
--virtual-machines string Virtual machines to include in application, format: namespace1(vm1,vm2),namespace2(vm3).
We can create an application my-vms containing the two VMs we want to protect with this CLI command.
$ tridentctl-protect create app my-vms --virtual-machines "pu-vm1(pu-vm1),pu-vm2(pu-vm2)" -n pu-vm1
Application "my-vms" created.
$ tridentctl-protect get app -n pu-vm1
+---------+---------------+-------+-------+
| NAME | NAMESPACES | STATE | AGE |
+---------+---------------+-------+-------+
| my-vms | pu-vm1,pu-vm2 | Ready | 5m26s |
+---------+---------------+-------+-------+
If you prefer to use yaml manifests, the corresponding application CR looks like this:
apiVersion: protect.trident.netapp.io/v1
kind: Application
metadata:
name: my-vms
namespace: pu-vm1
spec:
includedVirtualMachines:
- names:
- pu-vm1
namespace: pu-vm1
- names:
- pu-vm2
namespace: pu-vm2
resourceFilter: {}
Let’s protect the VMs in the application my-vms now with a snapshot.
$ tridentctl-protect create snapshot --app my-vms --appvault bucket-azure-b8lteoiumb-unca86uqsh -n pu-vm1
Snapshot "my-vms-xu4kix" created.
The snapshot operation finishes quickly.
$ tridentctl-protect get snapshot -n pu-vm1
+----------------+---------+----------------+-----------+-------+-------+
| NAME | APP | RECLAIM POLICY | STATE | ERROR | AGE |
+----------------+---------+----------------+-----------+-------+-------+
| my-vms-xu4kix | my-vms | Delete | Completed | | 4m03s |
+----------------+---------+----------------+-----------+-------+-------+
We check for the volume snapshots in the two namespaces pu-vm1 and pu-vm2 to confirm that only the two VMs pu-vm1 and pu-vm2 were protected.
$ kubectl get volumesnapshot --all-namespaces | grep -E "pu-vm1|pu-vm2"
volumesnapshot.snapshot.storage.k8s.io/snapshot-f76a19b3-399f-4553-99a3-ad552fc2a3fe-pvc-2d490981-d4b0-4a98-b43e-1a38653d4916 true pu-vm1-volume 1552Mi csi-trident-snapclass snapcontent-f9ca034e-5e45-4845-9ae6-0fe38b0ebe23 4m24s 4m29s
volumesnapshot.snapshot.storage.k8s.io/snapshot-f76a19b3-399f-4553-99a3-ad552fc2a3fe-pvc-56665088-6f24-49a9-8fae-52b4e4deee16 true pu-vm2-volume 1632820Ki csi-trident-snapclass snapcontent-9130f1ed-48e8-4fb8-b528-34932bcecf48 4m25s 4m30s
Imagine you later realize you need to protect another, existing or newly created VM, or don’t need to protect a VM anymore. With the static approach shown in the previous section, you’d need to recreate or edit the application definition.
Using label selectors in the application definition allows you to dynamically control which VMs are protected by Trident Protect.
Let’s label the VMs we want to protect with the label protect=true:
$ kubectl get vm -A --show-labels
NAMESPACE NAME AGE STATUS READY LABELS
pu-vm1 pu-vm1 32d Running True protect=true
pu-vm1 pu-vm1a 30d Running True <none>
pu-vm2 pu-vm2 23d Running True <none>
Now we define a dynamic VM application vms-dynamic using the includedNamespace and labelSelector fields to only include the VMs in our two namespaces that are labeled accordingly. As usual, we can either use the tridentctl-protect command to create the application:
$ tridentctl-protect create app vms-dynamic --namespaces pu-vm1'(protect=true)',pu-vm2'(protect=true)' -n pu-vm1
Application "vms-dynamic" created.
Or the corresponding yaml manifest:
apiVersion: protect.trident.netapp.io/v1
kind: Application
metadata:
name: vms-dynamic
namespace: pu-vm1
spec:
includedNamespaces:
- labelSelector:
matchLabels:
protect: "true"
namespace: pu-vm1
- labelSelector:
matchLabels:
protect: "true"
namespace: pu-vm2
resourceFilter: {}
The application will now protect all VMs in the two namespaces that are labeled accordingly.
Let’s create a snapshot with only pu-vm1 being labeled:
$ tridentctl-protect create snapshot vms-dynamic-1 --app vms-dynamic --appvault bucket-azure-b8lteoiumb-unca86uqsh --reclaim-policy Delete -n pu-vm1
Snapshot "vms-dynamic-1" created.
Once the snapshot finishes, we check in the snapshot CR that only the VM pu-vm1 was protected and frozen before the snapshot:
$ kubectl -n pu-vm1 get snapshot vms-dynamic-1 -o yaml | yq .status.volumeSnapshots
- name: snapshot-7d54c7de-60ef-4c32-9703-3e706954d0b0-pvc-2d490981-d4b0-4a98-b43e-1a38653d4916
namespace: pu-vm1
$ kubectl -n pu-vm1 get snapshot vms-dynamic-1 -o yaml | yq .status.vmSnapshotProgress
- frozen: true
podName: virt-launcher-pu-vm1-8dj62
podUID: 683f6621-8db4-4913-af9e-5229a49e3e77
pvcNames:
- pu-vm1-volume
unfrozen: true
vmName: pu-vm1
vmNamespace: pu-vm1
Only one volume snapshot was created across the two VM namespaces:
$ kubectl get volumesnapshot --all-namespaces | grep -E "pu-vm1|pu-vm2"
pu-vm1 snapshot-7d54c7de-60ef-4c32-9703-3e706954d0b0-pvc-2d490981-d4b0-4a98-b43e-1a38653d4916 true pu-vm1-volume 1640840Ki csi-trident-snapclass snapcontent-f3ebc36c-c86a-45e3-b645-4f6a7a7bb76a 2m58s 3m57s
We now want to also protect the VM pu-vm2 in the namespace pu-vm2 with the next snapshot, so let’s add the protect label to it.
$ kubectl -n pu-vm2 label vm pu-vm2 protect=true
virtualmachine.kubevirt.io/pu-vm2 labeled
$ kubectl get vm -A --show-labels
NAMESPACE NAME AGE STATUS READY LABELS
pu-vm1 pu-vm1 32d Running True protect=true
pu-vm1 pu-vm1a 30d Running True <none>
pu-vm2 pu-vm2 23d Running True protect=true
And create a second snapshot:
$ tridentctl-protect create snapshot vms-dynamic-2 --app vms-dynamic --appvault bucket-azure-b8lteoiumb-unca86uqsh --reclaim-policy Delete -n pu-vm1
Snapshot "vms-dynamic-2" created.
Looking at the snapshot CR, we see that this time the two VMs were protected:
$ kubectl -n pu-vm1 get snapshot vms-dynamic-2 -o yaml | yq .status.volumeSnapshots
- name: snapshot-3bf2bc3a-f15c-49c1-b185-b40baad49924-pvc-2d490981-d4b0-4a98-b43e-1a38653d4916
namespace: pu-vm1
- name: snapshot-3bf2bc3a-f15c-49c1-b185-b40baad49924-pvc-56665088-6f24-49a9-8fae-52b4e4deee16
namespace: pu-vm2
$ k -n pu-vm1 get snapshot vms-dynamic-2 -o yaml | yq .status.vmSnapshotProgress
- frozen: true
podName: virt-launcher-pu-vm1-8dj62
podUID: 683f6621-8db4-4913-af9e-5229a49e3e77
pvcNames:
- pu-vm1-volume
unfrozen: true
vmName: pu-vm1
vmNamespace: pu-vm1
- frozen: true
podName: virt-launcher-pu-vm2-bdfh6
podUID: a32133cb-1756-4fee-bb9a-141e3fbfeabd
pvcNames:
- pu-vm2-volume
unfrozen: true
vmName: pu-vm2
vmNamespace: pu-vm2
And we have indeed two volume snapshots for VM pu-vm1 and one for pu-vm2:
$ kubectl get volumesnapshot --all-namespaces | grep -E "pu-vm1|pu-vm2"
pu-vm1 snapshot-3bf2bc3a-f15c-49c1-b185-b40baad49924-pvc-2d490981-d4b0-4a98-b43e-1a38653d4916 true pu-vm1-volume 1641864Ki csi-trident-snapclass snapcontent-e25068ab-e2da-4a45-960b-f37692506e14 10m 12m
pu-vm1 snapshot-7d54c7de-60ef-4c32-9703-3e706954d0b0-pvc-2d490981-d4b0-4a98-b43e-1a38653d4916 true pu-vm1-volume 1640840Ki csi-trident-snapclass snapcontent-f3ebc36c-c86a-45e3-b645-4f6a7a7bb76a 17m 18m
pu-vm2 snapshot-3bf2bc3a-f15c-49c1-b185-b40baad49924-pvc-56665088-6f24-49a9-8fae-52b4e4deee16 true pu-vm2-volume 1686352Ki csi-trident-snapclass snapcontent-47de99d1-5f39-48ab-bb97-36d6cdc21e5c 8m53s 9m45s
If you manage multiple VMs in one Trident Protect application, you may not want to restore the complete application (i.e. all the VMs) in case of an issue with a single VM. Luckily, Trident Protect now also supports the use of includedVirtualMachines on restore CRs to restore only selected KubeVirt VMs from a backup, snapshot, or replicated snapshot archive.
When you specify includedVirtualMachines for a restore, Trident Protect restores only the listed VirtualMachines and their dependent resources, such as VirtualMachineInstance, DataVolume, PersistentVolumeClaim, PersistentVolume, Secret, ConfigMap, ServiceAccount, and other VM-related objects.
To showcase the restore of dedicated VMs, let’s try to restore only the VM pu-vm1 from the snapshot of the my-vms application created earlier.
The tridentctl-protect command now includes the --virtual-machines flag in its restore commands.
--virtual-machines string Restrict restore to specific KubeVirt VirtualMachines, format: namespace1(vm1,vm2),namespace2(vm3). When set, only the listed VMs and their dependent resources are restored.
So, the command to only restore VM pu-vm1 from the snapshot my-vms-xu4kix into a new namespace pu-vm1-restore is:
$ tridentctl-protect create snapshotrestore --virtual-machines "pu-vm1(pu-vm1)" --namespace-mapping pu-vm1:pu-vm1-restore --snapshot pu-vm1/my-vms-xu4kix --skip-application-creation -n pu-vm1-restore
SnapshotRestore "my-vms-9svx1q" created.
If you want to apply the snapshotrestore CR instead of using tridentctl-protect, the yaml manifest is:
apiVersion: protect.trident.netapp.io/v1
kind: SnapshotRestore
metadata:
name: my-vms-22pamd
namespace: pu-vm1-restore
spec:
appArchivePath: my-vms_023a7794-d101-45ca-b8b4-cd47b08bb699/snapshots/20260710151722_my-vms-xu4kix_f76a19b3-399f-4553-99a3-ad552fc2a3fe
appVaultRef: bucket-azure-b8lteoiumb-unca86uqsh
cleanUpAdditionalExecHooks: true
cleanUpArchivedExecHooks: false
includedVirtualMachines:
- names:
- pu-vm1
namespace: pu-vm1
namespaceMapping:
- destination: pu-vm1-restore
source: pu-vm1
resourceFilter: {}
runArchivedExecHooks: true
skipApplicationCreation: true
The restore finishes in a couple of minutes, and we confirm that the VM has been restored and is up and running.
$ kubectl get vm -A
NAMESPACE NAME AGE STATUS READY
pu-vm1-restore pu-vm1 5m6s Running True
pu-vm1 pu-vm1 30d Running True
pu-vm1 pu-vm1a 30d Running True
pu-vm2 pu-vm2 21d Running True
NetApp Trident Protect has introduced significant improvements in handling virtual machines (VMs) running on OpenShift Virtualization or KubeVirt. The latest updates enable users to back up and restore VMs more efficiently by offering two distinct ways to define which VMs to protect: by namespaces or by specific VM names using the includedVirtualMachines field.
Key features include:
Practical Usage
These enhancements make NetApp Trident Protect a robust solution for managing and safeguarding virtual environments, offering both flexibility and precision in VM protection and recovery.
If you’re looking for even more advanced capabilities like 3-2-1 protection policies, faster backups and restores with incremental forever backups and change block tracking (CBT), storage efficiency preservation and storage offloading for backup operations, managed with a graphical user interface, take a look at NetApp Backup and Restore for K8s. Login to NetApp Console, navigate to Protection --> Backup and Recovery and sign up for a free trial!