Virtual Machine

Every VMI object represents a single running virtual machine instance.

While VM represents the abstraction of virtual machine instances.

Create Virtual Machines Manifests

The virtctl sub command create vm allows easy creation of VirtualMachine manifests from the command line. It leverages instance types and preferences and provides several flags to control details of the created VM.

For example there are flags to specify the name or run strategy of a VM or flags to add volumes to a VM. Instance types and preferences can either be specified directly or it is possible to let KubeVirt infer those from the volume used to boot the VM.

For a full set of flags and their description use the following command:

virtctl create vm -h

Create Virtual Machines on a Cluster

The output of virtctl create vm can be piped into kubectl to directly create a VM on a cluster.

For example:

# Create a VM with name my-vm on the cluster
virtctl create vm --name my-vm | kubectl create -f -
virtualmachine.kubevirt.io/my-vm created

Specify Cloud-init User Data

To pass cloud-init user data to virtctl it needs to be encoded into a base64 string.

For example:

# Put your cloud-init user data into a file.
# This will add an authorized key to the default user.
# To get the default username read the documentation for the cloud image
$ cat cloud-init.txt
#cloud-config
ssh_authorized_keys:
- ssh-rsa AAAA...

# Base64 encode the contents of the file without line wraps and store it in a variable
$ CLOUD_INIT_USERDATA=$(base64 -w 0 cloud-init.txt)

# Show the contents of the variable
$ echo $CLOUD_INIT_USERDATA I2Nsb3VkLWNvbmZpZwpzc2hfYXV0aG9yaXplZF9rZXlzOgogIC0gc3NoLXJzYSBBQUFBLi4uCg==

You can now use this variable as an argument to the --cloud-init-user-data flag:

virtctl create vm --cloud-init-user-data $CLOUD_INIT_USERDATA

Create VM Directly from Manifest

You can create the VM or virtual machine instances directly from manifest.

apiVersion: kubevirt.io/v1

kind: VirtualMachine
metadata:
 name: sample-test-vm
spec:
 running: true
 template:
   metadata:
    labels:
      kubevirt.io/size: small
      kubevirt.io/domain: ubuntu-bionic
  spec:
    domain:
      cpu:
        cores: 1
      devices:
        disks:
          - name: containervolume
            disk:
              bus: virtio
          - name: cloudinitvolume
            disk:
              bus: virtio
        interfaces:
        - name: default
          masquerade: {}
      resources:
        requests:
          memory: 1024M
    networks:
    - name: default
      pod: {}
    volumes:
      - name: containervolume
        containerDisk:
          image: tedezed/ubuntu-container-disk:20.0
      - name: cloudinitvolume
        cloudInitNoCloud:
          userData: |-
            #cloud-config
            chpasswd:
              list: |
                ubuntu:ubuntu
                root:root
              expire: False

Access VMs

Once a VM is started, you are able to connect to the consoles it exposes. Usually there are two types of consoles:

  • Serial Console

    The serial console of a virtual machine can be accessed by using the console command:

    virtctl console testvm
    
  • Graphical Console (VNC)

    If NoVnc is installed on Cluster and exposed over NodePort, you can access virtual machines with http://<cluster IP>:port.

    Note

    Refer the section Install NoVNC for more details.

Lifecycle

Every VMI represents a single virtual machine instance. In general, the management of VMIs is kept similar to how Pods are managed. Every VM that is defined in the cluster is expected to be running, just like pods. Deleting a VMI is equivalent to shutting it down, this is also equivalent to how pods behave.

Launch a Virtual Machine

To start a VMI, you need to create a VMI object using kubectl:

kubectl create -f vmi.yaml

Example of vmi.yaml:

apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
 name: sample-test-vm
spec:
 running: true
 template:
   metadata:
     labels:
       kubevirt.io/size: small
       kubevirt.io/domain: ubuntu-bionic
   spec:
     domain:
       cpu:
         cores: 1
       devices:
         disks:
           - name: containervolume
             disk:
               bus: virtio
           - name: cloudinitvolume
             disk:
               bus: virtio
         interfaces:
         - name: default
           masquerade: {}
       resources:
         requests:
           memory: 1024M
     networks:
     - name: default
       pod: {}
     volumes:
       - name: containervolume
         containerDisk:
           image: tedezed/ubuntu-container-disk:20.0
       - name: cloudinitvolume
         cloudInitNoCloud:
           userData: |-
             #cloud-config
             chpasswd:
               list: |
                 ubuntu:ubuntu
                 root:root
               expire: False

List the VM

VMIs can be listed by querying for VMI objects:

kubectl get vmis

Retrieve a VMI Definition

A single VMI definition can be retrieved by getting the specific VMI object.

kubectl get vmis testvmi

Remove a VMI

To stop the VMI, you need to delete the corresponding VMI object using kubectl.

$ kubectl delete -f vmi.yaml

OR

$ kubectl delete vmis testvmi

Note

Stopping a VMI implies that it will be deleted from the cluster. You will not be able to start this VMI object again.

Start and Stop a VM

VMs, in contrast to VMIs, have a running state. Thus, on a VM you can define if it should be running, or not. VMIs are always running and consuming resources, if they are defined in the cluster

virtctl is used to start a VM:

$ virtctl start my-vm

And to stop a VM:

$ virtctl stop my-vm

Note

If you run the force stop to the VM, it may result in data inconsistencies, or there may be data loss.

Pause and Unpause a VM

Note

Pausing in this context refers to libvirt’s virDomainSuspend command. The process is frozen without further access to CPU resources and I/O but the memory used by the domain at the hypervisor level will stay allocated.

To pause a VM, you need the virtctl command line tool. The pause command works on either VMs or VMIs:

$ virtctl pause vm testvm

OR

$ virtctl pause vmi testvm

Paused VMIs have a Paused condition in their status:

$ kubectl get vmi testvm -o=jsonpath='{.status.conditions[?(@.type=="Paused")].message}'

VMI was paused by user

Unpausing works similar to pausing:

$ virtctl unpause vm testvm

OR

$ virtctl unpause vmi testvm