Openshift Virtualization: Creating Images, Bootable Volumes, and Templates

In the previous articles, an introduction was provided to the following concepts:

Images: Think of an image as as a snapshot of a filesystem, bootable media, and/or QCOW or raw image files.

Bootable Volume: This concept can include any images but it means that the result will automatically boot you into a running operating system once the VM is created.

Templates: A template is a predefined configuration for creating virtual machines. It includes settings like the operating system, hardware specifications (CPU, memory, disk size), network settings, and the image from which the VM will be created.

When the Fedora VM was created, a template was used but the option to use a specific instance type was provided in the GUI. U1 was selected in this case. There was some customization that could be done immediately before creating the VM but most of the settings were already set (IE: templated). Any additional settings or modifications to the template configuration would be over-rides which would be specific to this VM. More specifics on what is templated will be provided later in this article.

Since we used the Fedora operating system in the examples, this article will show an example on how this Fedora template was created. My hope is that this will help with the explanation of these topics (images/bootable volumes/templates).

In this walkthrough, a bootable volume based off of a Fedora image will be templated.

Re-Creating Fedora

Creating Bootable Image

For this exercise, I will first show how to create a bootable volume based off of Fedora to be used in a template.

  1. First let's download the latest Fedora ISO from the Fedora Project website.
  2. The ISO was downloaded.

As of this writing, Fedora Server 40 is the current version. It can be downloaded from:

https://download.fedoraproject.org/pub/fedora/linux/releases/40/Server/x86_64/iso/Fedora-Server-dvd-x86_64-40-1.14.iso

wget https://download.fedoraproject.org/pub/fedora/linux/releases/40/Server/x86_64/iso/Fedora-Server-dvd-x86_64-40-1.14.iso
  1. Now, let's install this on a VM. virt-manager is being used by exporting X Windows through SSH in my lab.
  2. Go to File --> New Virtual Machine.
  3. A boot iso that was just downloaded will be used (local install media).
  1. Browse to the location of the ISO and select it.
  1. The fact that this is a Fedora Linux 40 operating will be detected automatically.
  2. The default cpu/memory is 2VCPU/4GB of memory in this libvirt environment. This is sufficient for our exercise.

  1. The default disk of 20GB will be used (could probably go at least a little smaller). Remember this VM is just a base install right now. Operating system updates will be performed later but the updates will only be for the base packages that are automatically installed. We want to keep this small since it needs to be as portable as possible (to become an image). The resulting VM that is deployed can be resized at install time.
  1. I will use the default NAT networking for now and accept all other defaults. Let's just keep this simple for now. Click "Finish".

  1. The default installation screen will be provided. Just set the partitioning, root account, user account, etc to your liking.

    The user account created here will only be used for updating the operating system (or can be used as a backdoor by an administrator). It will be created on the bootable volume/template but cloud-init will create the username/password that will be used for the end-user. The end-user who will use this bootable-volume/template can decide if he/she wants to keep this account or remove it on the copy that he/she instantiates as a VM.

The operating system will install and we can proceed to next steps.

  1. When the operating is done installing, you can reboot.
  2. After logging into the VM, I ran an "yum update" command.

I immediately aborted but this will be an opportunity later for me to show you how updates work.

  1. The only package that we can install now is the qemu-guest-agent. This ensures better driver support/integration later. Run these two commands on the VM.
sudo yum install -y qemu-guest-agent
systemctl enable --now qemu-guest-agent
sudo yum install httpd
sudo systemctl enable httpd
sudo systemctl firewall-cmd --add-port=80/tcp --permanent
sudo firewall-cmd --reload
cp /var/lib/libvirt/images/fedora40.qcow2 /var/www/html
#Alternatively, you could do a symlink
#cd /var/www/html; ln -s /var/lib/libvirt/images/fedora40.qcow2
# Permissions may need to be changed too if doing symlink.  
# This is a just a lab environment so don't yell too load.
chmod 777 /var/lib/libvirt/images/fedora40.qcow2

Making this into a Template

Here are the steps to make this into a template that can be used later.

  1. In the Openshift Web Console, go to Virtualization --> Templates.
  2. Select "Create Template"
  1. After hitting the "Create Template" option, you be taken to a YAML page. Don't get too intimidated. I will walk you through it. Let's exit this for now and go over some other concepts.
  1. Some documentation that will be used for this next exercise comes from:
Creating VMs from custom images overview - Virtual machines | Virtualization | OpenShift Container Platform 4.16

Any of these options below are available at this point.

Let's create a container-image based on the image present at the webserver (which we did earlier).

I am using this document for these purposes:

https://docs.openshift.com/container-platform/4.16/virt/virtual_machines/creating_vms_custom/virt-creating-vms-from-container-disks.html#virt-preparing-container-disk-for-vms_virt-creating-vms-from-container-disks

  1. The command/syntax below will need to be adjusted. I uses the full URL to the qcow2 file in this docker file.

    ** You will need podman installed and a registry to push to. I used the internal OCP one **
$ cat > Dockerfile << EOF
FROM registry.access.redhat.com/ubi8/ubi:latest AS builder
ADD --chown=107:107 <vm_image>.qcow2 /disk/ 
RUN chmod 0440 /disk/*

FROM scratch
COPY --from=builder /disk/* /disk/
EOF
podman build -t <registry>/<container_disk_name>:latest .
  1. Push it
podman push <registry/image-name>
  1. Let's go back to the template that we started on earlier. Go to Virtualization --> Templates.

    The template that I will use for this purpose is located at:

    https://github.com/kcalliga/openshift-cnv/blob/main/template-example.yaml
  2. The only change that needs to be made is to change the path to the registry image.

Let's save it.

  1. To keep this article shorter, I am just going to accept all defaults but upon creation of the template, a screen will appear that allows other customizations.

This template is now visible in the Openshift Console at Virtualization – > Templates

Let's instantiate a new VM off of this template.

Instantiating VM from this Template

This template will show up under Virtualization --> Catalog --> Template Catalog Tab --> User Templates

  1. To keep this article short and not too overwhelming, I'm going to accept all the defaults. We have been through the exercise of customizing in the previous articles.
  1. After creating this VM, there was one issue. I had to set it to BIOS instead of UEFI to boot with this image. This is due to the way I built in my libvirt environment. Other than that, there were no issues.
  1. The console shows my VM booted.