Creating a Node from a Custom Basic Installation of RHEL 8.x

This document describes how to create a custom node image for a Red Hat Enterprise Linux system from a clean base installation. This process is meant for cases where you need to provision a node manually from a base ISO installation instead of using prebuilt Luna images.

Case Overview

When building a new node image from scratch, you must start from a clean, minimal RHEL installation. This case covers a RHEL 8 based node install and image creation, but the principle would work for RHEL 9 nodes as well. The described procedure captures the node installation into a Luna-managed image, which can then be used for provisioning of other nodes.

Procedure

All described tasks are executed as root.
Tasks, 1 to 3 are performed on the node. Tasks 4 to 11 are performed on the controller.

1. Prepare a Clean Base Installation

Install a clean RHEL 8.x system on a node.

2. Enable Required Repositories

Ensure that the repositories required for package installation are available on the node. Enrol the node into the RedHat subscription to have access to, or create a repo, e.g. /etc/yum.repos.d/redhat.repo to include at minimum BaseOS and AppStream repositories.

Example:

[BaseOS]
name=RHEL 8.9 BaseOS
baseurl=http://your_link/mirror/rhel8/8.9/BaseOS/
enabled=1
gpgcheck=0

[AppStream]
name=RHEL 8.9 AppStream
baseurl=http://your_link/mirror/rhel8/8.9/AppStream/
enabled=1
gpgcheck=0

3. Install Required Tools

Install rsync package for the grab process.

dnf install -y rsync

4. Add an Empty Luna Image on the controller

Add an empty image that will be used to store the captured OS.

Example:

luna osimage add rhel8

5. Prepare Node for OS Grab on the controller

Add the node to Luna and configure its interface before grabbing.

Example:

luna node add node-rhel8 -g compute-group -o rhel8
luna node change -if BOOTIF -I 1.2.3.4 node-rhel8
ssh-copy-id root@node-rhel8

The IP address, in the example's case 1.2.3.4, should match with what's currently configured on the installed node during step 1. If an existing node is used, the IP address change can be omitted, but make sure to assign the correct image to that node.

6. Perform OS Grab on the controller

Grab the system image from the node into the Luna image.

Example:

luna node osgrab -o rhel8 --nodry -b node-rhel8

7. Copy and Modify Compute Playbook

Note

This step assumes you have a cloned repo of the TrinityX stack on your controller. If this is not the case, please refer to the installation section for detailed steps.

Change directory to the TrinityX cloned repo location and into 'site'. Copy the default compute Ansible playbook and customize it for the new image.

Example:

cd ~/trinityX/site
cp compute-default.yml compute-rhel8.yml

Edit compute-rhel8.yml:

set_fact:
  image_name: "rhel8"        # Change image name

tags: always

- import_playbook: imports/trinity-redhat-image-create.yml

vars:
  image_name: "{{ hostvars['localhost']['image_name'] }}"
  alternative_distribution: RedHat-8   # Set correct distribution and version
  alternative_image_source: 'base'     # Use base instead of docker
  alternative_image_distr: redhat      # Specify the distribution

8. Run Ansible Playbook (First Pass)

Run the playbook to initialize the environment but skip image packing.

ansible-playbook compute-rhel8.yml --skip-tags=pack-images

9. Install Required Packages Script

Inside the same folder of the ansible playbooks (site), create a script with name extended-image-install-packages.sh with the following content:

#!/bin/bash

if [ "$1" == "" ]; then
        echo "needs argument: image name used for osgrabbing/building"
        exit 1
fi
IMAGE=$1

ARCH=$(uname -m)
PARCH=x64
if [ "$ARCH" == "aarch64" ] || [ "$ARCH" == "arm64" ]; then
        PARCH=aa64
fi

DISTR=$(luna osimage show ${IMAGE} | grep distribu | awk '{ print $4 }')
if [ "$DISTR" == "" ]; then
        echo "could not collect distribution information for image $IMAGE. does it exist?"
        exit 1
fi

PACKAGES=$(sed -n '/image_core_packages/,/^$/p' roles/trinity/image-create/vars/${PARCH}/image-${DISTR}.yaml |grep "\-"|sed -e 's/^\s*\-//g'|tr -d "\"\n")
if [ "$PACKAGES" == "" ]; then
        echo "I expect to see the directory 'roles', but i do not. Am i in the TrinityX/site directory?"
        exit 1
fi
echo "======================== Installing packages in ${IMAGE} ========================"
echo $PACKAGES | tr ' ' '\n'
echo

case "$DISTR" in
        ubuntu)
                lchroot $IMAGE apt install ${PACKAGES}
                ;;
        opensuse)
                lchroot $IMAGE zypper install ${PACKAGES}
                ;;
        *)
                lchroot $IMAGE dnf -y install ${PACKAGES}
                ;;
esac

echo "======================== Clearing fstab in ${IMAGE} ========================"
cp /etc/fstab /etc/fstab_backup
lchroot $IMAGE truncate -s0 /etc/fstab

echo
echo "finished. continue with running the ansible compute playbooks"

Run the provided script to install necessary packages for the distribution and architecture. The chosen image name in step 4 is provided as script parameter.

chmod 755 extended-image-install-packages.sh
./extended-image-install-packages.sh rhel8

10. Run Ansible Playbook (Final Pass)

Run the playbook again to finalize the image creation (this time without skipping tags).

ansible-playbook compute-rhel8.yml

11. Finalize

Once completed, your new RHEL 8.x compute image is ready to use and can be modified and tuned to your needs. Refer to Image management for more information on how to work with images.