Instance types and preferences

FEATURE STATE:

  • instancetype.kubevirt.io/v1alpha1 (Experimental) as of the v0.56.0 KubeVirt release
  • instancetype.kubevirt.io/v1alpha2 (Experimental) as of the v0.58.0 KubeVirt release
  • instancetype.kubevirt.io/v1beta1 as of the v1.0.0 KubeVirt release

See the Version History section for more details.

Introduction

KubeVirt’s VirtualMachine API contains many advanced options for tuning the performance of a VM that goes beyond what typical users need to be aware of. Users have previously been unable to simply define the storage/network they want assigned to their VM and then declare in broad terms what quality of resources and kind of performance characteristics they need for their VM.

Instance types and preferences provide a way to define a set of resource, performance and other runtime characteristics, allowing users to reuse these definitions across multiple VirtualMachines.

VirtualMachineInstancetype

  1. ---
  2. apiVersion: instancetype.kubevirt.io/v1beta1
  3. kind: VirtualMachineInstancetype
  4. metadata:
  5. name: example-instancetype
  6. spec:
  7. cpu:
  8. guest: 1
  9. memory:
  10. guest: 128Mi

KubeVirt provides two CRDs for instance types, a cluster wide VirtualMachineClusterInstancetype and a namespaced VirtualMachineInstancetype. These CRDs encapsulate the following resource related characteristics of a VirtualMachine through a shared VirtualMachineInstancetypeSpec:

  • CPU : Required number of vCPUs presented to the guest
  • Memory : Required amount of memory presented to the guest
  • GPUs : Optional list of vGPUs to passthrough
  • HostDevices : Optional list of HostDevices to passthrough
  • IOThreadsPolicy : Optional IOThreadsPolicy to be used
  • LaunchSecurity: Optional LaunchSecurity to be used

Anything provided within an instance type cannot be overridden within the VirtualMachine. For example, as CPU and Memory are both required attributes of an instance type, if a user makes any requests for CPU or Memory resources within the underlying VirtualMachine, the instance type will conflict and the request will be rejected during creation.

VirtualMachinePreference

  1. ---
  2. apiVersion: instancetype.kubevirt.io/v1beta1
  3. kind: VirtualMachinePreference
  4. metadata:
  5. name: example-preference
  6. spec:
  7. devices:
  8. preferredDiskBus: virtio
  9. preferredInterfaceModel: virtio

KubeVirt also provides two further preference based CRDs, again a cluster wide VirtualMachineClusterPreference and namespaced VirtualMachinePreference. These CRDsencapsulate the preferred value of any remaining attributes of a VirtualMachine required to run a given workload, again this is through a shared VirtualMachinePreferenceSpec.

Unlike instance types, preferences only represent the preferred values and as such, they can be overridden by values in the VirtualMachine provided by the user.

In the example shown below, a user has provided a VirtualMachine with a disk bus already defined within a DiskTarget and has also selected a set of preferences with DevicePreference and preferredDiskBus , so the user’s original choice within the VirtualMachine and DiskTarget are used:

  1. $ kubectl apply -f - << EOF
  2. ---
  3. apiVersion: instancetype.kubevirt.io/v1beta1
  4. kind: VirtualMachinePreference
  5. metadata:
  6. name: example-preference-disk-virtio
  7. spec:
  8. devices:
  9. preferredDiskBus: virtio
  10. ---
  11. apiVersion: kubevirt.io/v1
  12. kind: VirtualMachine
  13. metadata:
  14. name: example-preference-user-override
  15. spec:
  16. preference:
  17. kind: VirtualMachinePreference
  18. name: example-preference-disk-virtio
  19. runStrategy: Halted
  20. template:
  21. spec:
  22. domain:
  23. memory:
  24. guest: 128Mi
  25. devices:
  26. disks:
  27. - disk:
  28. bus: sata
  29. name: containerdisk
  30. - disk: {}
  31. name: cloudinitdisk
  32. resources: {}
  33. terminationGracePeriodSeconds: 0
  34. volumes:
  35. - containerDisk:
  36. image: registry:5000/kubevirt/cirros-container-disk-demo:devel
  37. name: containerdisk
  38. - cloudInitNoCloud:
  39. userData: |
  40. #!/bin/sh
  41. echo 'printed from cloud-init userdata'
  42. name: cloudinitdisk
  43. EOF
  44. virtualmachinepreference.instancetype.kubevirt.io/example-preference-disk-virtio created
  45. virtualmachine.kubevirt.io/example-preference-user-override configured
  46. $ virtctl start example-preference-user-override
  47. VM example-preference-user-override was scheduled to start
  48. # We can see the original request from the user within the VirtualMachine lists `containerdisk` with a `SATA` bus
  49. $ kubectl get vms/example-preference-user-override -o json | jq .spec.template.spec.domain.devices.disks
  50. [
  51. {
  52. "disk": {
  53. "bus": "sata"
  54. },
  55. "name": "containerdisk"
  56. },
  57. {
  58. "disk": {},
  59. "name": "cloudinitdisk"
  60. }
  61. ]
  62. # This is still the case in the VirtualMachineInstance with the remaining disk using the `preferredDiskBus` from the preference of `virtio`
  63. $ kubectl get vmis/example-preference-user-override -o json | jq .spec.domain.devices.disks
  64. [
  65. {
  66. "disk": {
  67. "bus": "sata"
  68. },
  69. "name": "containerdisk"
  70. },
  71. {
  72. "disk": {
  73. "bus": "virtio"
  74. },
  75. "name": "cloudinitdisk"
  76. }
  77. ]

