Fedora 43

Kubernetes : Create Virtual Machine2025/11/21

 

Create a virtual machine with KubeVirt.

This example is based on the environment like follows.

-----------+---------------------------+--------------------------+------------
           |                           |                          |
       eth0|10.0.0.30              eth0|10.0.0.51             eth0|10.0.0.52
+----------+-----------+   +-----------+----------+   +-----------+----------+
|   [ dlp.srv.world ]  |   | [ node01.srv.world ] |   | [ node02.srv.world ] |
|     Control Plane    |   |      Worker Node     |   |      Worker Node     |
+----------------------+   +----------------------+   +----------------------+

[1]

A Persistent storage is needed to store OS images.
On this example, install NFS Server on Control Plane Node and configure [/home/nfsshare] directory as NFS share as external persistent storage, and also configure dynamic volume provisioning with NFS plugin like the example of [1], [2], [3].

[2] Install Containerized Data Importer to store OS images.
[root@dlp ~]#
export TAG=$(curl -s -w %{redirect_url} https://github.com/kubevirt/containerized-data-importer/releases/latest)

[root@dlp ~]#
export VERSION=$(echo ${TAG##*/})

[root@dlp ~]#
wget https://github.com/kubevirt/containerized-data-importer/releases/download/${VERSION}/cdi-operator.yaml

[root@dlp ~]#
wget https://github.com/kubevirt/containerized-data-importer/releases/download/${VERSION}/cdi-cr.yaml
[root@dlp ~]#
vi cdi-cr.yaml
apiVersion: cdi.kubevirt.io/v1beta1
kind: CDI
metadata:
  name: cdi
spec:
  config:
    # add resource section to expand memory limits
    podResourceRequirements:
      limits:
        cpu: '1'
        memory: 4Gi
    featureGates:
    - HonorWaitForFirstConsumer
  imagePullPolicy: IfNotPresent
  infra:
    nodeSelector:
      kubernetes.io/os: linux
    tolerations:
    - key: CriticalAddonsOnly
      operator: Exists
  workload:
    nodeSelector:
      kubernetes.io/os: linux

[root@dlp ~]#
kubectl apply -f cdi-operator.yaml

namespace/cdi created
customresourcedefinition.apiextensions.k8s.io/cdis.cdi.kubevirt.io created
clusterrole.rbac.authorization.k8s.io/cdi-operator-cluster created
clusterrolebinding.rbac.authorization.k8s.io/cdi-operator created
serviceaccount/cdi-operator created
role.rbac.authorization.k8s.io/cdi-operator created
rolebinding.rbac.authorization.k8s.io/cdi-operator created
deployment.apps/cdi-operator created

[root@dlp ~]#
kubectl apply -f cdi-cr.yaml

cdi.cdi.kubevirt.io/cdi created
# after a few minutes, the pods will start up as follows

[root@dlp ~]#
kubectl get pods -n cdi

NAME                               READY   STATUS    RESTARTS      AGE
cdi-apiserver-6d6fd6cb84-ctwvn     1/1     Running   1 (70s ago)   79s
cdi-deployment-58548f6d58-ztq56    1/1     Running   0             79s
cdi-operator-5659646c9-8rbks       1/1     Running   0             86s
cdi-uploadproxy-6f47fb85b9-vtxpx   1/1     Running   0             79s
[3] Create a virtual machine. On this example, create it with Fedora 42.
[root@dlp ~]#
kubectl get sc

NAME         PROVISIONER                                                RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client   cluster.local/nfs-client-nfs-subdir-external-provisioner   Delete          Immediate           true                   26m

# create PVC definition

[root@dlp ~]#
vi fedora-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: "fedora-pvc"
  labels:
    app: containerized-data-importer
  annotations:
    cdi.kubevirt.io/storage.import.endpoint: "https://download.fedoraproject.org/pub/fedora/linux/releases/43/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-43-1.6.x86_64.qcow2"
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 15Gi
  storageClassName: nfs-client

[root@dlp ~]#
kubectl apply -f fedora-pvc.yml

persistentvolumeclaim/fedora-pvc created
[root@dlp ~]#
kubectl get pvc

NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
fedora-pvc   Bound    pvc-abb82cde-96f7-4ccc-a5d8-36a8b860f112   15Gi       RWO            nfs-client     <unset>                 5s

[root@dlp ~]#
kubectl get pods

NAME                  READY   STATUS    RESTARTS   AGE
importer-fedora-pvc   1/1     Running   0          19s

# possible to see importing logs

[root@dlp ~]#
kubectl logs -f importer-fedora-pvc

.....
.....
I1121 02:41:26.267855       1 data-processor.go:354] Expanding image size to: 15193866240
E1121 02:41:26.275408       1 prlimit.go:156] failed to kill the process; os: process already finished
I1121 02:41:26.275424       1 data-processor.go:266] Validating image
E1121 02:41:26.279204       1 prlimit.go:156] failed to kill the process; os: process already finished
I1121 02:41:26.283014       1 data-processor.go:260] New phase: Complete
I1121 02:41:26.283203       1 importer.go:231] {"scratchSpaceRequired":false,"preallocationApplied":false,"message":"Import Complete"}

# after finishing importing, importer pod will also finish

[root@dlp ~]#
kubectl get pods

No resources found in default namespace.
# create VM definition

[root@dlp ~]#
vi fedora-vm.yml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: fedora43
  labels:
    kubevirt.io/os: linux
spec:
  runStrategy: Halted
  template:
    spec:
      domain:
        cpu:
          cores: 2
        devices:
          disks:
          - disk:
              bus: virtio
            name: disk0
          - cdrom:
              bus: sata
              readonly: true
            name: cloudinitdisk
        machine:
          type: q35
        resources:
          requests:
            memory: 4096M
      volumes:
      - name: disk0
        persistentVolumeClaim:
          claimName: fedora-pvc
      - cloudInitNoCloud:
          userData: |
            #cloud-config
            hostname: fedora43
            ssh_pwauth: true
            disable_root: false
            chpasswd:
              list: |
                root:myrootpassword
                fedora:userpassword
              expire: False
        name: cloudinitdisk

[root@dlp ~]#
kubectl apply -f fedora-vm.yml

virtualmachine.kubevirt.io/fedora43 created
[root@dlp ~]#
kubectl get vms

NAME       AGE   STATUS    READY
fedora43   9s    Stopped   False

[root@dlp ~]#
virtctl start fedora43

VM fedora43 was scheduled to start

[root@dlp ~]#
kubectl get vmi

NAME       AGE   PHASE     IP                NODENAME           READY
fedora43   6s    Running   192.168.241.140   node02.srv.world   True

[root@dlp ~]# virtctl console fedora43 
Successfully connected to fedora43 console. The escape sequence is ^]

fedora43 login: root
Password:
[root@fedora43 ~]#

# to go back to the Host's console, push Ctrl + ] key
# * same operation as virsh command

[root@dlp ~]# ssh fedora@192.168.241.140 
The authenticity of host '192.168.241.140 (192.168.241.140)' can't be established.
ED25519 key fingerprint is SHA256:RDtAyUHGF2iViwbOwrMI/0WqLNDwDVjVGb8GBLexHZw.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.241.140' (ED25519) to the list of known hosts.
fedora@192.168.241.140's password:
[fedora@fedora43 ~]$
Matched Content