Skip to content

Instantly share code, notes, and snippets.

@SeanMooney
Created May 25, 2026 20:45
Show Gist options
  • Select an option

  • Save SeanMooney/e542eea07e60c0b3fdd67867b30dee79 to your computer and use it in GitHub Desktop.

Select an option

Save SeanMooney/e542eea07e60c0b3fdd67867b30dee79 to your computer and use it in GitHub Desktop.
OpenStack Nova to KubeVirt / OpenShift Virtualization Cheatsheet

OpenStack Nova to KubeVirt / OpenShift Virtualization Cheatsheet

This is a quick concept and workflow mapping for thinking about KubeVirt from an OpenStack Nova perspective.

Core concept mapping

OpenStack / Nova KubeVirt / OpenShift Virtualization Notes
Nova server / instance VirtualMachine + VirtualMachineInstance VirtualMachine is desired state; VirtualMachineInstance is the running guest.
Running libvirt domain VirtualMachineInstance The live domain generated by KubeVirt.
Flavor VirtualMachineInstancetype Defines vCPU, memory, CPU model, IOThreads policy, GPUs, host devices, etc.
Image boot source: DataSource, PVC, DataVolume, containerDisk, registry import Source for the root disk.
Glance image metadata / hw_* properties VirtualMachinePreference plus VM spec Captures guest hardware preferences: machine type, firmware, buses, topology, RNG, features.
Nova image + flavor selection boot source + instancetype + preference KubeVirt intentionally separates image/source, sizing, and guest hardware preferences.
Server create request VirtualMachine manifest May reference an instancetype, preference, and boot source.
Compute host Kubernetes node Selected by Kubernetes scheduler plus KubeVirt constraints.
Nova scheduler Kubernetes scheduler + KubeVirt admission/controllers Placement is Kubernetes-native, with KubeVirt-specific validation.
Placement resource providers Kubernetes nodes/resources/extended resources GPUs, KVM, tun, vhost-net, etc. appear as pod resources/device plugin resources.
Neutron port/network VMI network/interface definitions, Multus NADs, pod network Depends on cluster networking setup.
Cinder volume PVC / DataVolume VM disks are Kubernetes storage resources.
Config drive / metadata service cloud-init NoCloud/ConfigDrive, access credentials Commonly specified as VM volumes.
Keypair injection accessCredentials / cloud-init SSH keys Can source from Kubernetes Secret.
Console virtctl console, virtctl vnc, serial console log Depends on guest/VM config.
libvirt XML Generated in virt-launcher pod Usually inspected via virt-launcher logs or virsh dumpxml if RBAC permits exec.
nova live-migration virtctl migrate Live migration of a running VMI.
nova resize Stop VM, update instancetype/preference refs, start VM No direct Nova-style confirm/revert transaction.
nova evacuate KubeVirt node drain/eviction/live migration Controlled by eviction strategy and migration policy.
Shelve/unshelve Stop/start VM, possibly preserve PVCs Not a perfect 1:1 mapping.
Delete server Delete VirtualMachine; cleanup depends on DataVolume/PVC ownership PVC retention depends on how disks were created/owned.

Object roles

VirtualMachine

The persistent desired-state object. Similar to Nova's instance record plus desired power state.

apiVersion: kubevirt.io/v1
kind: VirtualMachine
spec:
  runStrategy: Always
  instancetype:
    kind: VirtualMachineInstancetype
    name: devstack-8c8g
  preference:
    kind: VirtualMachinePreference
    name: devstack
  template:
    spec:
      domain: {}
      volumes: []
      networks: []

VirtualMachineInstance / VMI

The live running instance. Similar to the active libvirt domain.

oc get vmi -n <namespace>
oc describe vmi <name> -n <namespace>

A stopped VM has no VMI.

VirtualMachineInstancetype

Closest to a Nova flavor.

Example:

apiVersion: instancetype.kubevirt.io/v1beta1
kind: VirtualMachineInstancetype
metadata:
  name: devstack-8c8g
spec:
  cpu:
    guest: 8
    model: host-passthrough
  memory:
    guest: 8Gi
  ioThreadsPolicy: auto

VirtualMachinePreference

Closest to image hardware metadata / guest hardware policy.

Example:

apiVersion: instancetype.kubevirt.io/v1beta1
kind: VirtualMachinePreference
metadata:
  name: devstack
