Repository navigation
Description
What happened
Commit 4cc60e3 (released in v1.5.0) removed the sed -i '/persistent: true/d' strip from packages/system/kubevirt-instancetypes and restored upstream's persistent firmware state for the windows.11, windows.2k22, windows.2k25 preferences (and their .virtio variants):
devices:
preferredTPM:
persistent: true
firmware:
preferredEfi:
persistent: true
secureBoot: trueThat was a correct fix (the strip left preferredTPM: null, which the v1.8 CRD rejects). But it has a side effect on live-migration.
With persistent EFI/TPM, KubeVirt creates a backend-storage PVC (persistent-state-for-<vm>). Its access mode is decided by backend-storage.getAccessMode: with vmStateStorageClass unset (the default), it consults the CDI StorageProfile of the cluster-default StorageClass. On the default replicated (linstor.csi.linbit.com) class the StorageProfile advertises only Filesystem: [ReadWriteOnce] (RWX is Block-only), so the backend PVC is created ReadWriteOnce.
An RWO backend PVC pins the VM to its node, so the VM cannot be live-migrated or drained.
Impact
On a default v1.5.0 install, windows.11 / windows.2k22 / windows.2k25 VMs are no longer live-migratable. Because the KubeVirt CR uses evictionStrategy: LiveMigrate and workloadUpdateMethods: [LiveMigrate, Evict], node drains and cluster upgrades involving these VMs can get stuck on the failed live-migration.
This is a behavioral regression vs. ≤ v1.4.x, where persistence was stripped (no backend PVC, migration worked — at the cost of non-persistent firmware state).
How to reproduce
- Install cozystack v1.5.0.
- Create a
windows.2k22VMInstance on the defaultreplicatedstorage. kubectl get pvc→persistent-state-for-<vm>isReadWriteOnce.- Trigger a live-migration / node drain of that VM → blocked.
Possible directions
- Provide an RWX backend for the persistent state:
- point
spec.configuration.vmStateStorageClassat an RWX-Filesystem class (the LINSTOR NFS-export RWX serverlinstor-csi-nfs-serveris already deployed in current installs), or - upstream KubeVirt support for a Block-mode (RWX-Block) backend volume so it uses
Block: [ReadWriteMany]onreplicateddirectly, no NFS — draft backend-storage: persistent EFI NVRAM on a Block-mode (RWX) volume kubevirt/kubevirt#18215.
- point
- Or make persistent firmware state opt-in (e.g. via an explicit
firmware.efiPersistentfield — see feat(vm-instance): add firmware config (UEFI/BIOS, Secure Boot, persistent EFI) #3002) rather than default-on through the Windows profiles, and document the live-migration trade-off.
Environment
- cozystack v1.5.0 (regression introduced by 4cc60e3; not present in ≤ v1.4.4)
- KubeVirt v1.8.2, default
replicatedStorageClass (linstor.csi.linbit.com)
Activity
fix(kubevirt-instancetypes): drop persistent EFI/TPM to unblock live-…
fix(kubevirt-instancetypes): drop persistent EFI/TPM to unblock live-…
fix(kubevirt-instancetypes): restore persistent EFI/TPM state (#3154)
lexfrei commentedon Sep 6, 2026
Closing this: the premise does not hold, and the disproof is already in our own changelog.
The v1.5.4 entry for restoring persistent EFI/TPM (#3154) states that the strip was motivated by a concern resting on an outdated premise, and that KubeVirt has migrated RWO-Filesystem backend storage since v1.4 (kubevirt/kubevirt#12629): it creates a fresh target state PVC and copies the state blob during migration. It records that this was verified on the default
replicatedclass, with a persistent-firmware VM reportingLiveMigratable=True.That behaviour predates the version this issue was filed against, so the RWO backend PVC never pinned the VM the way the description assumes.
backend-storage.gois unchanged in this respect between v1.8.2 and the v1.9.0 we now ship.What is left is not migration: copy-on-migrate churns a fresh 10Mi PVC on each migration and deletes the old one, which is waste rather than breakage. The
vmStateStorageClassknob in #3989 stands on its own merits rather than as a fix for this. If anyone reproduces a blocked migration on current main, please reopen with the condition or event that blocked it, since it will be a different mechanism.