DEV Community

Cover image for KubeVirt to run VMs in your K8s cluster
Sergio Méndez
Sergio Méndez

Posted on

KubeVirt to run VMs in your K8s cluster

Hi, dear readers I am starting a new series of blog posts called Learning Kubernetes with different complementing the traditional knowledge of Kubernetes. In this first post that I am going to share with my students in the university is about how to use KubeVirt in Kubernetes. One of my main topics in my course is virtualization so let me summarize my goals for writing this blog post:

  • Use VMs in container environments
  • Test how easy to use is KubeVirt
  • Customize my own VMs on a Kubernetes environment
  • Install KubeVirt on any Cloud Provider(GCP in specific) So let's start with the tutorial using KubeVirt. Let's have fun.

What you will learn

In this blog post you will learn how to:

  • Install KubeVirt bypassing the default requirements
  • Create a custom VM image in qcow2 with Qemu
  • Package your qcow2 image in a container image
  • Create a VM and expose VM services in KubeVirt

Requirements

  • A GKE cluster (Kubernetes cluster managed by Google Cloud)
  • Access to the cluster using kubectl
  • Preinstalled qemu in your distro (Let's asume Ubuntu) So let's get started with this tutorial. :)

Install KubeVirt bypassing the default requirements

To install KubeVirt get the KubeVirt latest stable version running the following steps:
1. Download the kubevirt-operator.yaml file and remove the affinity and tolerations:

export VERSION=$(curl -s https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt)
wget https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml
Enter fullscreen mode Exit fullscreen mode

Note: This downloads the kubevirt-operator.yaml file that you have to change to install the operator in any cloud provider like GKE, AKS or EKS. You have to change this file to remove the affinity and tolerations that the operator looks to deploy its components. KubeVirt looks for a control-plane node for security reason to deploy the operator.
2. Install the operator with the modified kubevirt-operator.yaml file

kubectl create -f "https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml"
Enter fullscreen mode Exit fullscreen mode

3. Create a KubeVirt definition to deploy the custom resource definitions:

cat << END > kubevirt-cr.yaml
apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
  name: kubevirt
  namespace: kubevirt
spec:
  certificateRotateStrategy: {}
  configuration:
    developerConfiguration:
      featureGates: []
  customizeComponents: {}
  imagePullPolicy: IfNotPresent
  workloadUpdateStrategy: {}
  infra:
    nodePlacement: {}
  workloads:
    nodePlacement: {}
END
Enter fullscreen mode Exit fullscreen mode

4. Deploy the definitions

kubectl apply -f kubevirt-cr.yaml
Enter fullscreen mode Exit fullscreen mode

5. Wait for the deployments to be ready you

kubectl get all -n kubevirt
Enter fullscreen mode Exit fullscreen mode

Create a custom VM image in qcow2 with Qemu

Assuming that you have an Ubuntu OS run the following steps:
1. Install Qemu:

sudo apt install qemu-kvm qemu-utils libvirt-daemon-system libvirt-clients bridge-utils
Enter fullscreen mode Exit fullscreen mode

2. In a directory create a disk for your VM, we are going to use Alpine for our VM:

qemu-img create -f qcow2 alpine_disk.qcow2 1G
Enter fullscreen mode Exit fullscreen mode

3. Download the ISO image for your Alpine VM

wget https://dl-cdn.alpinelinux.org/alpine/v3.23/releases/x86_64/alpine-standard-3.23.2-x86_64.iso
Enter fullscreen mode Exit fullscreen mode

4. Start the new Qemu VM and install the OS:

sudo qemu-system-x86_64 -enable-kvm -m 2G -cpu host -smp 2 -cdrom alpine-standard-3.22.0-x86_64.iso -drive file=alpine_disk.qcow2,format=qcow2 -boot d
Enter fullscreen mode Exit fullscreen mode

5. Boot from disk instead of the CD-ROM and install your software:

sudo qemu-system-x86_64   -enable-kvm   -m 2G   -cpu host   -smp 2   -drive file=alpine_disk.qcow2,format=qcow2
Enter fullscreen mode Exit fullscreen mode

6. Your new image alpine_disk.qcow2 its ready to be used.

Package your qcow2 image in a container image

Assuming that you have a Docker Hub user and you are login in your account run the following steps:
1. Create the Dockerfile to package for image

cat << END > Dockerfile
FROM scratch
ADD --chown=107:107 alpine_disk.qcow2 /disk/
END
Enter fullscreen mode Exit fullscreen mode

2. Tag you image with your Docker user

docker build -t <docker_hub_user>/alpineimage:latest .
docker push <docker_hub_user>/alpineimage:latest
Enter fullscreen mode Exit fullscreen mode

Create a VM a expose VM services in KubeVirt

To create a basic KubeVirt VM follow the next steps:
1. Create the KubeVirt VM definition

cat << END > vm.yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: alpinevm
spec:
  runStrategy: Halted
  template:
    metadata:
      labels:
        kubevirt.io/size: small
        kubevirt.io/domain: alpineso1
    spec:
      domain:
        devices:
          disks:
            - name: containerdisk
              disk:
                bus: virtio
          interfaces:
          - name: default
            masquerade: {}
        resources:
          requests:
            memory: 200M
      networks:
      - name: default
        pod: {}
      volumes:
        - name: containerdisk
          containerDisk:
            image: <docker_hub_user>/alpineimage
END
Enter fullscreen mode Exit fullscreen mode

2. Apply the definition

kubectl apply -f vm.yaml
Enter fullscreen mode Exit fullscreen mode

3. Check for the vm to be created

kubectl get vms
Enter fullscreen mode Exit fullscreen mode

You will see the VM in the stopped state
4. Install virtctl CLI

VERSION=$(kubectl get kubevirt.kubevirt.io/kubevirt -n kubevirt -o=jsonpath="{.status.observedKubeVirtVersion}")
ARCH=$(uname -s | tr A-Z a-z)-$(uname -m | sed 's/x86_64/amd64/') || windows-amd64.exe
echo ${ARCH}
curl -L -o virtctl https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/virtctl-${VERSION}-${ARCH}
sudo install -m 0755 virtctl /usr/local/bin
Enter fullscreen mode Exit fullscreen mode

5. Start the VM

virtctl start alpinevm
Enter fullscreen mode Exit fullscreen mode

6. Expose any service you have on the VM

virtctl expose vm alpinevm--port=<PORT_NUMBER>--name=<NEW_SERVICE_NAME> --type=ClusterIP
Enter fullscreen mode Exit fullscreen mode

7. Now you can access the service of your VM in any Kubernetes Pod, Deployment, etc.

Conclusion about KubeVirt

KubeVirt is a technology that can be used when your applications are difficult to convert to containers or there is an specific situation where containers are not suitable to be used. Also for security reasons some systems prefer the use of VMs instead of containers and already have a Kubernetes environment that should interact with this VMs.

KubeVirt its an option option for VMs. In the university, we are testing KubeVirt to run some experiments with cloud native technologies. It was nice to create a VM using Qemu again and see that virtual machines needs to be used also in containerized environments. So it was a nice experience playing with KubeVirt a little bit.

See you on my next post with something interesting again.

Follow me

These are my social networks:

https://www.linkedin.com/in/sergioarmgpl
https://sergiops.xyz
https://x.com/sergioarmgpl
https://www.instagram.com/sergioarmgpl/

Please contribute to this awesome project:

Top comments (0)