Skip to content

Commit

Permalink
Create MicroShift iso using image mode and bootc image builder
Browse files Browse the repository at this point in the history
With 4.18 microshift removed the steps of creating the iso using
image builder and there is no more `build.sh` script which is consumed
by mircoshift.sh script to create it. This PR use the image mode
and bootc image builder (BIB) to create the iso which is now microshift
team also pushing forward.
  • Loading branch information
praveenkumar committed Jan 13, 2025
1 parent 359c50d commit 83bd510
Show file tree
Hide file tree
Showing 4 changed files with 265 additions and 89 deletions.
135 changes: 135 additions & 0 deletions image-mode/microshift/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/bin/bash
set -eo pipefail

ROOTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../../" && pwd )"
SCRIPTDIR=${ROOTDIR}/image-mode/microshift
IMGNAME=microshift
USHIFT_VERSION=4.17
BUILD_ARCH=$(uname -m)
OSVERSION=$(awk -F: '{print $5}' /etc/system-release-cpe)
LVM_SYSROOT_SIZE_MIN=10240
LVM_SYSROOT_SIZE=${LVM_SYSROOT_SIZE_MIN}
OCP_PULL_SECRET_FILE=
AUTHORIZED_KEYS_FILE=
AUTHORIZED_KEYS=
USE_MIRROR_REPO=

# shellcheck disable=SC2034
STARTTIME="$(date +%s)"
BUILDDIR=${BUILDDIR:-${ROOTDIR}/_output/image-mode}

usage() {
local error_message="$1"

if [ -n "${error_message}" ]; then
echo "ERROR: ${error_message}"
echo
fi

echo "Usage: $(basename "$0") <-pull_secret_file path_to_file> [OPTION]..."
echo ""
echo " -pull_secret_file path_to_file"
echo " Path to a file containing the OpenShift pull secret, which can be"
echo " obtained from https://console.redhat.com/openshift/downloads#tool-pull-secret"
echo ""
echo "Optional arguments:"
echo " -lvm_sysroot_size num_in_MB"
echo " Size of the system root LVM partition. The remaining"
echo " disk space will be allocated for data (default: ${LVM_SYSROOT_SIZE})"
echo " -authorized_keys_file path_to_file"
echo " Path to an SSH authorized_keys file to allow SSH access"
echo " into the default 'redhat' account"
echo " -use-mirror-repo <mirror_repo>"
echo " Use mirror repo to get release candidate and engineering preview rpms"
echo " like (https://mirror.openshift.com/pub/openshift-v4/x86_64/microshift/ocp-dev-preview/latest-4.18/el9/os/)"
echo " -ushift-version <microshift-version>"
echo " Version of microshift for image generation (default: ${USHIFT_VERSION}"
exit 1
}

title() {
echo -e "\E[34m\n# $1\E[00m"
}

# Parse the command line
while [ $# -gt 0 ] ; do
case $1 in
-pull_secret_file)
shift
OCP_PULL_SECRET_FILE="$1"
[ -z "${OCP_PULL_SECRET_FILE}" ] && usage "Pull secret file not specified"
[ ! -s "${OCP_PULL_SECRET_FILE}" ] && usage "Empty or missing pull secret file"
shift
;;
-lvm_sysroot_size)
shift
LVM_SYSROOT_SIZE="$1"
[ -z "${LVM_SYSROOT_SIZE}" ] && usage "System root LVM partition size not specified"
[ "${LVM_SYSROOT_SIZE}" -lt ${LVM_SYSROOT_SIZE_MIN} ] && usage "System root LVM partition size cannot be smaller than ${LVM_SYSROOT_SIZE_MIN}MB"
shift
;;
-authorized_keys_file)
shift
AUTHORIZED_KEYS_FILE="$1"
[ -z "${AUTHORIZED_KEYS_FILE}" ] && usage "Authorized keys file not specified"
shift
;;
-use-mirror-repo)
shift
USE_MIRROR_REPO="$1"
[ -z "${USE_MIRROR_REPO}" ] && usage "Mirror repo not specified"
shift
;;
-ushift-version)
shift
USHIFT_VERSION="$1"
[ -z "${USHIFT_VERSION}" ] && usage "MicroShift version not specified"
shift
;;
*)
usage
;;
esac
done