PreferredCPUTopology

A preference can optionally include a PreferredCPUTopology that defines how the guest visible CPU topology of the VirtualMachineInstance is constructed from vCPUs supplied by an instance type.

  1. apiVersion: instancetype.kubevirt.io/v1beta1
  2. kind: VirtualMachinePreference
  3. metadata:
  4. name: example-preference-cpu-topology
  5. spec:
  6. cpu:
  7. preferredCPUTopology: cores

The allowed values for PreferredCPUTopology include:

  • sockets (default) - Provides vCPUs as sockets to the guest
  • cores - Provides vCPUs as cores to the guest
  • threads - Provides vCPUs as threads to the guest
  • spread - Spreads vCPUs across sockets and cores by default. See the following SpreadOptions section for more details.
  • any - Provides vCPUs as sockets to the guest, this is also used to express that any allocation of vCPUs is required by the preference. Useful when defining a preference that isn’t used alongside an instance type.

Note that support for the original preferSockets, preferCores, preferThreads and preferSpread values for PreferredCPUTopology is deprecated as of v1.4.0 ahead of removal in a future release.

SpreadOptions

When spread is provided as the value of PreferredCPUTopology we can further customize how vCPUs are spread across the guest visible CPU topology using SpreadOptions:

  1. apiVersion: instancetype.kubevirt.io/v1beta1
  2. kind: VirtualMachinePreference
  3. metadata:
  4. name: example-preference-cpu-topology
  5. spec:
  6. cpu:
  7. preferredCPUTopology: spread
  8. spreadOptions:
  9. across: SocketsCoresThreads
  10. ratio: 4

spreadOptions provides the following configurables:

  • across - Defines how vCPUs should be spread across the guest visible CPU topology
  • ratio - Defines the ratio at which vCPUs should be spread (defaults to 2)

The allowed values for across include:

  • SocketsCores (default) - Spreads vCPUs across sockets and cores with a ratio of 1:N where N is the provided ratio.
  • SocketsCoresThreads - Spreads vCPUs across sockets, cores and threads with a ratio of 1:N:2 where N is the provided ratio.
  • CoresThreads - Spreads vCPUs across cores and threads with an enforced ratio of 1:2. (requires at least 2 vCPUs to be provided by an instance type)

VirtualMachine

  1. ---
  2. apiVersion: kubevirt.io/v1
  3. kind: VirtualMachine
  4. metadata:
  5. name: example-vm
  6. spec:
  7. instancetype:
  8. kind: VirtualMachineInstancetype
  9. name: example-instancetype
  10. preference:
  11. kind: VirtualMachinePreference
  12. name: example-preference

The previous instance type and preference CRDs are matched to a given VirtualMachine through the use of a matcher. Each matcher consists of the following:

  • Name (string): Name of the resource being referenced
  • Kind (string): Optional, defaults to the cluster wide CRD kinds of VirtualMachineClusterInstancetype or VirtualMachineClusterPreference if not provided
  • RevisionName (string) : Optional, name of a ControllerRevision containing a copy of the VirtualMachineInstancetypeSpec or VirtualMachinePreferenceSpec taken when the VirtualMachine is first created. See the Versioning section below for more details on how and why this is captured.
  • InferFromVolume (string): Optional, see the Inferring defaults from a Volume section below for more details.

Creating InstanceTypes, Preferences and VirtualMachines

It is possible to streamline the creation of instance types, preferences, and virtual machines with the usage of the virtctl command-line tool. To read more about it, please see the Creating VirtualMachines.

Versioning

