Image mode is a new approach to operating system deployment that lets users build,
deploy, and manage Red Hat Enterprise Linux as a bootable container (bootc)
image. Such an image uses standard OCI/Docker containers as a transport and delivery
format for base operating system updates. A bootc image includes a Linux kernel,
which is used to boot.
MicroShift build and deployment procedures can utilize bootable containers to benefit from this technology.
This document demonstrates how to create a bootable container image, store this image in a remote registry and use it for installing a new RHEL operating system.
See Image mode for Red Hat Enterprise Linux for more information.
The procedures described below require the following setup:
- A
RHEL 9.6 hostwith an active Red Hat subscription for building MicroShiftbootcimages. For development purposes, you can use the Red Hat Developer subscription, which is free of charge. - A
hypervisor hostwith a virtualization technology that supports RHEL. In this documentation, libvirt virtualization is used as an example. - A
remote registry(e.g.quay.io) for storing and accessingbootcimages
Log into the RHEL 9.6 host using the user credentials that have SUDO
permissions configured.
Download the Containerfile using the following command and use it for subsequent image builds.
URL=https://raw.githubusercontent.com/openshift/microshift/refs/heads/main/docs/config/Containerfile.bootc-rhel9
curl -s -o Containerfile "${URL}"Important:
When building a container image, podman uses host subscription information and repositories inside the container. With onlyBaseOSandAppStreamsystem repositories enabled by default, we need to enable therhocpandfast-datapathrepositories for installing MicroShift and its dependencies. These repositories must be accessible in the host subscription, but not necessarily enabled on the host.
Examine the rhocp and fast-datapath repositories that are available in the host
subscription.
sudo subscription-manager repos --list | \
grep '^Repo ID:' | \
grep -E 'fast-datapath|rhocp-4.*-for-rhel' | sortRun the following image build command to create a local bootc image.
Note how secrets are used during the image build:
- The podman
--authfileargument is required to pull the base image from theregistry.redhat.ioregistry - The build
USER_PASSWDargument is used to set a password for theredhatuser
PULL_SECRET=~/.pull-secret.json
USER_PASSWD="<your_redhat_user_password>"
IMAGE_NAME=microshift-4.18-bootc
sudo podman build --authfile "${PULL_SECRET}" -t "${IMAGE_NAME}" \
--build-arg USER_PASSWD="${USER_PASSWD}" \
-f ContainerfileImportant:
Ifdnf upgradecommand is used in the container image build procedure, it may cause unintended operating system version upgrade (e.g. from9.6to9.6). To prevent this from happening, use the following command instead.RUN . /etc/os-release && dnf upgrade -y --releasever="${VERSION_ID}"
Verify that the local MicroShift 4.18 bootc image was created.
$ sudo podman images "${IMAGE_NAME}"
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/microshift-4.18-bootc latest 193425283c00 2 minutes ago 2.31 GBRun the following commands to log into a remote registry and push the image to a remote registry.
The image from the remote registry can be used for running the container on another host, or when installing a new operating system with the
bootcimage layer.
REGISTRY_URL=<myreg>
REGISTRY_IMG=<myorg>/<mypath>/"${IMAGE_NAME}"
sudo podman login "${REGISTRY_URL}"
sudo podman push localhost/"${IMAGE_NAME}" "${REGISTRY_URL}/${REGISTRY_IMG}"Replace
<myreg>with the URL to your remote registry, and<myorg>/<mypath>with your organization name and path inside your remote registry.
Log into the physical hypervisor host using the user credentials that have
SUDO permissions configured.
Set variables pointing to secret files that are included in kickstart.ks for
gaining access to private container registries:
AUTH_CONFIGfile contents are copied to/etc/ostree/auth.jsonat the pre-install stage to authenticate<myreg>/<myorg>registry accessPULL_SECRETfile contents are copied to/etc/crio/openshift-pull-secretat the post-install stage to authenticate OpenShift registry accessIMAGE_REFvariable contains the MicroShift bootc container image reference to be installed
AUTH_CONFIG=~/.registry-auth.json
PULL_SECRET=~/.pull-secret.json
IMAGE_REF="<myreg>/<myorg>/<mypath>/microshift-4.18-bootc"Replace
<myreg>with the URL to your remote registry, and<myorg>/<mypath>with your organization name and path inside your remote registry.
See the
containers-auth.json(5)manual pages for more information on the syntax of theAUTH_CONFIGregistry authentication file.
Run the following commands to create the kickstart.ks file to be used during
the virtual machine installation.
cat > kickstart.ks <<EOFKS
lang en_US.UTF-8
keyboard us
timezone UTC
text
reboot
# Partition the disk with hardware-specific boot and swap partitions, adding an
# LVM volume that contains a 10GB+ system root. The remainder of the volume will
# be used by the CSI driver for storing data.
zerombr
clearpart --all --initlabel
# Create boot and swap partitions as required by the current hardware platform
reqpart --add-boot
# Add an LVM volume group and allocate a system root logical volume
part pv.01 --grow
volgroup rhel pv.01
logvol / --vgname=rhel --fstype=xfs --size=10240 --name=root
# Lock root user account
rootpw --lock
# Configure network to use DHCP and activate on boot
network --bootproto=dhcp --device=link --activate --onboot=on
%pre-install --log=/dev/console --erroronfail
# Create a 'bootc' image registry authentication file
mkdir -p /etc/ostree
cat > /etc/ostree/auth.json <<'EOF'
$(cat "${AUTH_CONFIG}")
EOF
%end
# Pull a 'bootc' image from a remote registry
ostreecontainer --url "${IMAGE_REF}"
%post --log=/dev/console --erroronfail
# Create an OpenShift pull secret file
cat > /etc/crio/openshift-pull-secret <<'EOF'
$(cat "${PULL_SECRET}")
EOF
chmod 600 /etc/crio/openshift-pull-secret
%end
EOFKSThe kickstart file uses a special ostreecontainer
directive to pull a bootc image from the remote registry and use it to install
the RHEL operating system.
Download a RHEL boot ISO image from https://developers.redhat.com/products/rhel/download.
Copy the downloaded file to the /var/lib/libvirt/images directory.
Run the following commands to create a RHEL virtual machine with 2 cores, 2GB of
RAM and 20GB of storage. The command uses the kickstart file prepared in the
previous step to pull a bootc image from the remote registry and use it to install
the RHEL operating system.
VMNAME=microshift-4.18-bootc
NETNAME=default
sudo virt-install \
--name ${VMNAME} \
--vcpus 2 \
--memory 2048 \
--disk path=/var/lib/libvirt/images/${VMNAME}.qcow2,size=20 \
--network network=${NETNAME},model=virtio \
--events on_reboot=restart \
--location /var/lib/libvirt/images/rhel-9.6-$(uname -m)-boot.iso \
--initrd-inject kickstart.ks \
--extra-args "inst.ks=file://kickstart.ks" \
--waitLog into the virtual machine 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/kubeconfigThe bootc-image-builder, is a containerized tool to create disk images from bootc images. You can use the tool to generate various image artifacts and deploy them in different environments, such as the edge, server, and clouds.
Log into the RHEL 9.6 host using the user credentials that have SUDO
permissions configured.
Set variables pointing to secret files that are included in kickstart.ks for
gaining access to private container registries:
PULL_SECRETfile contents are copied to/etc/crio/openshift-pull-secretat the post-install stage to authenticate OpenShift registry access
PULL_SECRET=~/.pull-secret.jsonRun the following command to create the kickstart.ks file to be used during
the virtual machine installation. If you want to embed the kickstart file directly
to ISO using BIB refer to upstream docs.
cat > kickstart.ks <<EOFKS
lang en_US.UTF-8
keyboard us
timezone UTC
text
reboot
# Partition the disk with hardware-specific boot and swap partitions, adding an
# LVM volume that contains a 10GB+ system root. The remainder of the volume will
# be used by the CSI driver for storing data.
zerombr
clearpart --all --initlabel
# Create boot and swap partitions as required by the current hardware platform
reqpart --add-boot
# Add an LVM volume group and allocate a system root logical volume
part pv.01 --grow
volgroup rhel pv.01
logvol / --vgname=rhel --fstype=xfs --size=10240 --name=root
# Lock root user account
rootpw --lock
# Configure network to use DHCP and activate on boot
network --bootproto=dhcp --device=link --activate --onboot=on
%post --log=/dev/console --erroronfail
# Create an OpenShift pull secret file
cat > /etc/crio/openshift-pull-secret <<'EOF'
$(cat "${PULL_SECRET}")
EOF
chmod 600 /etc/crio/openshift-pull-secret
%end
EOFKSPULL_SECRET=~/.pull-secret.json
IMAGE_NAME=microshift-4.18-bootc
mkdir ./output
sudo podman run --authfile ${PULL_SECRET} --rm -it \
--privileged \
--security-opt label=type:unconfined_t \
-v /var/lib/containers/storage:/var/lib/containers/storage \
-v ./output:/output \
registry.redhat.io/rhel9/bootc-image-builder:latest \
--local \
--type iso \
localhost/${IMAGE_NAME}:latestNOTE:
Use--configargument to optionally specify additional BIB build-time customizations as described in Build config.
Run the following commands to copy the ./output/install.iso file to the
/var/lib/libvirt/images directory and create a virtual machine.
VMNAME=microshift-4.18-bootc
NETNAME=default
sudo cp -Z ./output/bootiso/install.iso /var/lib/libvirt/images/${VMNAME}.iso
sudo virt-install \
--name ${VMNAME} \
--vcpus 2 \
--memory 2048 \
--disk path=/var/lib/libvirt/images/${VMNAME}.qcow2,size=20 \
--network network=${NETNAME},model=virtio \
--events on_reboot=restart \
--location /var/lib/libvirt/images/${VMNAME}.iso \
--initrd-inject kickstart.ks \
--extra-args "inst.ks=file://kickstart.ks" \
--waitLog into the virtual machine 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/kubeconfigAdding MicroShift container image dependencies to bootc images may be necessary for isolated (no Internet access) setup or for improving MicroShift first startup performance. The container image references are specific to platform and to each MicroShift version.
Use this approach to create a fully self contained image that does not have any external dependencies on startup.
Download the Containerfile.embedded using the following command and use it for subsequent image builds.
URL=https://raw.githubusercontent.com/openshift/microshift/refs/heads/main/docs/config/Containerfile.bootc-embedded-rhel9
curl -s -o Containerfile.embedded "${URL}"Review comments in the
Containerfile.embeddedfile to understand how container dependencies are embedded during thebootcimage build.
Run the following image build command to create a local bootc image with embedded
container dependencies. It is using a base image built according to the instructions
in the Build Image section.
Note how secrets are used during the image build:
- The podman
--authfileargument is required to pull the base image from theregistry.redhat.ioregistry - The podman
--secretargument is required to pull image dependencies from the OpenShift container registries.
PULL_SECRET=~/.pull-secret.json
BASE_IMAGE_NAME=microshift-4.18-bootc
BASE_IMAGE_TAG=latest
IMAGE_NAME=microshift-4.18-bootc-embedded
sudo podman build --authfile "${PULL_SECRET}" -t "${IMAGE_NAME}" \
--secret "id=pullsecret,src=${PULL_SECRET}" \
--build-arg USHIFT_BASE_IMAGE_NAME="${BASE_IMAGE_NAME}" \
--build-arg USHIFT_BASE_IMAGE_TAG="${BASE_IMAGE_TAG}" \
-f Containerfile.embeddedVerify that the local MicroShift 4.18 bootc image was created.
$ sudo podman images "${IMAGE_NAME}"
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/microshift-4.18-bootc-embedded latest 6490d8f5752a About a minute ago 3.75 GBFollow the instructions in Create ISO Image Using BIB to build an ISO from the container image with embedded container dependencies.
Note: Make sure to set the
IMAGE_NAMEvariable tomicroshift-4.18-bootc-embedded
Set variables pointing to secret files that are included in kickstart.ks for
gaining access to private container registries:
PULL_SECRETfile contents are copied to/etc/crio/openshift-pull-secretat the post-install stage to authenticate OpenShift registry access
PULL_SECRET=~/.pull-secret.json
IMAGE_NAME=microshift-4.18-bootc-embeddedRun the following command to create the kickstart.ks file to be used during
the virtual machine installation.
cat > kickstart.ks <<EOFKS
lang en_US.UTF-8
keyboard us
timezone UTC
text
reboot
# Partition the disk with hardware-specific boot and swap partitions, adding an
# LVM volume that contains a 10GB+ system root. The remainder of the volume will
# be used by the CSI driver for storing data.
zerombr
clearpart --all --initlabel
# Create boot and swap partitions as required by the current hardware platform
reqpart --add-boot
# Add an LVM volume group and allocate a system root logical volume
part pv.01 --grow
volgroup rhel pv.01
logvol / --vgname=rhel --fstype=xfs --size=10240 --name=root
# Lock root user account
rootpw --lock
# Configure network to use DHCP and activate on boot
network --bootproto=dhcp --device=link --activate --onboot=on
# Configure bootc to install from the local embedded container repository.
# See /osbuild-base.ks on ISO images generated by bootc-image-builder.
ostreecontainer --transport oci --url /run/install/repo/container
%post --log=/dev/console --erroronfail
# Update the image reference for updates to work correctly.
# See /osbuild.ks on ISO images generated by bootc-image-builder.
bootc switch --mutate-in-place --transport registry localhost/${IMAGE_NAME}
# Create an OpenShift pull secret file
cat > /etc/crio/openshift-pull-secret <<'EOF'
$(cat "${PULL_SECRET}")
EOF
chmod 600 /etc/crio/openshift-pull-secret
%end
EOFKSBefore creating a virtual machine, it is necessary to configure a libvirt
network without Internet access. Run the following commands to create such
a network.
VM_ISOLATED_NETWORK=microshift-isolated-network
cat > isolated-network.xml <<EOF
<network>
<name>${VM_ISOLATED_NETWORK}</name>
<forward mode='none'/>
<ip address='192.168.111.1' netmask='255.255.255.0' localPtr='yes'>
<dhcp>
<range start='192.168.111.100' end='192.168.111.254'/>
</dhcp>
</ip>
</network>
EOF
sudo virsh net-define isolated-network.xml
sudo virsh net-start "${VM_ISOLATED_NETWORK}"
sudo virsh net-autostart "${VM_ISOLATED_NETWORK}"Follow the instructions in Create Virtual Machine to bootstrap a virtual machine from the ISO with embedded container dependencies.
Note: Make sure to set the
NETNAMEvariable to theVM_ISOLATED_NETWORKisolated network name.
Log into the virtual machine console using the redhat:<password> credentials.
Run the following command to verify that there is no Internet access, thus no container image dependencies could have been pulled over the network.
$ curl -I redhat.com
curl: (6) Could not resolve host: redhat.comRun 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