if [ ! -r "${OCP_PULL_SECRET_FILE}" ] ; then
echo "ERROR: pull_secret_file file does not exist or not readable: ${OCP_PULL_SECRET_FILE}"
exit 1
fi
if [ -n "${AUTHORIZED_KEYS_FILE}" ]; then
if [ ! -e "${AUTHORIZED_KEYS_FILE}" ]; then
echo "ERROR: authorized_keys_file does not exist: ${AUTHORIZED_KEYS_FILE}"
exit 1
else
AUTHORIZED_KEYS=$(cat "${AUTHORIZED_KEYS_FILE}")
fi
fi

mkdir -p "${BUILDDIR}"

title "Preparing kickstart config"
# Create a kickstart file from a template, compacting pull secret contents if necessary
cat < "${SCRIPTDIR}/config/config.toml.template" \
| sed "s;REPLACE_LVM_SYSROOT_SIZE;${LVM_SYSROOT_SIZE};g" \
| sed "s;REPLACE_OCP_PULL_SECRET_CONTENTS;$(cat < "${OCP_PULL_SECRET_FILE}" | jq -c);g" \
| sed "s^REPLACE_CORE_AUTHORIZED_KEYS_CONTENTS^${AUTHORIZED_KEYS}^g" \
> "${BUILDDIR}"/config.toml

title "Building bootc image for microshift"
sudo podman build --authfile ${OCP_PULL_SECRET_FILE} -t ${IMGNAME}:${USHIFT_VERSION} \
--build-arg USHIFT_VER=${USHIFT_VERSION} \
--env MIRROR_REPO=${USE_MIRROR_REPO} \
-f "${SCRIPTDIR}/config/Containerfile.bootc-rhel9"

title "Creating ISO image"
sudo podman run --authfile ${OCP_PULL_SECRET_FILE} --rm -it \
--privileged \
--security-opt label=type:unconfined_t \
-v /var/lib/containers/storage:/var/lib/containers/storage \
-v "${BUILDDIR}"/config.toml:/config.toml \
-v "${BUILDDIR}":/output \
registry.redhat.io/rhel9/bootc-image-builder:latest \
--local \
--type iso \
--config /config.toml \
localhost/${IMGNAME}:${USHIFT_VERSION}
30 changes: 30 additions & 0 deletions image-mode/microshift/config/Containerfile.bootc-rhel9
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
FROM registry.redhat.io/rhel9/rhel-bootc:9.4