Versioning of these resources is required to ensure the eventual VirtualMachineInstance created when starting a VirtualMachine does not change between restarts if any referenced instance type or set of preferences are updated during the lifetime of the VirtualMachine.

This is currently achieved by using ControllerRevision to retain a copy of the VirtualMachineInstancetype or VirtualMachinePreference at the time the VirtualMachine is created. A reference to these ControllerRevisions are then retained in the InstancetypeMatcher and PreferenceMatcher within the VirtualMachine for future use.

  1. $ kubectl apply -f examples/csmall.yaml -f examples/vm-cirros-csmall.yaml
  2. virtualmachineinstancetype.instancetype.kubevirt.io/csmall created
  3. virtualmachine.kubevirt.io/vm-cirros-csmall created
  4. $ kubectl get vm/vm-cirros-csmall -o json | jq .spec.instancetype
  5. {
  6. "kind": "VirtualMachineInstancetype",
  7. "name": "csmall",
  8. "revisionName": "vm-cirros-csmall-csmall-72c3a35b-6e18-487d-bebf-f73c7d4f4a40-1"
  9. }
  10. $ kubectl get controllerrevision/vm-cirros-csmall-csmall-72c3a35b-6e18-487d-bebf-f73c7d4f4a40-1 -o json | jq .
  11. {
  12. "apiVersion": "apps/v1",
  13. "data": {
  14. "apiVersion": "instancetype.kubevirt.io/v1beta1",
  15. "kind": "VirtualMachineInstancetype",
  16. "metadata": {
  17. "creationTimestamp": "2022-09-30T12:20:19Z",
  18. "generation": 1,
  19. "name": "csmall",
  20. "namespace": "default",
  21. "resourceVersion": "10303",
  22. "uid": "72c3a35b-6e18-487d-bebf-f73c7d4f4a40"
  23. },
  24. "spec": {
  25. "cpu": {
  26. "guest": 1
  27. },
  28. "memory": {
  29. "guest": "128Mi"
  30. }
  31. }
  32. },
  33. "kind": "ControllerRevision",
  34. "metadata": {
  35. "creationTimestamp": "2022-09-30T12:20:19Z",
  36. "name": "vm-cirros-csmall-csmall-72c3a35b-6e18-487d-bebf-f73c7d4f4a40-1",
  37. "namespace": "default",
  38. "ownerReferences": [
  39. {
  40. "apiVersion": "kubevirt.io/v1",
  41. "blockOwnerDeletion": true,
  42. "controller": true,
  43. "kind": "VirtualMachine",
  44. "name": "vm-cirros-csmall",
  45. "uid": "5216527a-1d31-4637-ad3a-b640cb9949a2"
  46. }
  47. ],
  48. "resourceVersion": "10307",
  49. "uid": "a7bc784b-4cea-45d7-8432-15418e1dd7d3"
  50. },
  51. "revision": 0
  52. }
  53. $ kubectl delete vm/vm-cirros-csmall
  54. virtualmachine.kubevirt.io "vm-cirros-csmall" deleted
  55. $ kubectl get controllerrevision/controllerrevision/vm-cirros-csmall-csmall-72c3a35b-6e18-487d-bebf-f73c7d4f4a40-1
  56. Error from server (NotFound): controllerrevisions.apps "vm-cirros-csmall-csmall-72c3a35b-6e18-487d-bebf-f73c7d4f4a40-1" not found

Users can opt in to moving to a newer generation of an instance type or preference by removing the referenced revisionName from the appropriate matcher within the VirtualMachine object. This will result in fresh ControllerRevisions being captured and used.

The following example creates a VirtualMachine using an initial version of the csmall instance type before increasing the number of vCPUs provided by the instance type:

  1. $ kubectl apply -f examples/csmall.yaml -f examples/vm-cirros-csmall.yaml
  2. virtualmachineinstancetype.instancetype.kubevirt.io/csmall created
  3. virtualmachine.kubevirt.io/vm-cirros-csmall created
  4. $ kubectl get vm/vm-cirros-csmall -o json | jq .spec.instancetype
  5. {
  6. "kind": "VirtualMachineInstancetype",
  7. "name": "csmall",
  8. "revisionName": "vm-cirros-csmall-csmall-3e86e367-9cd7-4426-9507-b14c27a08671-1"
  9. }
  10. $ virtctl start vm-cirros-csmall
  11. VM vm-cirros-csmall was scheduled to start
  12. $ kubectl get vmi/vm-cirros-csmall -o json | jq .spec.domain.cpu
  13. {
  14. "cores": 1,
  15. "model": "host-model",
  16. "sockets": 1,
  17. "threads": 1
  18. }
  19. $ kubectl patch VirtualMachineInstancetype/csmall --type merge -p '{"spec":{"cpu":{"guest":2}}}'
  20. virtualmachineinstancetype.instancetype.kubevirt.io/csmall patched

