Harvester Live Migration: The Storage and Capacity Checks That Make Node Maintenance Safe
Live migration in Harvester is a storage and capacity decision before it is a UI action. Learn the Longhorn prerequisites, KubeVirt migration checks, and a repeatable node-maintenance runbook.
07 Jul 2026, 16:46 UTC

The problem: patching a node without stopping the workloads
You need to apply OS patches or replace hardware on a Harvester node, but the virtual machines running on it cannot tolerate downtime. The obvious answer is live migration, but treating it as a simple UI button is how maintenance windows go wrong. In Harvester, a live migration is a capacity and storage decision first. If the destination node lacks memory or CPU headroom, or if the VM disks cannot follow the workload safely, the migration will stall or fail.
What actually moves during a Harvester migration
Harvester runs VMs as KubeVirt VirtualMachineInstance (VMI) objects. A live migration creates a VirtualMachineInstanceMigration that instructs KubeVirt to move the VMI's launcher pod to another node. QEMU—the process that emulates the VM hardware—transfers memory to the destination while the guest keeps running. For supported storage backends, disk access stays consistent. The VM does not reboot, but the final switch can still pause it briefly, so “live” does not always mean “zero-impact.”
Storage is the usual failure point
With Harvester's default Longhorn-backed storage, the volume must be migratable. Older Longhorn setups expose a migratable parameter on the StorageClass, and replica placement matters: the destination node should already host a replica or be able to attach one quickly. If a VM uses local-path, host-path, or a non-migratable class, plan a cold migration or downtime instead.
| Storage type | Live migration behavior | Action before draining |
|---|---|---|
| Longhorn (migratable class) | Supported when replicas are reachable | Verify replica placement on destination |
| local-path / host-path | Not migratable | Plan cold migration or downtime |
| Non-migratable CSI class | Blocked or unsafe | Inspect StorageClass parameters |
Harvester release cadence and KubeVirt/Longhorn versions change defaults. Do not assume a setting name or parameter exists in your build; inspect the StorageClass and the PersistentVolumeClaim (PVC) binding before you rely on it.
A worked migration check
Pick a small test VM on your default Longhorn class. Confirm where it is running, then trigger a migration and watch the result.
# Find the node currently running the VM
kubectl get vmi -n <namespace> <vm-name> -o jsonpath='{.status.nodeName}'
# Create a migration request
cat <<EOF | kubectl create -f -
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstanceMigration
metadata:
name: <vm-name>-migrate
namespace: <namespace>
spec:
vmiName: <vm-name>
EOF
# Watch the migration and the VM's placement
kubectl get virtualmachineinstancemigration -n <namespace> <vm-name>-migrate -w
kubectl get vmi -n <namespace> <vm-name> -o jsonpath='{.status.nodeName}'
Run these commands from a machine with cluster-admin or equivalent access to the Harvester management cluster. Replace <namespace> and <vm-name> with your actual values. The apiVersion may differ by Harvester version, so validate object names and API groups against your cluster before applying.
Expected checks: the migration object should reach a Succeeded phase, the VMI's status.nodeName should change to the destination, and your application-level health check should still pass. If the migration stays Pending or Failed, inspect the destination capacity and storage replica placement before retrying.
Trade-offs and hard limits
Live migration consumes bandwidth and time. On a single-network Harvester cluster, a large VM can saturate the link shared by management, storage, and VM traffic, causing latency spikes for everything else. Some releases expose a dedicated migration network or a bandwidth limit, but names and defaults vary, so verify before relying on them.
Some workloads cannot migrate at all. PCI/GPU passthrough, SR-IOV network interfaces (a PCI device-sharing technology), USB redirection, and host-passthrough CPU models (which expose the physical CPU's exact features to the guest) are common blockers or require identical CPU features on both nodes. Migration also does not fix bad replica placement or a full destination node, and eviction can still be blocked by a PodDisruptionBudget (a Kubernetes policy that limits voluntary disruptions) or a VM eviction policy. Finally, migration is not a backup: test snapshots and backups separately.
Make it a repeatable runbook
Treat node maintenance as a rehearsed procedure, not an emergency reaction:
- Label the node for maintenance and confirm the destination has CPU, memory, and storage headroom.
- Inspect the
StorageClassand PVC binding for every VM you plan to move; confirm the destination can host or reach a replica. - Run a canary migration on a small VM using the same node selector and storage class as production.
- Migrate the remaining VMs, or cordon and drain the node (mark it unschedulable and evict its pods) using the same flags your process uses.
- Confirm the VM list, node assignments, and health checks before uncordoning.
Rehearse the runbook on a non-production node first. The goal is not to prove that the Migrate button works, but to prove that your storage, capacity, and policy assumptions hold under your specific Harvester release.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.