ARG USHIFT_VER=4.17
RUN if [ -z "${MIRROR_REPO}" ]; then \
dnf config-manager --set-enabled "rhocp-${USHIFT_VER}-for-rhel-9-$(uname -m)-rpms" \
--set-enabled "fast-datapath-for-rhel-9-$(uname -m)-rpms"; \
else \
# This is required to update the gpgcheck for repoID
repoID=$(echo "${MIRROR_REPO#*://}" | tr '/:' '_'); \
dnf config-manager --add-repo "${MIRROR_REPO}" \
--add-repo "https://mirror.openshift.com/pub/openshift-v4/$(uname -m)/dependencies/rpms/${USHIFT_VER}-el9-beta" \
--set-enabled "fast-datapath-for-rhel-9-$(uname -m)-rpms"; \
dnf config-manager --save --setopt="${repoID}".gpgcheck=0 --setopt=*-el9-beta.gpgcheck=0; \
fi
RUN dnf install -y firewalld microshift microshift-release-info cloud-utils-growpart qemu-guest-agent && \
systemctl enable microshift && \
dnf clean all && rm -fr /etc/yum.repos.d/*

RUN rm -fr /opt && ln -sf /var/opt /opt && mkdir /var/opt

# Mandatory firewall configuration
RUN firewall-offline-cmd --zone=public --add-port=22/tcp && \
firewall-offline-cmd --zone=trusted --add-source=10.42.0.0/16 && \
firewall-offline-cmd --zone=trusted --add-source=169.254.169.1 && \
firewall-offline-cmd --zone=trusted --add-source=fd01::/48
# Application-specific firewall configuration
RUN firewall-offline-cmd --zone=public --add-port=80/tcp && \
firewall-offline-cmd --zone=public --add-port=443/tcp && \
firewall-offline-cmd --zone=public --add-port=30000-32767/tcp && \
firewall-offline-cmd --zone=public --add-port=30000-32767/udp
84 changes: 84 additions & 0 deletions image-mode/microshift/config/config.toml.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
[customizations.installer.kickstart]
contents = """
lang en_US.UTF-8
keyboard us
timezone UTC
text
reboot

# Configure network to use DHCP and activate on boot
network --bootproto=dhcp --device=link --activate --onboot=on

# Partition disk with a 1MB BIOS boot, 200M EFI, 800M boot XFS partition and
# an LVM volume containing a 10GB+ system root. The remainder of the volume
# will be used by the CSI driver for storing data
#
# For example, a 20GB disk would be partitioned in the following way:
#
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
# sda 8:0 0 20G 0 disk
# ├─sda1 8:1 0 1M 0 part
# ├─sda2 8:2 0 200M 0 part /boot/efi
# ├─sda3 8:3 0 800M 0 part /boot
# └─sda4 8:4 0 19G 0 part
# └─rhel-root 253:0 0 10G 0 lvm /sysroot
#
zerombr
clearpart --all --disklabel gpt
part biosboot --fstype=biosboot --size=1
part /boot/efi --fstype=efi --size=200
part /boot --fstype=xfs --asprimary --size=800
# Uncomment this line to add a SWAP partition of the recommended size
#part swap --fstype=swap --recommended
part pv.01 --grow
volgroup rhel pv.01
logvol / --vgname=rhel --fstype=xfs --size=REPLACE_LVM_SYSROOT_SIZE --name=root

# Lock root user account
rootpw --lock


%post --log=/var/log/anaconda/post-install.log --erroronfail

# The pull secret is mandatory for MicroShift builds on top of OpenShift, but not OKD
# The /etc/crio/crio.conf.d/microshift.conf references the /etc/crio/openshift-pull-secret file
cat > /etc/crio/openshift-pull-secret <<EOF
REPLACE_OCP_PULL_SECRET_CONTENTS
EOF
chmod 600 /etc/crio/openshift-pull-secret

# Create a default core user, allowing it to run sudo commands without password
useradd -m -d /home/core core
echo -e 'core\tALL=(ALL)\tNOPASSWD: ALL' > /etc/sudoers.d/microshift

# Add authorized ssh keys
mkdir -m 700 /home/core/.ssh
cat > /home/core/.ssh/authorized_keys <<EOF
REPLACE_CORE_AUTHORIZED_KEYS_CONTENTS
EOF
chmod 600 /home/core/.ssh/authorized_keys

# Make sure core user directory contents ownership is correct
chown -R core:core /home/core/

# Configure the firewall (rules reload is not necessary here)
firewall-offline-cmd --zone=trusted --add-source=10.42.0.0/16
firewall-offline-cmd --zone=trusted --add-source=169.254.169.1

# Make the KUBECONFIG from MicroShift directly available for the root user
echo -e 'export KUBECONFIG=/var/lib/microshift/resources/kubeadmin/kubeconfig' >> /root/.profile

# Configure systemd journal service to persist logs between boots and limit their size to 1G
sudo mkdir -p /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/microshift.conf <<EOF
[Journal]
Storage=persistent
SystemMaxUse=1G
RuntimeMaxUse=1G
EOF

# Update certificate trust storage in case new certificates were
# installed at /etc/pki/ca-trust/source/anchors directory
update-ca-trust
%end
"""
105 changes: 16 additions & 89 deletions microshift.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,8 @@ SNC_CLUSTER_CPUS=${SNC_CLUSTER_CPUS:-2}
CRC_VM_DISK_SIZE=${CRC_VM_DISK_SIZE:-31}
BASE_DOMAIN=${CRC_BASE_DOMAIN:-testing}
MIRROR=${MIRROR:-https://mirror.openshift.com/pub/openshift-v4/$ARCH/clients/ocp-dev-preview}
OPENSHIFT_MINOR_VERSION=${OPENSHIFT_MINOR_VERSION:-4.17}

if ! grep -q -i "release 9" /etc/redhat-release
then
echo "This script only works for RHEL-9"
exit 1
fi
MICROSHIFT_VERSION=${MICROSHIFT_VERSION:-4.19}
MIRROR_REPO=${MIRROR_REPO:-https://mirror.openshift.com/pub/openshift-v4/$ARCH/microshift/ocp-dev-preview/latest-${MICROSHIFT_VERSION}/el9/os}

echo "Check if system is registered"
# Check the subscription status and register if necessary
Expand All @@ -42,96 +37,28 @@ create_libvirt_resources
rm id_ecdsa_crc* || true
ssh-keygen -t ecdsa -b 521 -N "" -f id_ecdsa_crc -C "core"

# This requirement is taken from https://github.com/openshift/microshift/blob/main/scripts/image-builder/configure.sh
# Also https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/composing_a_customized_rhel_system_image/installing-composer_composing-a-customized-rhel-system-image
# list out the dependencies and usecase.
# lorax packages which install mkksiso is required for embedding kickstart file to iso file
# podman package is required to run the ostree-container to serve the rpm-ostree content
# createrepo package is required to create localrepo for microshift and it's dependenices
# yum-utils package is required for reposync utility to synchronize packages of a remote DNF repository to a local directory
function configure_host {
sudo dnf install -y git osbuild-composer composer-cli ostree rpm-ostree \
cockpit-composer cockpit-machines bash-completion lorax \
yum-utils createrepo
sudo dnf install -y podman --setopt=install_weak_deps=True
sudo systemctl start osbuild-composer.socket
sudo systemctl start cockpit.socket
sudo firewall-cmd --add-service=cockpit
}

function enable_repos {
local enable_repos="--enable fast-datapath-for-rhel-9-$(uname -i)-rpms"
if [ -z "${MICROSHIFT_PRERELEASE-}" ]; then
enable_repos="${enable_repos} --enable rhocp-${OPENSHIFT_MINOR_VERSION}-for-rhel-9-$(uname -i)-rpms"
fi
sudo subscription-manager repos ${enable_repos}
}

function download_microshift_rpm {
local pkgDir=$1
local extra_opts=""
local nvr_suffix=""
if [ -n "${MICROSHIFT_PRERELEASE-}" ]; then
extra_opts="--setopt=reposdir=./repos"
elif [ -n "${MICROSHIFT_NVR-}" ]; then
nvr_suffix="-${MICROSHIFT_NVR-}"
fi
sudo yum download ${extra_opts} --downloaddir ${pkgDir} --downloadonly microshift${nvr_suffix} microshift-networking${nvr_suffix} \
microshift-release-info${nvr_suffix} microshift-selinux${nvr_suffix} microshift-greenboot${nvr_suffix} microshift-olm${nvr_suffix} \
microshift-multus${nvr_suffix}
}

function create_iso {
local pkgDir=$1
rm -fr microshift
git clone -b release-${OPENSHIFT_MINOR_VERSION} https://github.com/openshift/microshift.git
cp podman_changes.ks microshift/
pushd microshift
sed -i '/# customizations/,$d' scripts/image-builder/config/blueprint_v0.0.1.toml
cat << EOF >> scripts/image-builder/config/blueprint_v0.0.1.toml
[[packages]]
name = "microshift-release-info"
version = "*"
[[packages]]
name = "cloud-utils-growpart"
version = "*"
[[packages]]
name = "qemu-guest-agent"
version = "*"
EOF
sed -i 's/redhat/core/g' scripts/image-builder/config/kickstart.ks.template
sed -i "/--bootproto=dhcp/a\network --hostname=api.${SNC_PRODUCT_NAME}.${BASE_DOMAIN}" scripts/image-builder/config/kickstart.ks.template
sed -i 's/clearpart --all --initlabel/clearpart --all --disklabel gpt/g' scripts/image-builder/config/kickstart.ks.template
sed -i "/clearpart --all/a\part biosboot --fstype=biosboot --size=1" scripts/image-builder/config/kickstart.ks.template
sed -i '$i\grub2-install --target=i386-pc /dev/vda' scripts/image-builder/config/kickstart.ks.template
sed -i '$e cat podman_changes.ks' scripts/image-builder/config/kickstart.ks.template
scripts/image-builder/cleanup.sh -full
# The home dir and files must have read permissions to group
# and others because osbuilder is running from another non-priviledged user account
# and allow it to read the files on current user home (like reading yum repo which is created as part of build script), it is required.
# https://github.com/openshift/microshift/blob/main/scripts/image-builder/configure.sh#L29-L32
chmod 0755 $HOME

scripts/image-builder/build.sh -microshift_rpms ${pkgDir} -pull_secret_file ${OPENSHIFT_PULL_SECRET_PATH} -lvm_sysroot_size 15360 -authorized_keys_file $(realpath ../id_ecdsa_crc.pub)
popd
local buildDir=$1
local extra_arg=""
if [ -n "${MICROSHIFT_PRERELEASE-}" ]; then
extra_arg="-use-mirror-repo ${MIRROR_REPO}"
fi
BUILDDIR=${buildDir} image-mode/microshift/build.sh -pull_secret_file ${OPENSHIFT_PULL_SECRET_PATH} \
-lvm_sysroot_size 15360 \
-authorized_keys_file $(realpath id_ecdsa_crc.pub) \
-ushift-version ${MICROSHIFT_VERSION} \
${extra_arg}
}

configure_host

enable_repos
microshift_pkg_dir=$(mktemp -p /tmp -d tmp-rpmXXX)
# This directory contains the microshift rpm passed to osbuilder, worker for osbuilder
# running as non-priviledged user and this tmp directory have 0700 permission. To allow
# worker to read/execute this file we need to change the permission to 0755
chmod 0755 ${microshift_pkg_dir}
download_microshift_rpm ${microshift_pkg_dir}

create_iso ${microshift_pkg_dir}
sudo cp -Z microshift/_output/image-builder/microshift-installer-*.iso /var/lib/libvirt/${SNC_PRODUCT_NAME}/microshift-installer.iso
OPENSHIFT_RELEASE_VERSION=$(rpm -qp --qf '%{VERSION}' ${microshift_pkg_dir}/microshift-4.*.rpm)
sudo cp -Z ${microshift_pkg_dir}/bootiso/install.iso /var/lib/libvirt/${SNC_PRODUCT_NAME}/microshift-installer.iso
OPENSHIFT_RELEASE_VERSION=$(sudo podman run --rm -it localhost/microshift:${MICROSHIFT_VERSION} /usr/bin/rpm -q --qf '%{VERSION}' microshift)
# Change 4.x.0~ec0 to 4.x.0-ec0
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Versioning/#_complex_versioning
OPENSHIFT_RELEASE_VERSION=$(echo ${OPENSHIFT_RELEASE_VERSION} | tr '~' '-')
rm -fr ${microshift_pkg_dir}
sudo rm -fr ${microshift_pkg_dir}

# Download the oc binary for specific OS environment
OC=./openshift-clients/linux/oc
Expand Down

0 comments on commit 83bd510

Please sign in to comment.