In order for this change to be picked up within the VirtualMachine, we need to stop the running VirtualMachine and clear the revisionName referenced by the InstancetypeMatcher:

  1. $ virtctl stop vm-cirros-csmall
  2. VM vm-cirros-csmall was scheduled to stop
  3. $ kubectl patch vm/vm-cirros-csmall --type merge -p '{"spec":{"instancetype":{"revisionName":""}}}'
  4. virtualmachine.kubevirt.io/vm-cirros-csmall patched
  5. $ kubectl get vm/vm-cirros-csmall -o json | jq .spec.instancetype
  6. {
  7. "kind": "VirtualMachineInstancetype",
  8. "name": "csmall",
  9. "revisionName": "vm-cirros-csmall-csmall-3e86e367-9cd7-4426-9507-b14c27a08671-2"
  10. }

As you can see above, the InstancetypeMatcher now references a new ControllerRevision containing generation 2 of the instance type. We can now start the VirtualMachine again and see the new number of vCPUs being used by the VirtualMachineInstance:

  1. $ virtctl start vm-cirros-csmall
  2. VM vm-cirros-csmall was scheduled to start
  3. $ kubectl get vmi/vm-cirros-csmall -o json | jq .spec.domain.cpu
  4. {
  5. "cores": 1,
  6. "model": "host-model",
  7. "sockets": 2,
  8. "threads": 1
  9. }

inferFromVolume

The inferFromVolume attribute of both the InstancetypeMatcher and PreferenceMatcher allows a user to request that defaults are inferred from a volume. When requested, KubeVirt will look for the following labels on the underlying PVC, DataSource or DataVolume to determine the default name and kind:

  • instancetype.kubevirt.io/default-instancetype
  • instancetype.kubevirt.io/default-instancetype-kind (optional, defaults to VirtualMachineClusterInstancetype)
  • instancetype.kubevirt.io/default-preference
  • instancetype.kubevirt.io/default-preference-kind (optional, defaults to VirtualMachineClusterPreference)

These values are then written into the appropriate matcher by the mutation webhook and used during validation before the VirtualMachine is formally accepted.

The validation can be controlled by the value provided to inferFromVolumeFailurePolicy in either the InstancetypeMatcher or PreferenceMatcher of a VirtualMachine.

The default value of Reject will cause the request to be rejected on failure to find the referenced Volume or labels on an underlying resource.

If Ignore was provided, the respective InstancetypeMatcher or PreferenceMatcher will be cleared on a failure instead.

Example with implicit default value of Reject:

  1. $ kubectl apply -k https://github.com/kubevirt/common-instancetypes.git
  2. [..]
  3. $ virtctl image-upload pvc cirros-pvc --size=1Gi --image-path=./cirros-0.5.2-x86_64-disk.img
  4. [..]
  5. $ kubectl label pvc/cirros-pvc \
  6. instancetype.kubevirt.io/default-instancetype=server.tiny \
  7. instancetype.kubevirt.io/default-preference=cirros
  8. [..]
  9. $ kubectl apply -f - << EOF
  10. ---
  11. apiVersion: cdi.kubevirt.io/v1beta1
  12. kind: DataSource
  13. metadata:
  14. name: cirros-datasource
  15. spec:
  16. source:
  17. pvc:
  18. name: cirros-pvc
  19. namespace: default
  20. ---
  21. apiVersion: kubevirt.io/v1
  22. kind: VirtualMachine
  23. metadata:
  24. name: cirros
  25. spec:
  26. instancetype:
  27. inferFromVolume: cirros-volume
  28. preference:
  29. inferFromVolume: cirros-volume
  30. runStrategy: Halted
  31. dataVolumeTemplates:
  32. - metadata:
  33. name: cirros-datavolume
  34. spec:
  35. storage:
  36. resources:
  37. requests:
  38. storage: 1Gi
  39. storageClassName: local
  40. sourceRef:
  41. kind: DataSource
  42. name: cirros-datasource
  43. namespace: default
  44. template:
  45. spec:
  46. domain:
  47. devices: {}
  48. volumes:
  49. - dataVolume:
  50. name: cirros-datavolume
  51. name: cirros-volume
  52. EOF
  53. [..]
  54. kubectl get vms/cirros -o json | jq '.spec.instancetype, .spec.preference'
  55. {
  56. "kind": "virtualmachineclusterinstancetype",
  57. "name": "server.tiny",
  58. "revisionName": "cirros-server.tiny-76454433-3d82-43df-a7e5-586e48c71f68-1"
  59. }
  60. {
  61. "kind": "virtualmachineclusterpreference",
  62. "name": "cirros",
  63. "revisionName": "cirros-cirros-85823ddc-9e8c-4d23-a94c-143571b5489c-1"
  64. }

