Skip to content

Installing KubeVirt v1.7.2 on Welkin

Date: 2026-03-27

Important

This tutorial applies only to Welkin Enterprise.

This tutorial shows how to install KubeVirt v1.7.2 on Welkin. The tutorial assumes that the goal is to allow application developers to run legacy applications shipped as Virtual Machines, while benefiting from the networking, security and observability provided by Welkin. The tutorial assumes the use of the Quick Start version of Welkin used in official training. The purpose of the tutorial, like for all tutorials is not a fully hardened production-ready setup, but to act as inspiration for solutions built by e.g. system integrators or platform administrators.

Check Pre-requisites

KubeVirt needs hardware-assisted virtualization. This means that Welkin needs to be installed either bare-metal or on VMs providing nested virtualization.

If you run Welkin on VMs, you can check support for nested virtualization as follows:

  1. SSH into one of the Workload Cluster Nodes.
  2. Type cat /sys/module/kvm_intel/parameters/nested.
  3. If you see Y, then nested virtualization is supported. If you see anything else than Y, then nested virtualization is not supported and KubeVirt cannot run. Contact your infrastructure provider for details.

Connect to Workload Cluster

export KUBECONFIG=$CK8S_CONFIG_PATH/.state/kube_config_wc.yaml

Check that you are connected as platform administrator:

kubectl auth can-i create CustomResourceDefinitions --all-namespaces

You should see the following output:

yes

Set some Safeguards to warn

Important

Welkin Safeguards are added with every release. These are the safeguards which needed to be set to warn with Welkin Apps v0.52.

For this tutorial, you must set:

Install KubeVirt

Download KubeVirt artifacts:

export VERSION=v1.7.2
wget "https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml"
wget "https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-cr.yaml"

Edit kubevirt-cr.yaml as follows:

---
apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
  name: kubevirt
  namespace: kubevirt
spec:
  certificateRotateStrategy: {}
  configuration:
    developerConfiguration:
      featureGates: []
    imagePullPolicy: IfNotPresent
  customizeComponents: {}
  imagePullPolicy: IfNotPresent
  workloadUpdateStrategy: {}
  # Add the lines below. They instruct KubeVirt to install
  # a ServiceMonitor compatible with Welkin.
  monitorNamespace: monitoring
  monitorAccount: kube-prometheus-stack-prometheus
  serviceMonitorNamespace: kubevirt

Now use both files to install KubeVirt:

kubectl create -f kubevirt-operator.yaml
kubectl create -f kubevirt-cr.yaml

Verify KubeVirt as Platform Administrator

kubectl get all -n kubevirt

After a minute or two, you should see:

Warning: kubevirt.io/v1 VirtualMachineInstancePresets is now deprecated and will be removed in v2.
NAME                                   READY   STATUS    RESTARTS   AGE
pod/virt-api-5c9d674db5-cvp7w          1/1     Running   0          88s
pod/virt-controller-7d8b9965fb-9cfcl   1/1     Running   0          60s
pod/virt-controller-7d8b9965fb-zpsk6   1/1     Running   0          60s
pod/virt-handler-wtg2s                 1/1     Running   0          60s
pod/virt-operator-7d465947c6-k6mm6     1/1     Running   0          2m10s
pod/virt-operator-7d465947c6-qsmwf     1/1     Running   0          2m10s

NAME                                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/kubevirt-operator-webhook     ClusterIP   10.99.110.58     <none>        443/TCP   92s
service/kubevirt-prometheus-metrics   ClusterIP   None             <none>        443/TCP   92s
service/virt-api                      ClusterIP   10.110.80.136    <none>        443/TCP   92s
service/virt-exportproxy              ClusterIP   10.100.124.100   <none>        443/TCP   92s

NAME                          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/virt-handler   1         1         1       1            1           kubernetes.io/os=linux   60s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/virt-api          1/1     1            1           88s
deployment.apps/virt-controller   2/2     2            2           60s
deployment.apps/virt-operator     2/2     2            2           2m10s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/virt-api-5c9d674db5          1         1         1       88s
replicaset.apps/virt-controller-7d8b9965fb   2         2         2       60s
replicaset.apps/virt-operator-7d465947c6     2         2         2       2m10s

NAME                            AGE    PHASE
kubevirt.kubevirt.io/kubevirt   2m7s   Deployed

In the last line, Deployed indicates successful KubeVirt Deployment.

Verify KubeVirt as Application Developer

Let us now test if application developers have access to KubeVirt features.

Connect to the Workload Cluster as an application developer. This tutorial assumes you already have a file dev.kubeconfig which gives said access. If in doubt, check the Welkin Administrator training.

export KUBECONFIG=dev.kubeconfig

