Skip to content
Home
Products
Solutions
Customers Enterprise Community Docs
Support
Live Demo

Deploying KubeVirt

About KubeVirt

KubeVirt is an open-source project that runs and manages virtual machines in a Kubernetes cluster just like containers, bringing a modern container orchestration platform to traditional VM workloads. Virtual machines are represented by a Custom Resource Definition (CRD) in Kubernetes.

Project: https://github.com/kubevirt/kubevirt

KubeVirt architecture

Preparing the base environment

    1. Install the required packages
$ apt install -y libvirt-clients virt-manager bridge-utils
    1. Check whether the node supports virtualization

Physical hosts are recommended for production. In lab environments without hardware virtualization, enable software emulation instead.

$ virt-host-validate qemu
  QEMU: Checking for hardware virtualization                                 : PASS
  QEMU: Checking if device /dev/vhost-net exists                             : PASS
  QEMU: Checking if device /dev/net/tun exists                               : PASS
  QEMU: Checking for cgroup 'cpu' controller support                         : PASS
  QEMU: Checking for cgroup 'cpuacct' controller support                     : PASS
  QEMU: Checking for cgroup 'cpuset' controller support                      : PASS
  QEMU: Checking for cgroup 'memory' controller support                      : PASS
  QEMU: Checking for cgroup 'devices' controller support                     : PASS
  QEMU: Checking for cgroup 'blkio' controller support                       : PASS
  QEMU: Checking for device assignment IOMMU support                         : WARN (Unknown if this platform has IOMMU support)
  QEMU: Checking for secure guest support                                    : WARN (Unknown if this platform has Secure Guest support)

Installing KubeVirt

    1. Install KubeVirt
# Get the latest release
$ export RELEASE=$(curl https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt)
# Deploy the KubeVirt operator
$ wget https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-operator.yaml
$ kubectl apply -f kubevirt-operator.yaml

# Create the KubeVirt CR (instance deployment request) which triggers the actual installation
$ wget https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-cr.yaml
# If hardware virtualization is unavailable, enable software emulation by adding useEmulation: true
$ vim kubevirt-cr.yaml
---
apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
  name: kubevirt
  namespace: kubevirt
spec:
  certificateRotateStrategy: {}
  configuration:
    developerConfiguration:
      useEmulation: true
      featureGates: []
  customizeComponents: {}
  imagePullPolicy: IfNotPresent
  workloadUpdateStrategy: {}
$ kubectl apply -f kubevirt-cr.yaml
# wait until all KubeVirt components are up
$ kubectl -n kubevirt wait kv kubevirt --for condition=Available
    1. Check the Pod status
root@kube-node1:~# kubectl get pods -n kubevirt
NAME                               READY   STATUS    RESTARTS   AGE
virt-api-fdbc87c9-rw4m8            1/1     Running   0          9m34s
virt-api-fdbc87c9-tsfvx            1/1     Running   0          9m34s
virt-controller-844699784f-72psc   1/1     Running   0          8m57s
virt-controller-844699784f-zpg44   1/1     Running   0          8m57s
virt-handler-clw89                 1/1     Running   0          8m57s
virt-handler-drbsn                 1/1     Running   0          8m57s
virt-operator-74bdf99686-nlxkk     1/1     Running   0          10m
virt-operator-74bdf99686-wxt5j     1/1     Running   0          10m
    1. Deploy virtctl

Virtual machines can subsequently be managed with either virtctl or kubectl.