Example with explicit value of Ignore:

  1. $ virtctl image-upload pvc cirros-pvc --size=1Gi --image-path=./cirros-0.5.2-x86_64-disk.img
  2. $ kubectl apply -f - << EOF
  3. ---
  4. apiVersion: cdi.kubevirt.io/v1beta1
  5. kind: DataSource
  6. metadata:
  7. name: cirros-datasource
  8. spec:
  9. source:
  10. pvc:
  11. name: cirros-pvc
  12. namespace: default
  13. ---
  14. apiVersion: kubevirt.io/v1
  15. kind: VirtualMachine
  16. metadata:
  17. name: cirros
  18. spec:
  19. instancetype:
  20. inferFromVolume: cirros-volume
  21. inferFromVolumeFailurePolicy: Ignore
  22. preference:
  23. inferFromVolume: cirros-volume
  24. inferFromVolumeFailurePolicy: Ignore
  25. runStrategy: Halted
  26. dataVolumeTemplates:
  27. - metadata:
  28. name: cirros-datavolume
  29. spec:
  30. storage:
  31. accessModes:
  32. - ReadWriteOnce
  33. resources:
  34. requests:
  35. storage: 1Gi
  36. storageClassName: local
  37. sourceRef:
  38. kind: DataSource
  39. name: cirros-datasource
  40. namespace: default
  41. template:
  42. spec:
  43. domain:
  44. devices: {}
  45. volumes:
  46. - dataVolume:
  47. name: cirros-datavolume
  48. name: cirros-volume
  49. EOF
  50. [..]
  51. kubectl get vms/cirros -o json | jq '.spec.instancetype, .spec.preference'
  52. null
  53. null

common-instancetypes

The kubevirt/common-instancetypes provide a set of instancetypes and preferences to help create KubeVirt VirtualMachines.

See Deploy common-instancetypes on how to deploy them.

Examples

Various examples are available within the kubevirt repo under /examples. The following uses an example VirtualMachine provided by the containerdisk/fedora repo and replaces much of the DomainSpec with the equivalent instance type and preferences:

  1. $ kubectl apply -f - << EOF
  2. ---
  3. apiVersion: instancetype.kubevirt.io/v1beta1
  4. kind: VirtualMachineInstancetype
  5. metadata:
  6. name: cmedium
  7. spec:
  8. cpu:
  9. guest: 1
  10. memory:
  11. guest: 1Gi
  12. ---
  13. apiVersion: instancetype.kubevirt.io/v1beta1
  14. kind: VirtualMachinePreference
  15. metadata:
  16. name: fedora
  17. spec:
  18. devices:
  19. preferredDiskBus: virtio
  20. preferredInterfaceModel: virtio
  21. preferredRng: {}
  22. features:
  23. preferredAcpi: {}
  24. preferredSmm: {}
  25. firmware:
  26. preferredUseEfi: true
  27. preferredUseSecureBoot: true
  28. ---
  29. apiVersion: kubevirt.io/v1
  30. kind: VirtualMachine
  31. metadata:
  32. creationTimestamp: null
  33. name: fedora
  34. spec:
  35. instancetype:
  36. name: cmedium
  37. kind: virtualMachineInstancetype
  38. preference:
  39. name: fedora
  40. kind: virtualMachinePreference
  41. runStrategy: Always
  42. template:
  43. metadata:
  44. creationTimestamp: null
  45. spec:
  46. domain:
  47. devices: {}
  48. volumes:
  49. - containerDisk:
  50. image: quay.io/containerdisks/fedora:latest
  51. name: containerdisk
  52. - cloudInitNoCloud:
  53. userData: |-
  54. #cloud-config
  55. ssh_authorized_keys:
  56. - ssh-rsa AAAA...
  57. name: cloudinit
  58. EOF

Version History

instancetype.kubevirt.io/v1alpha1 (Experimental)

  • Initial development version.

instancetype.kubevirt.io/v1alpha2 (Experimental)

  • This version captured complete VirtualMachine{Instancetype,ClusterInstancetype,Preference,ClusterPreference} objects within the created ControllerRevisions

  • This version is backwardly compatible with instancetype.kubevirt.io/v1alpha1.

instancetype.kubevirt.io/v1beta1