Migrate Virtual Machines Between Storage Classes
This document describes how to migrate a virtual machine (VM) disk from one StorageClass to another. Use this procedure when you need to move VM storage to another backend, storage pool, or CSI driver, for example from Ceph RBD to CephFS, between two Ceph RBD pools, or from platform-provided storage to a customer-provided storage class.
Two migration methods are available:
TOC
PrerequisitesPrepare the MigrationCold Migration with a DataVolume CloneStop the VMCreate the Destination DataVolumeUpdate the VM Disk ReferenceStart and Verify the VMLive Storage MigrationConfirm Live Migration ReadinessCreate the Migration ObjectsTroubleshootingNo VM Is Ready for Live Storage MigrationLive Migration Is Stuck in SchedulingDestination DataVolume Does Not CompleteLive Storage Migration Does Not Reach CompletedMigration Resources Are Stuck During CleanupPrerequisites
- ACP virtualization is enabled and includes live storage migration support.
- You have permission to manage
VirtualMachine,VirtualMachineInstance,PersistentVolumeClaim, andDataVolumeresources in the VM namespace. - The source VM uses a CDI
DataVolumeor a PVC-backed disk. - The destination StorageClass has enough capacity and supports the required
accessModesandvolumeMode. - For cold migration, plan a maintenance window because the VM is stopped while the disk is cloned and the VM definition is updated.
- For live storage migration, the running VMI must report both
LiveMigratable=TrueandStorageLiveMigratable=True.
Prepare the Migration
Set variables for the VM and destination storage:
Check the destination StorageProfile before creating the destination disk:
Choose accessModes and volumeMode from the claim property sets supported by the destination StorageProfile. For example, Ceph RBD is commonly used with volumeMode: Block, while CephFS is commonly used with volumeMode: Filesystem.
For a VirtualMachineStorageMigrationPlan, which is used for live storage migration and described later in this document, you can also set accessModes or volumeMode to Auto and let the storage migration controller look up the value from the StorageProfile. For a manually created DataVolume, use explicit Kubernetes PVC values such as ReadWriteOnce, ReadWriteMany, Block, or Filesystem.
If you plan to use live storage migration, check the running VMI conditions:
Continue with live storage migration only when the output includes both of the following conditions:
If either condition is missing or set to False, use cold migration or resolve the reported limitation before retrying live migration.
Cold Migration with a DataVolume Clone
Cold migration is the most compatible method across CSI drivers. It stops the VM, clones the source PVC into a new DataVolume that uses the destination StorageClass, and then updates the VM to use the new DataVolume.
Stop the VM
Stop the VM:
Some VM API versions warn that spec.running is deprecated in favor of
spec.runStrategy. If the VM already uses spec.running, do not set
spec.runStrategy without first removing spec.running, because the two
fields are mutually exclusive.
Wait until the VMI is deleted:
Create the Destination DataVolume
Create a DataVolume that clones the source PVC into the destination StorageClass:
Apply the manifest:
For a StorageClass with volumeBindingMode: Immediate, wait for the clone to complete:
For a StorageClass with volumeBindingMode: WaitForFirstConsumer, the DataVolume can remain in PendingPopulation until the VM starts and becomes the first consumer. This is expected for local or topology-aware storage. Continue with the VM update, start the VM, and monitor the DataVolume and VMI.
When migrating from block mode to filesystem mode, request a destination size larger than the source disk. A 5% to 10% increase is a practical starting point because the destination filesystem and disk image file need additional space.
Update the VM Disk Reference
Update the VM so the root disk volume points to the destination DataVolume.
When editing arrays such as spec.dataVolumeTemplates and spec.template.spec.volumes, keep all required entries. If the VM has other disks, cloud-init volumes, secrets, or config maps, include them in the final VM specification so they are not removed.
Example patch content:
Apply the patch:
Start and Verify the VM
Start the VM:
Check the VM, VMI, PVC, and DataVolume status:
If the destination uses WaitForFirstConsumer, monitor the DataVolume and PVC until the VM starts:
After the VM is running and guest workload checks pass, delete the old DataVolume or PVC only after confirming that it is no longer referenced by the VM.
Live Storage Migration
Use live storage migration only when the VM must stay running and all live migration prerequisites are met.
Confirm Live Migration Readiness
Check the VMI conditions:
Proceed only when the output includes LiveMigratable=True and StorageLiveMigratable=True.
Also confirm the following requirements:
-
The destination StorageClass can create a PVC with the selected
accessModesandvolumeMode. -
The VM can be scheduled on more than one node.
-
The VM does not report
RestartRequired=Truein.status.conditions. If the VM has pending changes that require a restart, restart the VM or resolve those pending changes before starting live storage migration. -
If the cluster has mixed CPU models, the VM uses a CPU model supported by all candidate nodes.
-
If the VM uses bridge binding on the pod network, the VM has the following annotation:
Create the Migration Objects
The ACP console is the preferred entry point because it validates the VM and destination storage options before creating the migration resources.
If you use Kubernetes manifests, create a VirtualMachineStorageMigrationPlan and a VirtualMachineStorageMigration. The plan alone does not execute — the migration object is the trigger:
Apply the manifest:
Monitor progress:
The expected flow is:
- ACP creates the destination PVC and DataVolume.
- ACP updates the VM disk reference to the destination DataVolume.
- KubeVirt performs a workload update through live migration.
- ACP cleans up the completed workload update resources.
- The
VirtualMachineStorageMigrationreachesCompleted.
When the migration reaches Completed, the VM specification references the destination DataVolume and the VM continues running on the migrated disk. Verify the VM, VMI, destination PVC, and destination DataVolume before deleting any old storage objects:
After the migration succeeds and guest workload checks pass, remove the old DataVolume or PVC only if it is no longer referenced by the VM or by any rollback procedure.
Troubleshooting
No VM Is Ready for Live Storage Migration
Describe the migration plan:
If the plan reports No virtual machines are ready for storage migration, check whether the VM is running and whether the VMI reports both LiveMigratable=True and StorageLiveMigratable=True.
If either condition is false, use cold migration or fix the underlying reason first. Also confirm that the target accessModes and volumeMode are supported by the destination StorageProfile, and that the VM does not report RestartRequired=True. Common causes include non-shared PVCs, local storage, unsupported network binding, unsupported target PVC properties, pending VM changes that require a restart, and node scheduling constraints.
Live Migration Is Stuck in Scheduling
Describe the pending launcher pod or the VirtualMachineInstanceMigration:
Common causes include:
- The destination launcher pod cannot be scheduled on a node different from the source node.
- The VM uses a CPU model or CPU feature set that exists only on the source node.
- The destination PVC cannot be attached or mounted on the target node.
Use a portable CPU model and confirm that the destination storage supports the required access mode.
Destination DataVolume Does Not Complete
Inspect the DataVolume and PVC events:
For WaitForFirstConsumer storage, PendingPopulation can be expected until a consumer pod is scheduled. For block-to-filesystem migration, increase the requested destination size and retry if CDI reports that the target PVC is too small.
Live Storage Migration Does Not Reach Completed
If the VirtualMachineStorageMigration does not reach Completed, inspect both the storage migration resource and the underlying KubeVirt migration:
If the VirtualMachineInstanceMigration is still running, continue troubleshooting it as a live migration issue. If the VirtualMachineInstanceMigration has already succeeded but the storage migration resource still does not complete, collect the migration resource, migration plan, VM, VMI, PVC, DataVolume, and controller logs before contacting support.
Migration Resources Are Stuck During Cleanup
Delete the migration resources first:
If a finalizer prevents deletion, remove it only after confirming that no active migration is still running:
Before restarting the VM after an interrupted live storage migration, confirm which DataVolume the VM references:
If the VM specification was updated but the migration did not complete, either finish the migration or restore the VM disk reference to the intended DataVolume before starting the VM.