$ cd /usr/local/src
$ wget https://github.com/kubevirt/kubevirt/releases/download/v1.3.1/virtctl-v1.3.1-linux-amd64
$ mv virtctl-v1.3.1-linux-amd64 /usr/local/bin/virtctl
$ chmod +x /usr/local/bin/virtctl
$ virtctl version
Client Version: version.Info{GitVersion:"v1.3.1", GitCommit:"ed1e7ae8548d319fa7aacf315ad198f7241287c5", GitTreeState:"clean", BuildDate:"2024-08-22T08:52:25Z", GoVersion:"go1.22.2 X:nocoverageredesign", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{GitVersion:"v1.3.1", GitCommit:"ed1e7ae8548d319fa7aacf315ad198f7241287c5", GitTreeState:"clean", BuildDate:"2024-08-22T10:09:02Z", GoVersion:"go1.22.2 X:nocoverageredesign", Compiler:"gc", Platform:"linux/amd64"}

Creating a virtual machine

# Example virtual machine manifest
$ vim vm.yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  labels:
    kubevirt.io/vm: vm-cirros
  name: vm-cirros
spec:
  running: false
  template:
    metadata:
      labels:
        kubevirt.io/vm: vm-cirros
    spec:
      domain:
        devices:
          disks:
          - disk:
              bus: virtio
            name: containerdisk
          - disk:
              bus: virtio
            name: cloudinitdisk
        machine:
          type: ""
        resources:
          requests:
            memory: 64M
      terminationGracePeriodSeconds: 0
      volumes:
      - name: containerdisk
        containerDisk:
          image: quay.io/kubevirt/cirros-container-disk-demo:latest
      - cloudInitNoCloud:
          userDataBase64: IyEvYmluL3NoCgplY2hvICdwcmludGVkIGZyb20gY2xvdWQtaW5pdCB1c2VyZGF0YScK
        name: cloudinitdisk

# Create the virtual machine
$ kubectl apply -f vm.yaml

# Check the virtual machine status
$ kubectl get vm,vmi,pod

# Start the virtual machine with kubectl
$ kubectl patch virtualmachine vm-cirros --type merge -p '{"spec":{"running":true}}'

Managing virtual machines

Connecting to a virtual machine

  • Connect with virtctl console
root@kube-node1:~# virtctl console vm-cirros
Successfully connected to vm-cirros console. The escape sequence is ^]

login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.
vm-cirros login: cirros
Password:
$ uptime
 03:58:23 up 11:56,  1 users,  load average: 0.00, 0.00, 0.00
  • Connect with virtctl ssh

The cirros image uses the username cirros and the default password gocubsgo.

root@kube-node1:~# virtctl ssh cirros@vm-cirros
cirros@vmi/vm-cirros.default's password:
$ ifconfig
eth0      Link encap:Ethernet  HWaddr BE:83:10:2A:15:F9
          inet addr:10.2.1.5  Bcast:10.2.1.255  Mask:255.255.255.0
          inet6 addr: fe80::bc83:10ff:fe2a:15f9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1402  Metric:1
          RX packets:121 errors:0 dropped:0 overruns:0 frame:0
          TX packets:77 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:16439 (16.0 KiB)  TX bytes:8842 (8.6 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
  • Connect over SSH

Like a Pod, every virtual machine gets an IP address from the Pod CIDR.

root@kube-node1:~# ssh cirros@10.2.1.5
cirros@10.2.1.5's password:
$ uptime
 04:04:42 up 12:02,  1 users,  load average: 0.00, 0.00, 0.00
  • Stop the virtual machine

Stopping a virtual machine deletes its VMI automatically, so the correct order for removing a VM is: stop it first, then delete it.

$ virtctl stop vm-cirros
VM vm-cirros was scheduled to stop

Virtual machine states

  • Stopped: the VM is stopped and is not expected to start.
  • Provisioning: cluster resources for the VM (such as volumes) are being configured and prepared.
  • Starting: the VM is being prepared to run.
  • Running: the VM is running.
  • Paused: the VM is paused.
  • Migrating: the VM is being migrated to another host.
  • Stopping: the VM is stopping.
  • Terminating: the VM is being deleted, including its related resources (VM instance, volumes, and so on).
  • Unknown: the VM state cannot be obtained, usually because of a communication error with the host running it.
Document