OADP Velero plugin for KubeVirt incremental backup and restore.
This repository contains Velero BackupItemAction (BIA) and RestoreItemAction (RIA) plugins that enable KubeVirt VirtualMachine backups using qcow2 incremental snapshots instead of traditional CSI snapshots.
These plugins work in conjunction with the KubeVirt Datamover Controller to provide:
- True block-level Changed Block Tracking (CBT) instead of full volume scans
- Faster incremental backups using QEMU/libvirt native capabilities
- VM-aware backup operations (as opposed to treating disks as generic PVCs)
┌─────────────────────────────────────────────────────────────────────────────┐
│ Velero Backup Flow │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Velero triggers backup │
│ │ │
│ ▼ │
│ 2. VirtualMachine BIA Plugin │
│ • Checks VM has ChangedBlockTracking enabled │
│ • Validates volume policies (action: "kubevirt") │
│ • Creates DataUpload with SnapshotType: "kubevirt" │
│ │ │
│ ▼ │
│ 3. KubeVirt Datamover Controller (separate component) │
│ • Reconciles DataUpload │
│ • Creates VirtualMachineBackup CR │
│ • Copies qcow2 files to BSL │
│ │ │
│ ▼ │
│ 4. Backup completes with incremental qcow2 data in object storage │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Handles VirtualMachine resources during backup:
- Validates that Changed Block Tracking is enabled on the VM
- Checks that the VM is running (offline backup not supported in initial release)
- Evaluates volume policies to determine if KubeVirt datamover should be used
- Creates a
DataUploadCR with:Spec.SnapshotType:"kubevirt"Spec.DataMover:"kubevirt"
- Adds
DataUploadNameAnnotationto the VirtualMachine - Returns an async operation ID for progress tracking
Handles PersistentVolumeClaim resources during backup:
- Determines whether a PVC belongs to a VM that is eligible for kubevirt datamover (same preconditions as the VirtualMachine BackupItemAction)
- Stamps the
AnnotationVMNameannotation on the PVC so the restore-side PersistentVolumeClaim RestoreItemAction can recognize it later - Does not create any CR itself — the VM BackupItemAction owns
DataUploadcreation
Handles PersistentVolumeClaim resources during restore:
- Recognizes PVCs backed up via the kubevirt datamover, using the
AnnotationVMNameannotation stamped on the PVC by the PVC BackupItemAction - Creates a
DataDownloadCR withSpec.DataMover: "kubevirt"to trigger the KubeVirt Datamover Controller's restore path (qcow2-to-raw conversion) - Returns an async operation ID for progress tracking, mirroring the backup-side DataUpload flow
- Honors
Restore.Spec.NamespaceMapping:Spec.TargetVolume.Namespaceis set to the remapped namespace, whileSpec.SourceNamespacestays the original, pre-remap namespace - Operates at the PVC level (not VM level), so multi-disk VMs are handled
naturally: one
DataDownloadper PVC, no special-casing required
Prevents restoration of backup-related CRs:
- Discards
VirtualMachineBackupresources on restore - Discards
VirtualMachineBackupTrackerresources on restore - Prevents accidental re-triggering of backup operations
- OADP 1.5+ with Velero 1.15+
- KubeVirt with Changed Block Tracking support
- KubeVirt Datamover Controller deployed in the cluster
SnapshotMoveData: trueon backups
The plugin is deployed as an init container in the Velero deployment. Add the following to your OADP DataProtectionApplication CR:
apiVersion: oadp.openshift.io/v1alpha1
kind: DataProtectionApplication
metadata:
name: velero-dpa
spec:
configuration:
velero:
defaultPlugins:
- openshift
- kubevirt
- kubevirt-datamover # Enable KubeVirt datamover plugins
# ... other configuration# Build locally
make build-local
# Build with Podman or Docker
make all
# Build container image
make container
# Run tests
make test
# Clean build artifacts
make cleankubevirt-datamover-plugin/
├── kubevirt-datamover-plugin/
│ ├── main.go # Plugin registration
│ └── clients/ # Kubernetes client factory
│ └── clients.go
├── Dockerfile
├── Makefile
├── go.mod
└── go.sum