Verify that you are an application developer:

kubectl auth can-i create CustomResourceDefinitions --all-namespaces

You should see:

no

Important

KubeVirt itself runs in the kubevirt namespace which should not be used by application developers. Instead, the application developers should create VMs in their own namespaces.

Create a file called testvm.yaml with the following content:

apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  labels:
    kubevirt.io/vm: testvm
  name: testvm
spec:
  runStrategy: Always
  template:
    metadata:
      labels:
        kubevirt.io/vm: testvm
    spec:
      domain:
        devices:
          disks:
            - disk:
                bus: virtio
              name: containerdisk
            - disk:
                bus: virtio
              name: cloudinitdisk
        machine:
          type: ""
        resources:
          requests:
            memory: 64M
            cpu: 10m
      terminationGracePeriodSeconds: 0
      volumes:
        - name: containerdisk
          containerDisk:
            image: kubevirt/cirros-container-disk-demo:v0.36.4
        - cloudInitNoCloud:
            # Decoded userData:
            # #!/bin/sh
            # echo 'printed from cloud-init userdata'
            userDataBase64: IyEvYmluL3NoCgplY2hvICdwcmludGVkIGZyb20gY2xvdWQtaW5pdCB1c2VyZGF0YScK
          name: cloudinitdisk

Important

KubeVirt VM images, such as kubevirt/cirros-container-disk-demo:v0.36.4 above, do not obey Welkin's trusted container registry guardrail guardrail. This is due to the fact that Welkin only enforces said guardrail on container images understood by Kubernetes.

And apply it:

kubectl apply -f testvm.yaml

Verify that the VM is running:

kubectl get VirtualMachine

After a minute or so, you should see:

NAME     AGE   STATUS    READY
testvm   44s   Running   True

Verify Accessing the VirtualMachine as Application Developers

Application Developers will most likely want to use the virtctl tool for interacting with VMs.

To test that this works, start by installing virtctl:

export VERSION=v1.7.2
wget https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/virtctl-${VERSION}-linux-amd64
sudo mv virtctl-v1.7.2-linux-amd64 /usr/local/bin/virtctl
sudo chmod +x /usr/local/bin/virtctl

Just to make sure, verify that you are an application developer:

kubectl auth can-i create CustomResourceDefinitions --all-namespaces

You should see:

no

Now access the VM:

virtctl console testvm

You should see:

Successfully connected to testvm console. Press Ctrl+] or Ctrl+5 to exit console.

login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.
testvm login:

Networking Considerations

VMs run as Pods in application developer namespaces. Network-wise, they are indistringuishable from Pods. Among others, this means that:

  • VMs can connect to other Pods, either via in-Cluster DNS or the Pod's IP;
  • VMs can be selected by Services.

Check out the Welkin network model for details.

Observability Considerations

Logs

Welkin collects the logs of all Pods. This means that logs produced by KubeVirt will be available in OpenSearch, as shown in the screenshot below.

KubeVirt logs collected by Welkin

Note that, there is no standardized way to collect logs from VMs. When it comes to the Pods representing the VMs, Welkin will collect the logs of virt-laucher a component of KubeVirt and not the VM itself.

Exposing logs from the application running inside the VM to Welkin is highly dependent on the application, therefore outside the scope of this tutorial. Application developers may want to consider running Fluentd as a sidecar.

Metrics

Welkin collects KubeVirt metrics, as shown in the screenshot below.

KubeVirt metrics collected by Welkin

Exposing metrics of the application running inside the VM is outside the scope of this tutorial. Application developers may want to consider exposing a /metrics endpoint and instructing Welkin to collect metrics by configuring a ServiceMonitor. For details, see metrics.

Security Hardening

To ensure the KubeVirt installation is secure, Welkin recommends that Platform Administrators:

  • install KubeVirt on separate Nodes, via tolerations and taints;
  • ensure all containers created by KubeVirt in the kubevirt namespace are selected by restrictive NetworkPolicies;
  • ensure all containers created by KubeVirt in the kubevirt namespace have resource requests and limits;
  • ensure all container images are hosted by a container registry you trust, such as the one provided by Welkin.

Application Developers should:

  • ensure VMs do not have default passwords;
  • ensure VMs are selected by restrictive NetworkPolicies.

Some of these suggested hardening steps, such as the Network Policy requirement and requiring resource requests and limits, can be implemented directly using configuration of Welkin's built-in policy as code guardrails. Other steps, and your organization's own policies that need to be enforced, require more custom solutions. The Welkin Platform Administrator training program includes the required information to help you successfully configure Welkin. If you ever get stuck, or need custom solutions built for Welkin, reach out to Elastisys for assistance!

Further Reading