1.2. Start and stop a VM
In the previous section, we wrote a VirtualMachine specification and applied the manifest to the Kubernetes cluster.
Lifecycle
When the underlying technology libvirt refers to a VM it often also uses the concept of so-called guest domains.
According to libvirt.org , a guest domain can be in several states:
- Undefined: This is a baseline state. Libvirt does not know anything about domains in this state because the domain hasn’t been defined or created yet.
- Defined or Stopped: The domain has been defined but it’s not running. This state is also called stopped. Only persistent domains can be in this state. When a transient domain is stopped or shut down, it ceases to exist.
- Running: The domain has been created and started either as transient or persistent domain. Either domain in this state is being actively executed on the node’s hypervisor.
- Paused: The domain execution on the hypervisor has been suspended. Its state has been temporarily stored until it is resumed. The domain does not have any knowledge whether it was paused or not.
- Saved: Similar to the paused state, but the domain state is stored to persistent storage. Again, the domain in this state can be restored and it does not notice that any time has passed.

Note
In this section we will have a look how to use the statesRunning, Stopped (Defined) and Paused.Task 1.2.1: List your virtual machines
Since you created a VirtualMachine in the previous section, you may verify its creation with:
kubectl get virtualmachine --namespace lab-<username>
You should see your virtual machines listed as follows:
NAME AGE STATUS READY
lab01-firstvm 10m Stopped False
This indicates that the VM has been created but is still in a stopped state.
Note
In Kubernetes, the resource VirtualMachine has a shortname vm. Therefore, the following command is equivalent to the one above:
kubectl get vm --namespace lab-<username>
Working with your VMs
There are different ways of starting and stopping your virtual machines.
You can patch your VirtualMachine resource with kubectl or use virtctl to start the VM.
Try starting and stopping your VM with different methods.
Task 1.2.4: Start with kubectl
Your VirtualMachine resource contains a field spec.runStrategy which indicates the desired state of the VM. You can check
the resource with:
kubectl describe vm lab01-firstvm --namespace lab-<username>
Alternatively you can directly select the relevant field using a jsonpath:
kubectl get vm lab01-firstvm -o jsonpath='{.spec.runStrategy}' --namespace lab-<username>
Note
With kubectl all you have to do to start and stop your VM is patching the field spec.runStrategy.
Alwaysto start vmHaltedto stop the vm
Use the following command to start your VM:
kubectl patch vm lab01-firstvm --type merge -p '{"spec":{"runStrategy":"Always"}}' --namespace lab-<username>
The output should be:
virtualmachine.kubevirt.io/lab01-firstvm patched
Now check the state of your VM again:
kubectl get vm --namespace lab-<username>
You should see that the VM is now in Running state:
NAME AGE STATUS READY
lab01-firstvm 11m Running True
Task 1.2.7: Stop with kubectl
Stopping the VM is similar to starting. Just set spec.runStrategy back to Halted:
kubectl patch vm lab01-firstvm --type merge -p '{"spec":{"runStrategy":"Halted"}}' --namespace lab-<username>
The output should again be:
virtualmachine.kubevirt.io/lab01-firstvm patched
Note
The process of starting and stopping VMs takes a bit of time. Make sure the VM is in statusStopped before you start it again.Task 1.2.8: Start with virtctl
The binary virtctl provides an easier way of interacting with KubeVirt VMs. And adds additional features like:
- Serial and graphical console access
- Starting and stopping VirtualMachineInstances
- Live migrating VirtualMachineInstances
- Uploading virtual machine disk images
- Adding, removing volumes
- Exposing services
- Debugging features: creating memory dumps
We will use some of those functionalities during the lab.
virtctl uses the default kubeconfig to interact with the Kubernetes Cluster.
Explore the capabilities of virtctl by executing the following commands:
virtctl --help
and
virtctl <command> --help
or the following to display all options
virtctl options
Let’s now start the VM by using virtctl by executing the following command:
virtctl start lab01-firstvm --namespace lab-<username>
The output should be:
VM lab01-firstvm was scheduled to start
If you check the state of your VM you’ll see that it had the same effect as using the kubectl command:
kubectl get vm --namespace lab-<username>
Your VM is in Running state:
NAME AGE STATUS READY
lab01-firstvm 11m Running True
Question to explore virtctl: What’s the exact command to restart a VM (vm-to-restart) using the kubeconfig from (~/.kube/prod-cluster the config does not exist in the webshell, it’s just an example)
Solution
virtctl --kubeconfig ~/.kube/prod-cluster restart vm-to-restart --namespace lab-<username>
Task 1.2.9: Stop with virtctl
When using the --dry-run option we can see what would happen without really executing the actual command. This can be a helpful option when interacting with production workload.
Let’s dry-run the stop command:
virtctl stop lab01-firstvm --dry-run --namespace lab-<username>
This will return the following:
Dry Run execution
VM lab01-firstvm was scheduled to stop
To stop your VM for real, remove the --dry-run option:
virtctl stop lab01-firstvm --namespace lab-<username>
The output should be:
VM lab01-firstvm was scheduled to stop
Task 1.2.10: Pause a VirtualMachine with virtctl
Pausing a VM is as simple as:
virtctl pause vm lab01-firstvm --namespace lab-<username>
However, if you try to execute above command, it will result in an error:
Error pausing VirtualMachineInstance lab01-firstvm. VirtualMachine lab01-firstvm is not set to run
Obviously we can not pause a stopped VM, so start the VM first and then try the pause command again:
virtctl start lab01-firstvm --namespace lab-<username>
Make sure the VM shows it has started before you pause it:
kubectl get vm --namespace lab-<username>
Now pause it:
virtctl pause vm lab01-firstvm --namespace lab-<username>
The output should be:
VMI lab01-firstvm was scheduled to pause
Again, verify the state of the VM:
kubectl get vm --namespace lab-<username>
Resuming a VM can be done with:
virtctl unpause vm lab01-firstvm --namespace lab-<username>
The output should be:
VMI lab01-firstvm was scheduled to unpause
Involved components
When your VM is in a running state, you may have noticed that there is an additional pod running. Make sure your VM is running and issue the following command:
kubectl get pods --namespace lab-<username>
The output will be similar to:
NAME READY STATUS RESTARTS AGE
<username>-webshell-885dbc579-lwhtd 2/2 Running 0 1d
virt-launcher-lab01-firstvm-mfxrs 3/3 Running 0 90s
For each running VM there is a virt-launcher pod which is responsible to start the effective VM process in the container and observes the VM state.
Beside the existence of the virt-launcher pod, a new custom resource VirtualMachineInstance is present. This resource is
created under the hood by the virt-controller and will only be available as long as the VM is running. It represents a
single running virtual machine instance.
You may see your VirtualMachineInstance with the following command:
kubectl get vmi --namespace lab-<username>
Note
Note thatvmi is the shortname for VirtualMachineInstance just like vm for VirtualMachine.The output will be similar to:
NAME AGE PHASE IP NODENAME READY
lab01-firstvm 3m59s Running 10.244.3.144 training-worker-0 True
Above output also indicates that our lab01-firstvm is running on Kubernetes node training-worker-0.
Note
You may use -o wide to get more details about the VM.
kubectl get vmi -o wide --namespace lab-<username>
With wide you can see if your VM is live-migratable or is currently in a paused state.
The output of a paused VM will be:
NAME AGE PHASE IP NODENAME READY LIVE-MIGRATABLE PAUSED
lab01-firstvm 7m52s Running 10.244.3.144 training-worker-0 True True
Task 1.2.11: (Optional) Under the hood: Explore the virt-launcher pod
In this optional lab we are going to explore the virt-launcher pod, which we discovered in the previous task.
For every VirtualMachineInstance or VMI (running VM), one virt-launcher pod is created. The virt-launcher pod provides boundaries (cgoups, namespaces), the interface to the Kubernetes ecosystem and manages and monitors the lifecycle of the VMI.
In its core, the virt-launcher pod runs a libvirtd instance, which manages the lifecycle of the VMI process.
With the following command, we can have a look at the pod’s manifest (replace the pod name with the actual pod’s name from kubectl get pods --namespace lab-<username>):
kubectl get pod virt-launcher-lab01-firstvm-<pod> -o yaml --namespace lab-<username>
Or simply use the describe command:
kubectl describe pod virt-launcher-lab01-firstvm-<pod> --namespace lab-<username>
Explore the pod definition or use the describe command:
labelsownerReferenceinitContainersandcontainerscontainer-disk-binaryvolumecontainerdisk-initcomputevolumecontainerdiskguest-console-log
limitsandrequestsvolumesandvolumeMountsstatus
You can even exec into the pod and list the running processes, where you can find the running libvirt and qemu-kvm processes:
kubectl exec --stdin --tty --namespace lab-<username> virt-launcher-lab01-firstvm-<pod> -- /bin/bash
ps -ef
Press CTRL + d or type exit to exit the shell of the pod again.
Note
This does not connect to a shell within the VirtualMachineInstance but to the pod which is managing the VirtualMachineInstance.
Connecting to the shell of a VirtualMachineInstance will be explained in the next lab.