Image Mode for MicroShift Contributors
August 6, 2025 ยท View on GitHub
Follow the instructions in Image Mode for MicroShift Users to create a bootable container image, store this image in a remote registry and use it for installing a new RHEL operating system.
This document demonstrates how to run a bootc image using podman.
NOTE:
Use thepodmanapproach only for development purposes to benefit from the fast turnaround times it allows. Do not use it for production use cases.
The procedures described below require the following setup:
- A
RHEL 9.6 hostwith an active Red Hat subscription for building MicroShiftbootcimages and running containers - A
remote registry(e.g.quay.io) for storing and accessingbootcimages
Run MicroShift Bootc Image
Log into the RHEL 9.6 host using the user credentials that have SUDO
permissions configured.
Configure CNI
The MicroShift CNI driver (OVN) requires the Open vSwitch service to function
properly. The service depends on the openvswitch kernel module to be available
in the bootc image.
Run the following commands on the host to check the openvswitch module presence
and the version of kernel-core package used in the bootc image. Note that the
kernel versions are different.
$ find /lib/modules/$(uname -r) -name "openvswitch*"
/lib/modules/6.9.9-200.fc40.x86_64/kernel/net/openvswitch
/lib/modules/6.9.9-200.fc40.x86_64/kernel/net/openvswitch/openvswitch.ko.xz
$ IMAGE_NAME=microshift-4.18-bootc
$ sudo podman inspect "${IMAGE_NAME}" | grep kernel-core
"created_by": "kernel-core-5.14.0-427.26.1.el9_4.x86_64"
When a bootc image is started as a container, it uses the host kernel, which is
not necessarily the same one used for building the image. This means that the
openvswitch module cannot be loaded in the container due to the kernel version
mismatch with the modules present in the /lib/modules directory.
One way to work around this problem is to pre-load the openvswitch module before
starting the container as described in the Run Container section.
Configure CSI
If the host is already configured to have a rhel volume group with free space,
this configuration is inherited by the container so that it can be used by the
MicroShift CSI driver to allocate storage.
Run the following command to determine if the volume group exists and it has the necessary free space.
$ sudo vgs
VG #PV #LV #SN Attr VSize VFree
rhel 1 1 0 wz--n- <91.02g <2.02g
Otherwise, a new volume group should be set up for MicroShift CSI driver to allocate
storage in bootc MicroShift containers.
Run the following commands to create a file to be used for LVM partitioning and configure it as a loop device.
VGFILE=/var/lib/microshift-lvm-storage.img
VGSIZE=1G
sudo truncate --size="${VGSIZE}" "${VGFILE}"
sudo losetup -f "${VGFILE}"
Query the loop device name and create a free volume group on the device according to the MicroShift CSI driver requirements described in Storage Configuration.
VGLOOP=$(losetup -j ${VGFILE} | cut -d: -f1)
sudo vgcreate -f -y rhel "${VGLOOP}"
The device will now be shared with the newly created containers as described in the next section.
The following commands can be run to detach the loop device and delete the LVM volume group file.
sudo losetup -d "${VGLOOP}" sudo rm -f "${VGFILE}"
Run Container
Run the following commands to start the MicroShift bootc image in an interactive
terminal session.
The host shares the following configuration with the container:
- The
openvswitchkernel module to be used by the Open vSwitch service - A pull secret file for downloading the required OpenShift container images
- Host container storage for reusing available container images
PULL_SECRET=~/.pull-secret.json
IMAGE_NAME=microshift-4.18-bootc
sudo modprobe openvswitch
sudo podman run --rm -it --privileged \
-v "${PULL_SECRET}":/etc/crio/openshift-pull-secret:ro \
-v /var/lib/containers/storage:/var/lib/containers/storage \
--name "${IMAGE_NAME}" \
"${IMAGE_NAME}"
The
systemd-modules-loadservice will fail to start in the container if the host kernel version is different from thebootcimage kernel version. This failure can be safely ignored as all the necessary kernel modules have already been loaded by the host.
If additional LVM volume group device was allocated as described in the Configure CSI section, the loop device should automatically be shared with the container and used by the MicroShift CSI driver.
After the MicroShift bootc image has been successfully started, a login prompt
will be presented in the terminal. Log into the running container using the
redhat:<password> credentials.
Run the following command to verify that all the MicroShift pods are up and running without errors.
watch sudo oc get pods -A \
--kubeconfig /var/lib/microshift/resources/kubeadmin/kubeconfig
Run the
sudo shutdown nowcommand to stop the container.
Appendix A: Multi-Architecture Image Build
It is often convenient to build multi-architecture container images and store them under the same registry URL using manifest lists.
See podman-manifest for more information.
The Build Image procedure needs to be adjusted in the following manner to create multi-architecture images.
PULL_SECRET=~/.pull-secret.json
USER_PASSWD="<your_redhat_user_password>"
IMAGE_ARCH=amd64 # Use amd64 or arm64 depending on the current platform
IMAGE_PLATFORM="linux/${IMAGE_ARCH}"
IMAGE_NAME="microshift-4.18-bootc:linux-${IMAGE_ARCH}"
sudo podman build --authfile "${PULL_SECRET}" -t "${IMAGE_NAME}" \
--platform "${IMAGE_PLATFORM}" \
--build-arg USER_PASSWD="${USER_PASSWD}" \
-f Containerfile
Verify that the local MicroShift 4.18 bootc image was created for the specified
platform.
$ sudo podman images "${IMAGE_NAME}"
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/microshift-4.18-bootc linux-amd64 3f7e136fccb5 13 minutes ago 2.19 GB
Repeat the procedure on the other platform (i.e. arm64) and proceed by publishing
the platform-specific amd64 and arm64 images to the remote registry as described
in the Publish Image section.
Cross-platform
podmanbuilds are not in the scope of this document. Log into the RHEL 9.6 host running on the appropriate architecture to perform the container image builds and publish the platform-specific image to the remote registry.
Finally, create a manifest containing the platform-specific image references and publish it to the remote registry.
Images for both
amd64andarm64architectures should have been pushed to the remote registry before creating the manifest.
REGISTRY_URL=quay.io
REGISTRY_ORG=myorg/mypath
BASE_NAME=microshift-4.18-bootc
MANIFEST_NAME="${BASE_NAME}:latest"
sudo podman manifest create -a "localhost/${MANIFEST_NAME}" \
"${REGISTRY_URL}/${REGISTRY_ORG}/${BASE_NAME}:linux-amd64" \
"${REGISTRY_URL}/${REGISTRY_ORG}/${BASE_NAME}:linux-arm64"
sudo podman manifest push \
"localhost/${MANIFEST_NAME}" \
"${REGISTRY_URL}/${REGISTRY_ORG}/${MANIFEST_NAME}"
Replace
myorg/mypathwith your remote registry organization name and path.
Inspect the remote manifest to make sure it contains image digests from multiple architectures.
$ sudo podman manifest inspect \
"${REGISTRY_URL}/${REGISTRY_ORG}/${MANIFEST_NAME}" | \
jq .manifests[].platform.architecture
"amd64"
"arm64"
It is now possible to access images using the manifest name with the latest tag
(e.g. quay.io/myorg/mypath/microshift-4.18-bootc:latest). The image for the
current platform will automatically be pulled from the registry if it is part of
the manifest list.
Appendix B: The rpm-ostree to Image Mode Upgrade Procedure
Refer to RHEL documentation for generic instructions on upgrading rpm-ostree
systems to Image Mode. The upgrade process should be planned carefully considering
the following guidelines:
- Follow instructions in RHEL documentation for converting
rpm-ostreeblueprints to Image Mode container files - Consider using rpm-ostree compose container-encapsulate
to experiment with Image Mode based on the existing
ostreecommits - Invest in defining a proper container build pipeline for fully adopting Image Mode
If reinstalling MicroShift devices from scratch is not an option, read the remainder of this section that outlines the upgrade details specific to MicroShift.
Upgrading existing systems during the transition from rpm-ostree to Image Mode
may pose the challenge of UID / GID Drift
because the existing rpm-ostree and the new Image Mode images are not derived
from the same parent image.
One way of working around this issue is to add systemd units that run before the
affected system services and apply the necessary fixes.
Note: The workaround is only necessary for
rpm-ostreeto Image Mode upgrade and it can be removed once all the devices are running the upgraded image.
Add the following command to the MicroShift image build procedure to create a
systemd unit file solving a potential UID / GID drift for ovsdb-server.service.
# Install systemd configuration drop-ins to fix potential permission problems
# when upgrading from older rpm-ostree commits to Image Mode container layers
RUN mkdir -p /usr/lib/systemd/system/ovsdb-server.service.d && \
cat > /usr/lib/systemd/system/ovsdb-server.service.d/microshift-ovsdb-ownership.conf <<'EOF'
# The openvswitch database files must be owned by the appropriate user and its
# primary group. Note that the user and its group may be overwritten too, so
# they need to be recreated in this case.
[Service]
ExecStartPre=/bin/sh -c '/bin/getent passwd openvswitch >/dev/null || useradd -r openvswitch'
ExecStartPre=/bin/sh -c '/bin/getent group hugetlbfs >/dev/null || groupadd -r hugetlbfs'
ExecStartPre=/sbin/usermod -a -G hugetlbfs openvswitch
ExecStartPre=/bin/chown -Rhv openvswitch. /etc/openvswitch
EOF