spec:
  cpu:
    preferredCPUTopology: cores
  devices:
    preferredDiskBus: virtio
    preferredInterfaceModel: virtio
    preferredRng: {}
  features:
    preferredKvm: {}
  firmware:
    preferredEfi:
      secureBoot: false
  machine:
    preferredMachineType: q35

Boot source / DataSource

Closest to a Glance image reference, but implemented through CDI/PVCs.

A boot source can advertise default instancetype and preference labels:

metadata:
  labels:
    instancetype.kubevirt.io/default-instancetype: devstack-8c8g
    instancetype.kubevirt.io/default-preference: devstack

Basic workflows

Create a VM from boot source + instancetype + preference

apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: my-vm
spec:
  runStrategy: Always
  instancetype:
    kind: VirtualMachineInstancetype
    name: devstack-8c8g
  preference:
    kind: VirtualMachinePreference
    name: devstack
  dataVolumeTemplates:
  - metadata:
      name: my-vm-rootdisk
    spec:
      sourceRef:
        kind: DataSource
        name: debian-13
        namespace: my-namespace
      storage:
        resources:
          requests:
            storage: 80Gi
        storageClassName: rh-internal-nfs
  template:
    spec:
      domain:
        devices:
          interfaces:
          - name: default
            masquerade: {}
      networks:
      - name: default
        pod: {}
      volumes:
      - name: rootdisk
        dataVolume:
          name: my-vm-rootdisk

Apply:

oc apply -f vm.yaml -n <namespace>
oc get vm,vmi,dv,pvc -n <namespace>

Start / stop / restart

virtctl start <vm> -n <namespace>
virtctl stop <vm> -n <namespace>
virtctl restart <vm> -n <namespace>

Equivalent mental model:

  • start: create a VMI from the VM desired state.
  • stop: remove the VMI while keeping the VM object and disks.
  • restart: recreate the VMI.

Inspect VM and running VMI

oc get vm <vm> -n <namespace> -o yaml
oc get vmi <vm> -n <namespace> -o yaml
oc describe vm <vm> -n <namespace>
oc describe vmi <vm> -n <namespace>

Useful compact inspection:

oc get vmi <vm> -n <namespace> -o jsonpath='cpu={.spec.domain.cpu}{"\n"}memory={.spec.domain.memory}{"\n"}ioThreads={.spec.domain.ioThreadsPolicy}{"\n"}firmware={.spec.domain.firmware}{"\n"}features={.spec.domain.features}{"\n"}machine={.spec.domain.machine}{"\n"}'

Expand instancetype/preference

virtctl expand shows the VM after instancetype/preference expansion.

virtctl expand --vm <vm> -n <namespace>
virtctl expand --vm <vm> -n <namespace> -o json

This is inspect-only; it does not modify the VM.

Resize-like workflow: change instancetype/preference

KubeVirt does not provide a Nova-style resize transaction with confirm/revert. The closest cold resize workflow is:

  1. Stop the VM.
  2. Patch spec.instancetype and/or spec.preference.
  3. Remove old revisionName pins.
  4. Start the VM.
  5. Validate the new VMI.

Example:

NS=<namespace>
VM=<vm>

virtctl stop "$VM" -n "$NS"

# Wait for VMI deletion
oc get vmi "$VM" -n "$NS"

oc patch vm "$VM" -n "$NS" --type=merge -p '{
  "spec": {
    "instancetype": {
      "kind": "VirtualMachineInstancetype",
      "name": "devstack-8c8g"
    },
    "preference": {
      "kind": "VirtualMachinePreference",
      "name": "devstack"
    }
  }
}'

virtctl start "$VM" -n "$NS"

Validate:

oc get vm,vmi -n "$NS" | grep "$VM"
oc get vmi "$VM" -n "$NS" -o jsonpath='{.spec.domain.cpu}{"\n"}{.spec.domain.memory}{"\n"}'

Revision pinning

KubeVirt captures instancetype/preference revisions on VM creation/start:

spec:
  instancetype:
    name: devstack-8c8g
    revisionName: ...
  preference:
    name: devstack
    revisionName: ...

This is similar to Nova preserving flavor/image metadata on an instance. Editing the global instancetype or preference does not automatically mutate existing VMs. To consume a new definition, update the VM reference and clear/recreate the revision reference by replacing the field without revisionName.

