Treat VMs as a Kubernetes Object Using KubeVirt

KubeVirt provides a unified development platform where developers can build, modify, and deploy applications residing in both Containers and Virtual Machines in a common environment. This lesson guides the user through all the steps required to install KubeVirt on a Kubernetes cluster and run a Virtual Machine. On completing this lesson, the user will learn the following skills:

  • Installation of the latest KubeVirt using operators and the KubeVirt Custom Resource
  • Installation of virtctl, the command-line client for managing Virtual Machines
  • Use of kubectl and virtctl commands to create, start, stop, and report status of Virtual Machines

Deploy KubeVirt

Deploy the KubeVirt operator using the latest KubeVirt version. An Operator is a method of packaging, deploying and managing a Kubernetes application. A Kubernetes application is an application that is both deployed on Kubernetes and managed using the Kubernetes APIs and kubectl tooling. You can think of Operators as the runtime that manages this type of application on Kubernetes. If you want to learn more about Operators you can check here.

We query GitHub's API to get the latest available release. Assuming that you're connected to some Kubernetes cluster, execute the following code on your terminal:

export KUBEVIRT_VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases/latest | jq -r .tag_name) 
echo $KUBEVIRT_VERSION

Run the following command to deploy the KubeVirt Operator:

kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-operator.yaml

Now let's deploy KubeVirt by creating a Custom Resource that will trigger the 'operator' reaction and perform the deployment:

kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-cr.yaml

Next, we need to configure KubeVirt to use software emulation for virtualization. This is necessary for the development environment, but results in poor performance, so avoid this step in production environments.

kubectl -n kubevirt patch kubevirt kubevirt --type=merge --patch '{"spec":{"configuration":{"developerConfiguration":{"useEmulation":true}}}}'

Let's check the deployment:

kubectl get pods -n kubevirt

Once it's ready, it will show something similar to:

~~~

controlplane $ kubectl get pods -n kubevirt

NAME                               READY     STATUS    RESTARTS   AGE

virt-api-7fc57db6dd-g4s4w          1/1       Running   0          3m

virt-api-7fc57db6dd-zd95q          1/1       Running   0          3m

virt-controller-6849d45bcc-88zd4   1/1       Running   0          3m

virt-controller-6849d45bcc-cmfzk   1/1       Running   0          3m

virt-handler-fvsqw                 1/1       Running   0          3m

virt-operator-5649f67475-gmphg     1/1       Running   0          4m

virt-operator-5649f67475-sw78k     1/1       Running   0          4m

~~~

Install Virtctl

`virtctl` is a client utility that helps interact with VM's (start/stop/console, etc):

wget -O virtctl https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/virtctl-${KUBEVIRT_VERSION}-linux-amd64

chmod +x virtctl

Now everything is ready to continue and launch a VM.

Deploy a VM

The command below applies a YAML definition of a virtual machine into our current Kubernetes environment, defining the VM name, the resources required (disk, CPU, memory), etc. You can take a look at the vm.yaml file if you have interest in knowing more about a virtual machine definition:

kubectl apply -f https://kubevirt.io/labs/manifests/vm.yaml

We are creating a Virtual Machine in the same way as we would create any other Kubernetes resource thanks to what KubeVirt has enabled in our environment. Now we have a Virtual Machine as a Kubernetes resource.

After the vm resource has been created, you can manage the VMs with standard 'kubectl' commands:

kubectl get vms
kubectl get vms -o yaml testvm

Check that the VM is defined (using commands above):

kubectl get vms

Notice from the output that the VM is not running yet.

To start a VM, `virtctl` should be used:

./virtctl start testvm

Alternatively you can use `kubectl edit vm testvm` to set `.spec.running: true`.

Now you can check again the VM status:

kubectl get vms

A `VirtualMachine` resource contains a VM's definition and status. An instance of a running VM has an additional associated resource, a `VirtualMachineInstance`.

Once the VM is running you can inspect its status:

kubectl get vmis
kubectl get vmis -o yaml testvm
kubectl get vmis

Once it's ready, the command above will print something like:

~~~ controlplane $ kubectl get vmis

NAME    AGE    PHASE           IP                NODENAME

testvm   1m        Running         10.32.0.11   controlplane

~~~  

Accessing VMs (serial console & vnc)

Now that a VM is running you can access its serial console:

~~~ # Connect to the serial console $ ./virtctl console testvm ~~~

In environments where VNC client access is available, the graphical console of a VM can be accessed with the virtctl vnc command.

Shutdown and cleanup

Shutting down a VM works by either using `virtctl` or editing the VM.

./virtctl stop testvm

Finally, the VM can be deleted using:

kubectl delete vms testvm

Reference

This lesson is referenced from this public GitHub repository

Beyond KBE

We hope you enjoyed this lesson. For more information about KubeVirt, please