diff --git a/.github/workflows/release.md b/.github/workflows/release.md index ad71fa63..fa9a0aca 100644 --- a/.github/workflows/release.md +++ b/.github/workflows/release.md @@ -31,3 +31,7 @@ sudo podman pull ${IMAGE}:${TAG} ``` Review the instructions in [MicroShift Bootc Deployment](https://github.com/microshift-io/microshift/blob/main/docs/run-bootc.md) to run the image. + +#### ISO + +Review the instructions in [MicroShift ISO Deployment](https://github.com/microshift-io/microshift/blob/main/docs/run-iso.md) to install from ISO and run MicroShift. diff --git a/Makefile b/Makefile index 3b31759e..c6a80712 100644 --- a/Makefile +++ b/Makefile @@ -53,6 +53,7 @@ all: @echo " rpm: build the MicroShift RPMs" @echo " srpm: build the MicroShift SRPM" @echo " image: build the MicroShift bootc container image" + @echo " iso: create a bootable ISO from the MicroShift bootc image" @echo " run: create and run a MicroShift cluster (1 node) in a bootc container" @echo " add-node: add a new node to the MicroShift cluster in a bootc container" @echo " start: start the MicroShift cluster that was already created" @@ -133,6 +134,17 @@ image: --env EMBED_CONTAINER_IMAGES="${EMBED_CONTAINER_IMAGES}" \ -f packaging/bootc.Containerfile . +.PHONY: iso +iso: + @if ! sudo podman image exists "$${BOOTC_IMAGE:-localhost/${USHIFT_IMAGE}}" ; then \ + echo "ERROR: Run 'make image' to build the MicroShift bootc image" ; \ + exit 1 ; \ + fi + + @echo "Creating a bootable ISO from the MicroShift bootc image" + @outdir="$${ISO_OUTDIR:-$$(mktemp -d /tmp/microshift-iso-XXXXXX)}" && \ + sudo ./src/iso/makeiso.sh "$${BOOTC_IMAGE:-localhost/${USHIFT_IMAGE}}" "$${outdir}" + .PHONY: run run: @USHIFT_IMAGE=${USHIFT_IMAGE} ISOLATED_NETWORK=${ISOLATED_NETWORK} LVM_DISK=${LVM_DISK} LVM_VOLSIZE=${LVM_VOLSIZE} VG_NAME=${VG_NAME} EXPOSE_KUBEAPI_PORT=${EXPOSE_KUBEAPI_PORT} ./src/cluster_manager.sh create diff --git a/README.md b/README.md index 8059123d..161aaf76 100644 --- a/README.md +++ b/README.md @@ -64,4 +64,5 @@ setup, next steps for accessing MicroShift and uninstall instructions. * [Versioning Scheme](./docs/versioning.md) * [MicroShift Host Deployment](./docs/run.md) * [MicroShift Bootc Deployment](./docs/run-bootc.md) +* [MicroShift ISO Deployment](./docs/run-iso.md) * [GitHub Workflows](./docs/workflows.md) diff --git a/docs/build.md b/docs/build.md index c15343df..4f15d991 100644 --- a/docs/build.md +++ b/docs/build.md @@ -61,9 +61,9 @@ system. RPMs are build from the SRPM built by running `make srpm`. The following options can be specified in the make command line using the `NAME=VAL` format. -| Name | Required | Default | Comments | -|-----------------|----------|----------|----------| -| RPM_OUTDIR | no | /tmp/... | RPM repository output directory | +| Name | Required | Default | Comments | +|------------|----------|----------|----------| +| RPM_OUTDIR | no | /tmp/... | RPM repository output directory | ```bash make rpm @@ -143,3 +143,30 @@ If the build completes successfully, the `microshift-okd` image is created. > The base operating system image used to run MicroShift can be overriden by > specifying `BOOTC_IMAGE_URL=value` and `BOOTC_IMAGE_TAG=value` make command line > arguments. + +### Create ISO + +Create a bootable ISO from the MicroShift Bootc image by running the `make iso` command. + +The following options can be specified in the make command line using the `NAME=VAL` format. + +| Name | Required | Default | Comments | +|-------------|----------|--------------------------|----------| +| ISO_OUTDIR | no | /tmp/... | ISO image output directory | +| BOOTC_IMAGE | no | localhost/microshift-okd | Bootc image used for ISO build | + +The `make iso` command uses the latest bootc image to create a bootable ISO with +[Bootc Image Builder](https://github.com/osbuild/bootc-image-builder). + +```bash +make iso +``` + +If the ISO creation completes successfully, the `install.iso` file is created at +the `${ISO_OUTDIR}/bootiso` directory on the host. + +``` +... +... +ISO image created at '/tmp/microshift-iso-niQwAN/bootiso/install.iso' +``` diff --git a/docs/run-iso.md b/docs/run-iso.md new file mode 100644 index 00000000..d15106cf --- /dev/null +++ b/docs/run-iso.md @@ -0,0 +1,182 @@ +# MicroShift ISO Deployment + +MicroShift ISO can be installed on a physical host or a virtual machine. +This document describes how to install MicroShift ISO inside a virtual machine. + +> Hardware-level configuration is host-dependent and excluded from this document +> to maintain a vendor-neutral deployment guide. + +## Prerequisites + +### Virtualization + +The procedures described in this document must be run on a physical hypervisor host +of the supported `x86_64` or `aarch64` architecture. The [libvirt](https://libvirt.org/) +toolkit for managing virtualization platforms is used for starting virtual machines. + +### Kickstart + +MicroShift ISO uses [Anaconda Installer](https://anaconda-installer.readthedocs.io/), +which can be customized using [Kickstart](https://anaconda-installer.readthedocs.io/en/latest/kickstart.html). + +It is recommended to customize the system with user-specific settings like +hostname, user names and passwords, SSH keys, disk partitioning, etc. + +An opinionated example of such a customization can be found at [kickstart.ks.template](../src/iso/kickstart.ks.template). +The file is used during the installation procedures described below. + +### Installer Types + +Two installation techniques are presented below: +- Using a custom ISO installer with an embedded Bootc container image +- Using a stock ISO installer image with a Bootc container image from registry + +> Stock ISO deployment is recommended for most use cases to minimize maintenance. +> Custom builds are reserved for specific environmental needs that fall outside +> the scope of Kickstart automation. + +When using a custom ISO installer, follow the instructions in [Create ISO](./build.md#create-iso) +to build the ISO installer. + +When using a stock ISO installer, download it from one of the following sites. + +| OS | Link | +|-----------|-----------------| +| Fedora | [Booting via ISO](https://docs.fedoraproject.org/en-US/fedora-coreos/live-booting/#_booting_via_iso) | +| CentOS 10 | [x86_64](https://mirror.stream.centos.org/10-stream/BaseOS/x86_64/iso/) [aarch64](https://mirror.stream.centos.org/10-stream/BaseOS/aarch64/iso/) | +| CentOS 9 | [x86_64](https://mirror.stream.centos.org/9-stream/BaseOS/x86_64/iso/) [aarch64](https://mirror.stream.centos.org/9-stream/BaseOS/aarch64/iso/) | + +## Installation + +Follow instructions in one of [Custom ISO](#custom-iso) or [Stock ISO](#stock-iso) +sections below, depending on the installation type of choice. + +### Custom ISO + +Copy the `install.iso` file to the `/var/lib/libvirt/images` directory and set +the following variables to be used during the virtual machine creation. + +```bash +VMNAME="microshift-okd" +NETNAME="default" +ISOFILE="install.iso" +``` + +Convert the kickstart template to a configuration suitable for the custom ISO +installation by resetting transport and URL variables. + +```bash +KSTEMP="./src/iso/kickstart.ks.template" +KSFILE=/tmp/kickstart-custom-iso.ks + +# Loading the bootc image bundled in the ISO +export BOOTC_IMAGE_TRANSPORT=oci +export BOOTC_IMAGE_URL=/run/install/repo/container + +envsubst '${BOOTC_IMAGE_TRANSPORT} ${BOOTC_IMAGE_URL}' \ + < "${KSTEMP}" > "${KSFILE}" +``` + +Run the following commands to create a virtual machine. You can watch the +installation progress at the console of the created virtual machine. + +```bash +# Always use a full path for kickstart files +KSFILE="$(readlink -f "${KSFILE}")" + +sudo bash -c " \ +cd /var/lib/libvirt/images/ && \ +virt-install \ + --name "${VMNAME}" \ + --vcpus 2 \ + --memory 3072 \ + --disk "path=./${VMNAME}.qcow2,size=20" \ + --network "network=${NETNAME},model=virtio" \ + --events on_reboot=restart \ + --location "${ISOFILE}" \ + --initrd-inject "${KSFILE}" \ + --extra-args "inst.ks=file:/$(basename "${KSFILE}") console=tty0" \ + --wait \ +" +``` + +The virtual machine should reboot in the event of a successful installation and +present a user login prompt. + +### Stock ISO + +Download an ISO from one of the locations mentioned in the [Installer Types](#installer-types) +and copy the file to the `/var/lib/libvirt/images` directory. +Set the following variables to be used during the virtual machine creation. + +```bash +VMNAME="microshift-okd" +NETNAME="default" +ISOFILE="CentOS-Stream-10-latest-$(uname -m)-boot.iso" +``` + +Convert the kickstart template to a configuration suitable for the stock ISO +installation by resetting transport and URL variables. + +```bash +KSTEMP="./src/iso/kickstart.ks.template" +KSFILE=/tmp/kickstart-stock-iso.ks + +# Loading the bootc image from a container registry +export BOOTC_IMAGE_TRANSPORT=registry +export BOOTC_IMAGE_URL="ghcr.io/microshift-io/microshift:" + +envsubst '${BOOTC_IMAGE_TRANSPORT} ${BOOTC_IMAGE_URL}' \ + < "${KSTEMP}" > "${KSFILE}" +``` + +Run the following commands to create a virtual machine. You can watch the +installation progress at the console of the created virtual machine. + +```bash +# Always use a full path for kickstart files +KSFILE="$(readlink -f "${KSFILE}")" + +sudo bash -c " \ +cd /var/lib/libvirt/images/ && \ +virt-install \ + --name "${VMNAME}" \ + --vcpus 2 \ + --memory 3072 \ + --disk "path=./${VMNAME}.qcow2,size=20" \ + --network "network=${NETNAME},model=virtio" \ + --events on_reboot=restart \ + --location "${ISOFILE}" \ + --initrd-inject "${KSFILE}" \ + --extra-args "inst.ks=file:/$(basename "${KSFILE}") console=tty0" \ + --wait \ +" +``` + +The virtual machine should reboot in the event of a successful installation and +present a user login prompt. + +## Login + +Log into the virtual machine console by running the following command. Enter the +`microshift:microshift` credentials when prompted. + +```bash +sudo virsh console --force "${VMNAME}" +``` + +Verify that all the MicroShift services are up and running successfully. +```bash +sudo oc get nodes +sudo oc get pods -A +``` + +## Cleanup + +Run the following commands to shut down and delete the virtual machine. + +```bash +sudo virsh destroy "${VMNAME}" +sudo virsh undefine "${VMNAME}" +sudo rm -f "/var/lib/libvirt/images/${VMNAME}.qcow2" +``` diff --git a/src/iso/kickstart.ks.template b/src/iso/kickstart.ks.template new file mode 100644 index 00000000..4da15799 --- /dev/null +++ b/src/iso/kickstart.ks.template @@ -0,0 +1,80 @@ +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 system root partition of the specified size. +# The remainder of the volume will be used by the CSI driver for storing data. +# +# For example, a 20GB disk with 15GB system root may be partitioned in the following way. +# +# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS +# loop0 7:0 0 7.9M 1 loop +# sda 8:0 0 20G 0 disk +# ├─sda1 8:1 0 1G 0 part /boot +# └─sda2 8:2 0 19G 0 part +# └─rhel-root 253:0 0 15G 0 lvm /sysroot +# sr0 11:0 1 1024M 0 rom +# zram0 252:0 0 3.8G 0 disk [SWAP] +# +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 myvg1 pv.01 +logvol / --vgname=myvg1 --fstype=xfs --size=15360 --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 --hostname=microshift-okd + +# Configure bootc to install from the local embedded container repository or +# a remote container registry +# +# Transport: 'oci' for local or 'registry' for remote +# URL: '/run/install/repo/container' for local or FQDN for remote +ostreecontainer --transport $BOOTC_IMAGE_TRANSPORT --url $BOOTC_IMAGE_URL + +%post --log=/dev/console --erroronfail + +# Create a default microshift user, allowing it to run sudo commands without password. +# NOTE: Remove or change the password hash for production deployments. +useradd -m -p \$5\$XCVQ6AZVF6D5YW6V\$7wV451u/3oxvWA8vlqX.bWiBAYO/M8VRpZidA0vmzj5 microshift +echo -e 'microshift\tALL=(ALL)\tNOPASSWD: ALL' > /etc/sudoers.d/microshift + +# Make the KUBECONFIG from MicroShift directly available for the root user +if [ ! -d /root ]; then + # Workaround for bootc container init. + # /var/roothome (which /root symlinks to) is not present when init + # entrypoint starts (before systemd). So it needs to be pre-populated, + # so it exists when /var/roothome is mounted. + mkdir -p /var/roothome/ + echo -e 'export KUBECONFIG=/var/lib/microshift/resources/kubeadmin/kubeconfig' >> /var/roothome/.bash_profile +else + echo -e 'export KUBECONFIG=/var/lib/microshift/resources/kubeadmin/kubeconfig' >> /root/.bash_profile +fi + +# Configure systemd journal service to persist logs between boots and limit their size to 1G +mkdir -p /etc/systemd/journald.conf.d +cat > /etc/systemd/journald.conf.d/microshift.conf <> /etc/fstab + +%end diff --git a/src/iso/makeiso.sh b/src/iso/makeiso.sh new file mode 100755 index 00000000..730dbe99 --- /dev/null +++ b/src/iso/makeiso.sh @@ -0,0 +1,52 @@ +#!/bin/bash +set -euo pipefail + +BIB_IMAGE="quay.io/centos-bootc/bootc-image-builder:latest" + +usage() { + echo "Usage: ${0} " + exit 1 +} + +# +# Main +# +if [ $# -ne 2 ] ; then + usage +fi + +IMAGE_IN="${1}" +ISO_OUT="${2}" + +if ! sudo podman image exists "${IMAGE_IN}" ; then + echo "ERROR: '${IMAGE_IN}' is not a valid image" + exit 1 +fi + +if [ ! -d "${ISO_OUT}" ] ; then + echo "ERROR: '${ISO_OUT}' is not a directory" + exit 1 +fi + +echo "Creating ISO image from '${IMAGE_IN}'" +echo "Output ISO path: '${ISO_OUT}'" + +# Create the ISO image +sudo podman run --rm -i \ + --privileged \ + --pull=newer \ + --security-opt label=type:unconfined_t \ + -v /var/lib/containers/storage:/var/lib/containers/storage \ + -v "${ISO_OUT}:/output" \ + "${BIB_IMAGE}" \ + --type anaconda-iso \ + "${IMAGE_IN}" + +ISO_FILE="$(find "${ISO_OUT}" -name "install.iso" -print -quit)" +if [ -z "${ISO_FILE}" ] ; then + echo "ERROR: ISO image not found in '${ISO_OUT}'" + exit 1 +fi + +# Exit with the ISO image path +echo "ISO image created at '${ISO_FILE}'"