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:
- SSH into one of the Workload Cluster Nodes.
- Type
cat /sys/module/kvm_intel/parameters/nested. - If you see
Y, then nested virtualization is supported. If you see anything else thanY, 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.

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.

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
kubevirtnamespace are selected by restrictive NetworkPolicies; - ensure all containers created by KubeVirt in the
kubevirtnamespace 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!