CentOS Stream 10: Create Virtual Machine
Create and manage virtual machines using KubeVirt within a Kubernetes cluster on CentOS Stream 10.
Create a virtual machine with KubeVirt.
This example is based on the environment like follows.
+----------------------+ +----------------------+
| [ ctrl.srv.world ] | | [ dlp.srv.world ] |
| Manager Node | | Control Plane |
+-----------+----------+ +-----------+----------+
eth0|10.0.0.25 eth0|10.0.0.30
| |
------------+--------------------------+-----------
| |
eth0|10.0.0.51 eth0|10.0.0.52
+-----------+----------+ +-----------+----------+
| [ node01.srv.world ] | | [ node02.srv.world ] |
| Worker Node#1 | | Worker Node#2 |
+----------------------+ +----------------------+
Step 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].
Step 2
Install Containerized Data Importer to store OS images.
[cent@ctrl ~]$ export TAG=$(curl -s -w %{redirect_url} https://github.com/kubevirt/containerized-data-importer/releases/latest)
[cent@ctrl ~]$ export VERSION=$(echo ${TAG##*/})
[cent@ctrl ~]$ wget https://github.com/kubevirt/containerized-data-importer/releases/download/${VERSION}/cdi-operator.yaml
[cent@ctrl ~]$ wget https://github.com/kubevirt/containerized-data-importer/releases/download/${VERSION}/cdi-cr.yaml
[cent@ctrl ~]$ vi cdi-cr.yaml
apiVersion: cdi.kubevirt.io/v1beta1
kind: CDI
metadata:
name: cdi
spec:
config:
<span class="color2"># add resource section to expand memory limits</span>
<span class="color1">podResourceRequirements:
limits:
cpu: '1'
memory: 4Gi</span>
featureGates:
- HonorWaitForFirstConsumer
imagePullPolicy: IfNotPresent
infra:
nodeSelector:
kubernetes.io/os: linux
tolerations:
- key: CriticalAddonsOnly
operator: Exists
workload:
nodeSelector:
kubernetes.io/os: linux
[cent@ctrl ~]$ 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
[cent@ctrl ~]$ kubectl apply -f cdi-cr.yaml
cdi.cdi.kubevirt.io/cdi created
after a few minutes, the pods will start up as follows
[cent@ctrl ~]$ kubectl get pods -n cdi
NAME READY STATUS RESTARTS AGE
cdi-apiserver-6c76687b66-fx6jq 1/1 Running 1 (25s ago) 55s
cdi-deployment-5f6ff949d7-pjx8c 1/1 Running 0 55s
cdi-operator-ccb895984-hnnls 1/1 Running 0 76s
cdi-uploadproxy-b499c7956-wcfrg 1/1 Running 0 55s
Step 3
Create a virtual machine. On this example, create it with Ubuntu 24.04.
[cent@ctrl ~]$ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-client cluster.local/nfs-client-nfs-subdir-external-provisioner Delete Immediate true 97m
create PVC definition
[cent@ctrl ~]$ vi ubuntu-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: "ubuntu-pvc"
labels:
app: containerized-data-importer
annotations:
cdi.kubevirt.io/storage.import.endpoint: "http://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-amd64.img"
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 15Gi
storageClassName: nfs-client
[cent@ctrl ~]$ kubectl apply -f ubuntu-pvc.yml
persistentvolumeclaim/ubuntu-pvc created
[cent@ctrl ~]$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
ubuntu-pvc Bound pvc-91489452-5712-4a35-986a-7385e130a0dc 15Gi RWO nfs-client <unset> 5s
[cent@ctrl ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
importer-ubuntu-pvc 1/1 Running 0 3s
possible to see importing logs
[cent@ctrl ~]$ kubectl logs -f importer-ubuntu-pvc
.....
.....
I0520 05:27:44.437641 1 data-processor.go:341] Expanding image size to: 15220080640
E0520 05:27:44.445445 1 prlimit.go:156] failed to kill the process; os: process already finished
I0520 05:27:44.445500 1 data-processor.go:253] Validating image
E0520 05:27:44.449675 1 prlimit.go:156] failed to kill the process; os: process already finished
I0520 05:27:44.452912 1 data-processor.go:247] New phase: Complete
I0520 05:27:44.453080 1 importer.go:231] {"scratchSpaceRequired":false,"preallocationApplied":false,"message":"Import Complete"}
after finishing importing, importer pod will also finish
[cent@ctrl ~]$ kubectl get pods
No resources found in default namespace.
create VM definition
[cent@ctrl ~]$ vi ubuntu-vm.yml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: ubuntu2404
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
interfaces:
- name: default
masquerade: {}
machine:
type: q35
resources:
requests:
memory: 4096M
networks:
- name: default
pod: {}
volumes:
- name: disk0
persistentVolumeClaim:
claimName: ubuntu-pvc
- cloudInitNoCloud:
userData: |
#cloud-config
hostname: ubuntu2404
ssh_pwauth: true
disable_root: false
chpasswd:
list: |
root:myrootpassword
ubuntu:userpassword
expire: False
name: cloudinitdisk
[cent@ctrl ~]$ kubectl apply -f ubuntu-vm.yml
virtualmachine.kubevirt.io/ubuntu2404 created
[cent@ctrl ~]$ kubectl get vms
NAME AGE STATUS READY
ubuntu2404 10s Stopped False
<span class="color1">virtctl start ubuntu2404 </span>
VM ubuntu2404 was scheduled to start
[cent@ctrl ~]$ kubectl get vmi
NAME AGE PHASE IP NODENAME READY
ubuntu2404 18s Running 192.168.40.215 node01.srv.world True
<span class="color1">virtctl console ubuntu2404 </span>
Successfully connected to ubuntu2404 console. The escape sequence is ^]
ubuntu2404 login: <span class="color1">root</span>
Password:
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-60-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
.....
.....
root@ubuntu2404:~#
<span class="color2"># to go back to the Host's console, push Ctrl + ] key
# * same operation as virsh command</span>
<span class="color2"># connect to VM via ssh</span>
<span class="color1">kubectl get pods </span>
NAME READY STATUS RESTARTS AGE
virt-launcher-ubuntu2404-vssn2 2/2 Running 0 33s
<span class="color1">kubectl port-forward pod/virt-launcher-ubuntu2404-vssn2 2220:22 & </span>
<span class="color1">ssh ubuntu@127.0.0.1 -p 2220 </span>
Handling connection for 2220
The authenticity of host '[127.0.0.1]:222 ([127.0.0.1]:222)' can't be established.
ED25519 key fingerprint is SHA256:W/jCnIP+PoghhP3FOrVDa9HBGjOzip+QVBqGEep5roM.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? <span class="color1">yes</span>
Warning: Permanently added '[127.0.0.1]:222' (ED25519) to the list of known hosts.
ubuntu@127.0.0.1's password:
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-60-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
....
.....
ubuntu@ubuntu2404:~$