Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create MicroShift iso using image mode and bootc image builder #999

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions 00-microshift-dns.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
dns:
# baseDomain is the base domain of the cluster. All managed DNS records will
# be sub-domains of this base.


# For example, given the base domain `example.com`, router exposed
# domains will be formed as `*.apps.example.com` by default,
# and API service will have a DNS entry for `api.example.com`,
# as well as "api-int.example.com" for internal k8s API access.


# Once set, this field cannot be changed.
# example:
# microshift.example.com
baseDomain: example.com
9 changes: 4 additions & 5 deletions createdisk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,11 @@ EOF
# also in case of microshift the ports like 2222, 443, 80 ..etc need to be manually added
# and OCP/OKD/podman bundles have it disabled by default.
${SSH} core@${VM_IP} -- sudo systemctl disable firewalld
${SSH} core@${VM_IP} -- cat /etc/microshift/config.yaml.default > config.yaml
${YQ} eval --inplace ".dns.baseDomain = \"${SNC_PRODUCT_NAME}.${BASE_DOMAIN}\"" config.yaml
${SCP} config.yaml core@${VM_IP}:/home/core
${SSH} core@${VM_IP} -- 'sudo mv /home/core/config.yaml /etc/microshift/config.yaml'
${YQ} eval --inplace ".dns.baseDomain = \"${SNC_PRODUCT_NAME}.${BASE_DOMAIN}\"" 00-microshift-dns.yaml
${SCP} 00-microshift-dns.yaml core@${VM_IP}:/home/core
${SSH} core@${VM_IP} -- 'sudo mv /home/core/00-microshift-dns.yaml /etc/microshift/config.d/00-microshift-dns.yaml'
# Make sure `baseDomain` is set to crc.testing
${SSH} core@${VM_IP} -- "grep '^\s\+baseDomain: ${SNC_PRODUCT_NAME}.${BASE_DOMAIN}' /etc/microshift/config.yaml"
${SSH} core@${VM_IP} -- "grep '^\s\+baseDomain: ${SNC_PRODUCT_NAME}.${BASE_DOMAIN}' /etc/microshift/config.d/00-microshift-dns.yaml"
# Remove the lvm system.device file since it have diskID and deviceName which changes
# for different hypervisor and as per `man lvmdevices` if the file does not exist, or if lvm.conf
# includes use_devicesfile=0, then lvm will not use a devices file.
Expand Down
144 changes: 144 additions & 0 deletions image-mode/microshift/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/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}"
echo " -hostname <hostname>"
echo " Hostname of the machine"
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
;;
-hostname)
shift
HOSTNAME="$1"
[ -z "${HOSTNAME}" ] && usage "hostname 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_HOSTNAME;${HOSTNAME};g" \
| 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}
34 changes: 34 additions & 0 deletions image-mode/microshift/config/Containerfile.bootc-rhel9
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
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 dnsmasq && \
dnf clean all && rm -fr /etc/yum.repos.d/*

# https://github.com/containers/bootc/discussions/1036
# /Users is created to make sure share directory works on
# mac because on linux it is /home and for windows it is /mnt
# and both are symlink to `var` already
RUN rm -fr /opt && ln -sf var/opt /opt && mkdir /var/opt
RUN ln -sf var/Users /Users && mkdir /var/Users

# 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
112 changes: 112 additions & 0 deletions image-mode/microshift/config/config.toml.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
[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/

# Set static hostname
echo "REPLACE_HOSTNAME" > /etc/hostname
chmod 644 /etc/hostname

# 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


# 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

# Support to boot for UEFI and legacy mode
grub2-install --target=i386-pc /dev/vda

# Make podman rootless available
mkdir -p /home/core/.config/systemd/user/default.target.wants
ln -s /usr/lib/systemd/user/podman.socket /home/core/.config/systemd/user/default.target.wants/podman.socket
chown -R core:core /home/core/.config

mkdir -p /home/core/.config/containers
tee /home/core/.config/containers/containers.conf <<EOF
[containers]
netns="bridge"
rootless_networking="cni"
EOF
chown -R core:core /home/core/.config/containers

touch /etc/containers/podman-machine

tee /etc/containers/registries.conf.d/999-podman-machine.conf <<EOF
unqualified-search-registries=["docker.io"]
EOF

# Enable linger for core user to make sure podman socket work when user not logged in
mkdir -p /var/lib/systemd/linger/
touch /var/lib/systemd/linger/core
%end
"""
Loading