Protect KubeVirt virtual machines with Trident Protect
Trident Protect enables you to back up and restore KubeVirt virtual machines (VMs) running on OpenShift Virtualization. You can protect all VMs across one or more namespaces at once, or use the 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.
KubeVirt protection modes
Trident Protect supports two ways to define which KubeVirt VMs to protect. Choose one mode when you define an application:
| Mode | Field | Description |
|---|---|---|
Namespace-based |
|
Protect all matching resources in one or more namespaces. Use a |
VM-scoped |
|
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.
Both modes support additional filtering:
-
Use
resourceFilterto include or exclude specific resources. -
Use
includedClusterScopedResourcesto include compatible cluster-scoped resources, such asStorageClassobjects.
|
|
Trident Protect can freeze and unfreeze KubeVirt VM filesystems during data protection operations to ensure consistency. For configuration details, see Protecting data with KubeVirt VMs. |
Resources collected during backup and snapshot
When you create a backup or snapshot for an application that includes KubeVirt VMs, Trident Protect collects the selected VM resources and automatically discovers their dependent resources.
The collection behavior applies in two cases:
-
VM-scoped applications that use
includedVirtualMachines. -
Namespace-based applications that contain KubeVirt
VirtualMachineresources.
VM-scoped collection
For VM-scoped applications, Trident Protect starts with each VirtualMachine listed in includedVirtualMachines and discovers the dependent resources needed to restore that VM.
| Resource type | Scope | How it is discovered |
|---|---|---|
|
Namespaced |
Direct match from the |
|
Namespaced |
Same namespace and name as the VM, if the VM is running. |
|
Namespaced |
Referenced by |
|
Cluster |
Referenced by |
|
Namespaced |
Referenced by |
|
Cluster |
Referenced by |
|
Namespaced |
Referenced by |
|
Namespaced |
Discovered from DataVolume-backing PVCs, which use the same name as the DataVolume; direct PVC references in |
|
Cluster |
Discovered from the backing PV for each collected PVC by using |
|
Namespaced |
Discovered from volume secrets in |
|
Namespaced |
Discovered from volume ConfigMaps in |
|
Namespaced |
Discovered from |
|
Namespaced |
Discovered from Multus networks in |
|
Namespaced |
Discovered for |
Storage class, Trident volumes, and Trident backends |
Cluster |
Collected the same way as namespace-based applications, based on the PVCs discovered for the VM. |
|
|
After all VM-scoped namespaced resources are collected, Trident Protect applies the standard resourceFilter, if one is configured. Cluster-scoped resource collection then proceeds as normal.
|
Namespace-based collection
For namespace-based applications, Trident Protect scans the selected namespaces and collects all matching resources. If any KubeVirt VirtualMachine objects are found, Trident Protect automatically collects their dependent resources, including instance types, preferences, and virt-launcher Pods, the same way it does for VM-scoped applications.
This means VM-specific resources are included in your backup or snapshot even when the application is defined with includedNamespaces.
Protect VMs using namespace-based application definitions
When you create a namespace-based application, Trident Protect scans the selected namespaces and collects all resources, including any KubeVirt VMs. For each virtual machine found, Trident Protect also collects the dependent resources needed to back up and restore that VM.
Example namespace-based application CR:
apiVersion: protect.trident.netapp.io/v1
kind: Application
metadata:
name: <application_name>
namespace: <application_namespace>
spec:
includedNamespaces:
- namespace: <vm_namespace>
After you create the application, use the standard Trident Protect workflows for backups and snapshots:
-
For snapshot YAML examples, see Create an on-demand snapshot.
-
For backup YAML examples, see Create an on-demand backup.
Restore behavior for namespace-based VM applications
Because namespace-based applications collect resources from the selected namespaces, the backup or snapshot can include KubeVirt runtime objects and KubeVirt-managed metadata. Some of these objects should not be restored directly because they represent runtime state from the source cluster.
During restore, Trident Protect applies KubeVirt-aware transforms to remove source-cluster metadata and skip transient KubeVirt resources. This helps KubeVirt recreate the VM cleanly in the restored environment.
| Resource | Transform |
|---|---|
VirtualMachine |
Removes labels and annotations that start with |
VirtualMachineInstance |
Removes labels and annotations that start with |
VirtualMachineInstanceMigration |
Ignored and not restored. |
VirtualMachineSnapshot |
Ignored and not restored. |
VirtualMachineSnapshotContent |
Ignored and not restored. |
Pod ( |
Skipped when the pod has the |
|
|
Trident Protect restores KubeVirt resources in a defined order to avoid dependency issues. CDI DataVolumes (cdi.kubevirt.io) are restored first so VM disk data is available before the VM objects are created. After that, VirtualMachines (kubevirt.io) are restored before VirtualMachineInstances.
|
Dynamic VM protection with label selectors
If you want to protect VMs dynamically without listing each VM name, use namespace-based application definitions with label selectors.
Only the VirtualMachine CR needs labels. Dependent resources such as DataVolumes, PVCs, Secrets, and ConfigMaps are collected automatically.
-
Label virtual machine CRs with a shared label:
kubectl label virtualmachine <vm_name 1> app=<label_value> -n <vm_namespace> kubectl label virtualmachine <vm_name_2> app=<label_value> -n <vm_namespace> -
Create an application CR with
includedNamespacesand alabelSelector:apiVersion: protect.trident.netapp.io/v1 kind: Application metadata: name: <application_name> namespace: <application_namespace> spec: includedNamespaces: - namespace: <vm_namespace> labelSelector: matchLabels: app: <label_value> -
Create backups and restores using the standard Trident Protect workflow.
Additional details:
-
You can add or remove VMs from protection at any time by changing labels:
kubectl label virtualmachine <vm_name_to_add> app=<label_value> -n <vm_namespace>
kubectl label virtualmachine <vm_name_to_remove> app=<different_label_value> -n <vm_namespace>
-
You can also use label selectors across multiple namespaces:
spec:
includedNamespaces:
- namespace: <vm_namespace_1>
labelSelector:
matchLabels:
<label_key>: <label_value>
- namespace: <vm_namespace_2>
labelSelector:
matchLabels:
<label_key>: <label_value>
Protect specific VMs with includedVirtualMachines
Use includedVirtualMachines when you want to protect a named set of VirtualMachines across one or more namespaces and selectively restore specific VMs from an archive.
Both the application and restore CRs use the same includedVirtualMachines selector format.
Use this selector in different contexts:
-
In an application CR, it defines which VMs are protected.
-
In a restore CR, it defines which VMs are restored from the backup or snapshot archive.
|
|
On restore CRs, includedVirtualMachines is optional. If you do not include this field, the entire archive is restored. When specified, only the listed VMs and their dependent resources are restored.
|
The YAML below shows the shared selector structure:
includedVirtualMachines:
- namespace: <vm_namespace_1>
names:
- <vm_name_1>
- <vm_name_2>
- namespace: <vm_namespace_2>
names:
- <vm_name_3>
|
|
Multiple entries in includedVirtualMachines can reference different namespaces, which enables multi-namespace VM-aware application definitions and restores.
|
| Field | Type | Description |
|---|---|---|
namespace |
string |
Kubernetes namespace that contains the target virtual machine objects. |
names |
list of strings |
One or more virtual machine names in that namespace. |
apiVersion: protect.trident.netapp.io/v1
kind: Application
metadata:
name: <application_name>
namespace: <application_namespace>
spec:
includedVirtualMachines:
- namespace: <vm_namespace_1>
names:
- <vm_name_1>
- <vm_name_2>
- namespace: <vm_namespace_2>
names:
- <vm_name_3>
includedClusterScopedResources:
- group: storage.k8s.io
kind: StorageClass
Restore specific KubeVirt VMs
You can use includedVirtualMachines on restore CRs to restore only selected KubeVirt VMs from a backup, snapshot, or replicated snapshot archive.
When includedVirtualMachines is specified on a restore CR, 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.
If you do not specify includedVirtualMachines on the restore CR, Trident Protect restores the full archive according to the restore CR configuration.
Supported restore CRs and CLI commands
The following table lists the restore CRs that support includedVirtualMachines and their corresponding CLI commands.
| Restore CR | CLI command | Description |
|---|---|---|
|
|
Restores from a backup to new or different namespace mappings. Supports |
|
|
Restores from a backup into the original namespace or namespaces. |
|
|
Restores from a snapshot to new or different namespace mappings. Supports |
|
|
Restores from a snapshot into the original namespace or namespaces. |
|
YAML only, or use the supported CLI command if available in your environment |
Restores from a replicated snapshot. Supports |
|
|
The tridentctl-protect CLI does not have a flag for includedVirtualMachines on restore commands. To restore specific VMs, you must apply a restore CR YAML file directly using kubectl apply. You can write the YAML from scratch, or use the CLI with --dry-run --output yaml to generate a starting file, add the includedVirtualMachines field under spec, and then apply it.
|
VM-scoped restore behavior
The includedVirtualMachines field on a restore CR uses the same selector format as the application CR:
includedVirtualMachines:
- namespace: <source_vm_namespace>
names:
- <vm_name_1>
- <vm_name_2>
For restore CRs, the namespace values in includedVirtualMachines refer to the source namespaces as they exist in the backup, snapshot, or replicated snapshot archive.
If you use namespaceMapping, Trident Protect first selects the requested VMs from the source archive and then applies namespace mappings during restore. If you use storageClassMapping, Trident Protect applies the storage class mappings during the restore transform phase.
Generate restore YAML with the CLI
You can use tridentctl-protect to generate a base restore CR and then edit the YAML to add includedVirtualMachines.
tridentctl-protect create <restore_command> <restore_name> \
<restore_options> \
--dry-run --output yaml > <restore_name>.yaml
Edit the generated YAML and add the includedVirtualMachines field under spec, then apply the file:
kubectl apply -f <restore_name>.yaml
Example: Define a VM-based application
The following application protects three specific VMs across two namespaces.
apiVersion: protect.trident.netapp.io/v1
kind: Application
metadata:
name: production-vms
namespace: prod
spec:
includedVirtualMachines:
- namespace: prod
names:
- app-server
- database-server
- namespace: monitoring
names:
- prometheus-vm
includedClusterScopedResources:
- group: storage.k8s.io
kind: StorageClass
Example: Create a backup
Creating a backup for a VM-based application uses the standard backup CR. No VM-specific fields are required on the backup CR.
apiVersion: protect.trident.netapp.io/v1
kind: Backup
metadata:
name: daily-backup
namespace: prod
spec:
applicationRef: production-vms
appVaultRef: s3-vault
Example: Restore a single VM from a backup
The following example restores only database-server from the backup archive. The other VMs in the archive, such as app-server and prometheus-vm, are skipped.
apiVersion: protect.trident.netapp.io/v1
kind: BackupRestore
metadata:
name: restore-db-only
namespace: prod-vms-restore
spec:
appVaultRef: s3-vault
appArchivePath: backups/production-vms/2026-03-10T00-00-00Z
namespaceMapping:
- source: prod
destination: prod-dr
includedVirtualMachines:
- namespace: prod
names:
- database-server
kubectl apply -f restore-db-only.yaml
Only database-server and its dependent resources, such as DataVolumes, PVCs, PVs, Secrets, ConfigMaps, and related KubeVirt resources, are restored.
Example: Restore a single VM in place from a backup
The following example restores only database-server into its original namespace from the backup archive.
apiVersion: protect.trident.netapp.io/v1
kind: BackupInplaceRestore
metadata:
name: ipr-db-only
namespace: prod
spec:
appVaultRef: s3-vault
appArchivePath: backups/production-vms/2026-03-10T00-00-00Z
includedVirtualMachines:
- namespace: prod
names:
- database-server
kubectl apply -f ipr-db-only.yaml
Example: Restore a single VM from a snapshot
The following example restores only ubuntu-vm-blue-a627be38 from a snapshot archive.
apiVersion: protect.trident.netapp.io/v1
kind: SnapshotRestore
metadata:
name: blue-vm-snap-restore
namespace: blue
spec:
appVaultRef: my-appvault
appArchivePath: snapshots/protectctl-blue-vm/snap-1
includedVirtualMachines:
- namespace: blue
names:
- ubuntu-vm-blue-a627be38
kubectl apply -f blue-vm-snap-restore.yaml
Combine VM restore with other filters
You can use includedVirtualMachines together with resourceFilter, namespaceMapping, and storageClassMapping in the same restore CR to fine-tune what gets restored.
When you add a resourceFilter, Trident Protect first selects the VMs listed in includedVirtualMachines and their dependent resources. It then applies the resource filter to further narrow down what is included or excluded from those results.
spec:
includedVirtualMachines:
- namespace: <vm_namespace>
names:
- <vm_name>
resourceFilter:
resourceSelectionCriteria: Include
resourceMatchers:
- kinds: ["PersistentVolumeClaim"]
names: ["<pvc_name>"]
For BackupRestore, SnapshotRestore, and ReplicateSnapshotRestore, namespaceMapping and storageClassMapping work alongside includedVirtualMachines. Namespace references in includedVirtualMachines correspond to source namespaces as they appear in the archive. Namespace and storage class mappings are applied during the restore transform phase after filtering is complete.
For restore behavior details, refer to Restore applications using Trident Protect.
Create a VM-scoped application using the CLI
Use the --virtual-machines flag to scope an application to specific KubeVirt VMs instead of whole namespaces. The --virtual-machines flag is mutually exclusive with --namespaces.
-
Create the application by running one of the following commands, replacing values in brackets with information from your environment. The format for the
--virtual-machinesflag is<namespace>(<vm_name>). For multiple VMs, use comma-separated names within the parentheses:-
Single VM in a namespace:
tridentctl-protect create application <application_name> \ -n <application_namespace> \ --virtual-machines "<vm_namespace>(<vm_name>)" -
Multiple VMs across namespaces:
tridentctl-protect create application <application_name> \ -n <application_namespace> \ --virtual-machines "<vm_namespace_1>(<vm_name_1>,<vm_name_2>),<vm_namespace_2>(<vm_name_3>)"
-