Live migration

virtctl migrate <vm> -n <namespace>

Watch:

oc get vmi <vm> -n <namespace> -w
oc get virtualmachineinstancemigrations -n <namespace>

This maps to Nova live migration, not resize.

Console / access

virtctl console <vm> -n <namespace>
virtctl vnc <vm> -n <namespace>
virtctl ssh <user>@<vm> -n <namespace>

Guest agent helpers, if installed/running:

virtctl guestosinfo <vm> -n <namespace>
virtctl fslist <vm> -n <namespace>
virtctl userlist <vm> -n <namespace>

Inspect generated QEMU/libvirt details

If RBAC permits exec into virt-launcher:

POD=$(oc get pod -n <namespace> -l vm.kubevirt.io/name=<vm> -o jsonpath='{.items[0].metadata.name}')
oc exec -n <namespace> "$POD" -c compute -- virsh dumpxml 1

If exec is blocked, inspect virt-launcher logs for the QEMU command line:

oc logs -n <namespace> "$POD" -c compute | grep -i qemu-kvm

Example check for Free Page Reporting:

oc logs -n <namespace> "$POD" -c compute | grep -i free-page-reporting

A QEMU arg like this indicates FPR is enabled:

-device ...,"virtio-balloon...","free-page-reporting":true,...

Storage concepts

Nova/Cinder concept KubeVirt concept
Root disk from image DataVolume cloning/importing from DataSource/PVC
Cinder volume PVC
Boot from volume VM volume backed by PVC/DataVolume
Volume attach Add VM volume / hotplug volume if supported
Ephemeral disk containerDisk or ephemeral volume patterns

Common commands:

oc get dv,pvc -n <namespace>
oc describe dv <name> -n <namespace>
oc describe pvc <name> -n <namespace>
virtctl addvolume <vm> --volume-name <name> -n <namespace>
virtctl removevolume <vm> --volume-name <name> -n <namespace>

Networking concepts

Nova/Neutron concept KubeVirt concept
Port VMI interface/network attachment
Tenant network Pod network or Multus network
Security groups Kubernetes/OVN/network policy depending on platform
Floating IP Service/route/load balancer or external networking integration

Simple pod-network masquerade example:

networks:
- name: default
  pod: {}
domain:
  devices:
    interfaces:
    - name: default
      masquerade: {}

Quotas and limits

OpenShift/Kubernetes quotas apply to KubeVirt through the resources consumed by VMs:

  • pods
  • CPU/memory requests and limits
  • PVC count
  • storage requests
  • services/load balancers if exposed
  • extended resources such as KVM/tun/vhost-net/GPU devices

Useful checks:

oc get resourcequota -n <namespace>
oc describe quota -n <namespace>
oc get appliedclusterresourcequota -n <namespace>
oc describe appliedclusterresourcequota -n <namespace>
oc describe limitrange -n <namespace>

CPU and memory notes

  • VirtualMachineInstancetype.spec.cpu.guest defines guest vCPU count.
  • VirtualMachineInstancetype.spec.memory.guest defines guest-visible RAM.
  • memory.overcommitPercent can reduce the virt-launcher memory request, but increases risk.
  • CPU overcommit is generally controlled by Kubernetes requests/limits and whether dedicated CPU placement is used.
  • dedicatedCPUPlacement is closer to pinned CPUs / dedicated pCPUs.
  • CPU topology is influenced by VirtualMachinePreference.spec.cpu.preferredCPUTopology.

Example topology preference:

spec:
  cpu:
    preferredCPUTopology: cores

Firmware and machine type notes

Common preference settings for Linux/q35/UEFI without secure boot:

spec:
  firmware:
    preferredEfi:
      secureBoot: false
  machine:
    preferredMachineType: q35

Mental model summary

Nova flavor              -> VirtualMachineInstancetype
Nova image               -> DataSource / PVC / DataVolume / boot source
Nova image hw metadata   -> VirtualMachinePreference
Nova server              -> VirtualMachine
Running libvirt domain   -> VirtualMachineInstance
Nova resize              -> stop, patch instancetype/preference, clear revisions, start
Nova live migration      -> virtctl migrate
Cinder volume            -> PVC
Config drive/cloud-init  -> cloudInitNoCloud/cloudInitConfigDrive volume
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment