Lab 14 - Virtual Machines¶
45 min Intermediate OpenShift Virtualization
Problem¶
A legacy "hello" web service can't be containerized yet: it has to run on a full Fedora operating system. Run it as a virtual machine on OpenShift, next to your containers, and make it reachable the same way you would a containerized app.
See OpenShift Virtualization for the concepts.
Prerequisites¶
- An OpenShift cluster with the OpenShift Virtualization operator installed, and worker nodes that support virtualization (bare metal, or cloud instances with virtualization enabled). See Lab Environments.
- The
virtctlCLI. In the web console, open the ? menu > Command Line Tools and download virtctl, or on macOS runbrew install virtctl.
Part 1: Create a VM¶
-
Save this VirtualMachine as
fedora-vm.yaml. It sizes the VM with theu1.smallinstance type (1 vCPU, 2 GiB), applies thefedorapreference, boots from a FedoracontainerDisk, and uses cloud-init to create a user and start a small web server on port 8080:fedora-vm.yamlapiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: fedora-vm spec: runStrategy: Always instancetype: kind: VirtualMachineClusterInstancetype name: u1.small preference: kind: VirtualMachineClusterPreference name: fedora template: metadata: labels: app: fedora-vm # Services select the VM by this label spec: domain: devices: {} volumes: - name: rootdisk containerDisk: image: quay.io/containerdisks/fedora:43 - name: cloudinitdisk cloudInitNoCloud: userData: | #cloud-config user: fedora password: bootcamp chpasswd: { expire: false } write_files: - path: /srv/www/index.html content: | Hello from a virtual machine running on Kubernetes! - path: /etc/systemd/system/hello-web.service content: | [Unit] Description=Hello web server After=network-online.target [Service] ExecStart=/usr/bin/python3 -m http.server 8080 --directory /srv/www Restart=always [Install] WantedBy=multi-user.target runcmd: - systemctl daemon-reload - systemctl enable --now hello-web.serviceARM clusters
On a cluster with ARM (aarch64) worker nodes, use the
fedora.arm64preference. -
Create the VM and watch it start. Which three objects represent it, and how are they related?
Once the pod is
Running,oc get vmishows the VM's IP address and node. Also open Virtualization > VirtualMachines in the web console.
Part 2: Log in¶
-
Open the VM's serial console and log in as
fedora/bootcamp. It can take a minute or two after the pod starts before the login prompt appears. Check that the web server is running, then exit with Ctrl+].
Part 3: Lifecycle¶
-
Inside the VM, create a file:
echo "I was here" > ~/note.txt. Then restart the VM withvirtctl, log in again, and look for the file. What happened, and why?Solution
virtctl restart fedora-vm oc get vmi -w # the VMI is deleted and recreated virtctl console fedora-vm ls ~/note.txt # No such file or directoryThe root disk is a containerDisk: an image pulled from a registry, like a container's filesystem. It's reset every time the VM starts. Real workloads use a persistent disk (a DataVolume backed by a PVC). See Part 5.
-
Stop the VM and look at what's left. Then start it again.
Part 4: Networking¶
-
Create a Service named
fedora-vmthat exposes the VM's web server (port8080) on port80, then call it from a container in the same project.Solution
fedora-vm-service.yamlapiVersion: v1 kind: Service metadata: name: fedora-vm spec: selector: app: fedora-vm ports: - port: 80 targetPort: 8080oc apply -f fedora-vm-service.yaml oc run client --image=registry.access.redhat.com/ubi9/ubi-minimal -- sleep infinity oc wait --for=condition=Ready pod/client oc exec client -- curl -s fedora-vmvirtctl expose vm fedora-vm --name fedora-vm --port 80 --target-port 8080creates the same Service. -
Publish it outside the cluster with a Route, and open it in your browser.
Solution
Containers and VMs use the same Services, Routes, DNS names and NetworkPolicies. A containerized frontend can call a VM backend by name, which is how teams modernize one piece at a time.
Part 5 (optional): A VM with a persistent disk¶
-
Create a RHEL 9 VM whose disk is cloned from OpenShift's golden image, so changes survive restarts. Log in with SSH, restart the VM, and confirm a file you create is still there.
virtctl create vm --name rhel9-vm \ --instancetype u1.small --preference rhel.9 \ --volume-import type:ds,src:openshift-virtualization-os-images/rhel9,size:30Gi \ --user cloud-user --ssh-key "$(cat ~/.ssh/id_ed25519.pub)" | oc apply -f - oc get datavolume -w # the disk is cloned into a PVC virtctl ssh cloud-user@vm/rhel9-vmReplace
~/.ssh/id_ed25519.pubwith your public key. If you don't have one, create it withssh-keygen -t ed25519.