Select a Fixed System Disk on Multi-Disk Bare-Metal Hosts

Use this guide when one SeedImage ISO must be reused across multiple bare-metal hosts and each host has more than one disk. The procedure prevents Elemental from automatically choosing a different disk on each boot and lets an operator select the system disk on each host by its stable WWN.

Why a Manual Disk Gate Is Required

Do not leave MachineRegistration.spec.config.elemental.install.device empty on a multi-disk host. An empty device and an empty device-selector do not make Elemental wait for an operator to choose a disk. Multiple discovered disks can match, and one of them is selected without a uniqueness check.

Do not use /dev/sda as a persistent disk identity either. Storage-controller discovery order can change between the Live ISO and the installed system, so the same logical disk can appear as /dev/sda during one boot and /dev/sdb during another.

This guide uses a fail-closed manual gate:

  1. Every reusable ISO contains the same, initially nonexistent install path: /dev/elemental-install-target.
  2. The install service cannot proceed while that path does not exist, and it does not fall back to automatic disk selection.
  3. On each host, an operator identifies the intended whole disk by /dev/disk/by-id/wwn-* and creates the gate as a symbolic link to that disk.
  4. The operator starts the install service only after the disk, network, mount, and stale-label checks pass.
WARNING

The cleanup procedure in this guide permanently destroys data. Run it only from the Live ISO console, only on disks approved for reinstallation, and only after verifying that none of those disks is mounted.

Prerequisites

  • The bare-metal provider and elemental-operator are installed on the global cluster.
  • You can create or edit MachineRegistration and SeedImage resources in cpaas-system.
  • You have console access to each host through BMC, iDRAC, iLO, or an equivalent interface.
  • Each intended system disk has a stable /dev/disk/by-id/wwn-* entry.
  • You know which disks may be erased. If the host contains data disks that must be preserved, exclude them from every cleanup command.
  • If the Live ISO network has no DHCP service, you have the host IP address, prefix, gateway, DNS server, and Global registration URL.

See Creating Clusters on Bare Metal for the complete provider and cluster creation workflow.

Configure the Shared MachineRegistration

Set the install device to /dev/elemental-install-target. Do not configure a device-selector for this workflow.

MachineRegistration install settings
apiVersion: elemental.cattle.io/v1beta1
kind: MachineRegistration
metadata:
  name: <cluster-name>-registration
  namespace: cpaas-system
spec:
  machineName: "<cluster-name>-${System Information/UUID}"
  config:
    elemental:
      install:
        device: /dev/elemental-install-target
        eject-cd: true
        reboot: true
        snapshotter:
          type: btrfs
          maxSnaps: 4
      registration:
        auth: tpm
        # Use hardware TPM when available. For hosts without TPM, enable
        # emulation and derive a unique identity for every host.
        emulate-tpm: true
        emulated-tpm-seed: -1

The path is intentionally absent when the Live ISO starts. A filesystem label, GPT PARTLABEL, or /dev/disk/by-label/* path is not an alternative: these identify partitions, while Elemental requires a whole-disk install target.

Create a SeedImage that references this MachineRegistration, or rebuild the existing SeedImage after changing the install device.

WARNING

The MachineRegistration settings are embedded in the generated ISO. Patching the MachineRegistration does not change an ISO that was already built and downloaded. Rebuild the SeedImage, wait until it is ready, download the new ISO, and verify its checksum before booting hosts from it.

Prepare Each Host

Perform the following steps on one host at a time. Do not prepare multiple hosts in parallel when disk cleanup is required.

1. Boot the Expected Live ISO and Block Automatic Installation

Boot the host from the shared ISO. As soon as the Live ISO console is available, stop and mask the automatic installer:

systemctl stop elemental-register-install.service
systemctl mask elemental-register-install.service
systemctl reset-failed elemental-register-install.service

Confirm that the ISO contains the manual gate:

grep -n -C 3 '/dev/elemental-install-target' \
  /run/initramfs/live/livecd-cloud-config.yaml

If the path is not present, the host did not boot the expected ISO. Do not continue.

2. Confirm That the Host Is Running from the Live ISO

findmnt -n -o SOURCE,FSTYPE,TARGET /
findmnt /run/initramfs/live
lsblk -e7 -o NAME,PATH,TYPE,SIZE,MODEL,SERIAL,WWN,FSTYPE,LABEL,MOUNTPOINTS

Confirm all of the following:

  • / is the Live root, such as LiveOS_rootfs.
  • The virtual CD device, normally /dev/sr0, has the COS_LIVE label.
  • No disk that you plan to clean or use as the install target is mounted.

Check for physical-disk, device-mapper, swap, LVM, and multipath use:

findmnt -rn -o SOURCE,TARGET | grep -E '^/dev/(sd|mapper/)' || \
  echo NO_PHYSICAL_DISK_MOUNTS
swapon --show
pvs 2>/dev/null || true
vgs 2>/dev/null || true
multipath -ll 2>/dev/null || true

Stop if a target disk is mounted or if you cannot prove that the root filesystem belongs to the Live ISO.

3. Configure the Live ISO Network When DHCP Is Unavailable

First identify the actual NetworkManager connection and interface. Do not assume the connection is always named Wired connection 1.

nmcli device status
nmcli connection show
ip -br link

Configure the selected connection with the values assigned to this host:

nmcli connection modify "Wired connection 1" \
  ipv4.method manual \
  ipv4.addresses 192.168.254.76/24 \
  ipv4.gateway 192.168.254.1 \
  ipv4.dns 192.168.16.19 \
  ipv4.ignore-auto-dns yes

nmcli connection up "Wired connection 1"

Verify the address, default route, DNS resolution, and the complete registration URL:

ip -br addr
ip route
cat /etc/resolv.conf
ping -c 2 -W 2 192.168.254.1
getent hosts <global-domain>
curl -ksS --connect-timeout 10 \
  -o /dev/null -w 'REG_HTTP=%{http_code}\n' \
  'https://<global-domain>/<registration-path-and-token>'

Use the site-specific network values instead of copying the example addresses. Keep the full registration URL and token out of source control and shared logs.

This network configuration only connects the Live ISO for registration and initial installation. It does not replace the persistent networking applied to the installed system during Cluster API reprovisioning.

4. Identify All Disks and the Intended System Disk

List stable disk attributes:

lsblk -d -e7 -o NAME,PATH,TYPE,SIZE,MODEL,SERIAL,WWN,HCTL

for current_disk in /dev/sda /dev/sdb /dev/sdc /dev/sdd; do
  echo "=== ${current_disk} ==="
  udevadm info -q symlink -n "${current_disk}" | tr ' ' '\n' |
    grep -E 'disk/by-id/(wwn|scsi)-' || true
done

Adjust the disk list for the current host. Record and cross-check:

  • Current kernel device name.
  • Size, model, serial number, and controller address (HCTL).
  • /dev/disk/by-id/wwn-* path.
  • Which whole disk is approved as the system disk.

Use the WWN plus the size, model, and controller information to make the decision. Do not select a disk by kernel name or capacity alone.

5. Remove Stale Elemental Labels When Reinstalling a Host

Skip destructive cleanup on disks that must preserve data. When the host is being fully reinstalled, remove old mappings before cleaning the approved disks:

swapoff -a
vgchange -an 2>/dev/null || true
systemctl stop multipathd.service multipathd.socket 2>/dev/null || true
systemctl mask multipathd.service multipathd.socket 2>/dev/null || true
multipath -F 2>/dev/null || true
udevadm settle

If the host has unrelated LVM, multipath, or shared-storage devices, do not use global deactivation commands. Deactivate only mappings that belong to the approved disks.

For each approved disk, clear its GPT, recognized signatures, and metadata at the start and end of the disk. The example below operates on /dev/sda; repeat it only for each disk that you have independently identified and approved.

disk_to_wipe=/dev/sda

lsblk -d -o NAME,PATH,SIZE,MODEL,SERIAL,WWN,HCTL "${disk_to_wipe}"
sgdisk --zap-all "${disk_to_wipe}"
wipefs -a -f "${disk_to_wipe}"
dd if=/dev/zero of="${disk_to_wipe}" \
  bs=1M count=64 conv=fsync status=progress

disk_sectors=$(blockdev --getsz "${disk_to_wipe}")
if [ "${disk_sectors}" -le 262144 ]; then
  echo 'REFUSE: disk is too small; stop and recheck the target'
else
  dd if=/dev/zero of="${disk_to_wipe}" bs=512 \
    seek=$((disk_sectors-131072)) count=131072 \
    conv=fsync status=progress
fi

Refresh the kernel and udev after all approved disks are cleaned:

partprobe /dev/sda /dev/sdb /dev/sdc /dev/sdd 2>/dev/null || true
udevadm trigger --subsystem-match=block
udevadm settle

Adjust the partprobe list to include only the disks cleaned on this host.

Verify that the cleaned disks have no signatures, partitions, filesystem types, labels, or partition labels:

wipefs /dev/sda /dev/sdb /dev/sdc /dev/sdd
lsblk -e7 -o \
NAME,PATH,TYPE,SIZE,MODEL,SERIAL,WWN,FSTYPE,LABEL,PARTLABEL,MOUNTPOINTS

if blkid /dev/sda /dev/sdb /dev/sdc /dev/sdd 2>/dev/null |
  grep -E 'LABEL="(OLD_)?COS_(GRUB|OEM|RECOVERY|STATE|PERSISTENT)"'; then
  echo COS_LABELS_REMAIN
else
  echo NO_COS_LABELS
fi

Adjust each device list to match the cleaned disks. Continue only when:

  • wipefs prints no signature for any cleaned disk.
  • lsblk shows no old child partitions, FSTYPE, LABEL, or PARTLABEL.
  • The check prints NO_COS_LABELS.
  • The only remaining COS_LIVE label belongs to the virtual CD device, not a system disk.

6. Create the Per-Host Install Target

List the stable WWN paths again after cleanup:

ls -l /dev/disk/by-id/wwn-*
lsblk -d -e7 -o NAME,PATH,SIZE,MODEL,SERIAL,WWN,HCTL

Create the gate only after selecting and verifying the intended whole disk. Replace the example WWN with the value recorded for this host:

test ! -e /dev/elemental-install-target
test ! -L /dev/elemental-install-target

ln -s \
  /dev/disk/by-id/wwn-0x0123456789abcdef \
  /dev/elemental-install-target

readlink -f /dev/elemental-install-target
test -b /dev/elemental-install-target && echo TARGET_IS_BLOCK
lsblk -d -o NAME,PATH,SIZE,MODEL,SERIAL,WWN,HCTL \
  "$(readlink -f /dev/elemental-install-target)"

If the alias already exists or is a dangling link, do not overwrite it. Inspect it with readlink, determine why it exists, and remove it only after confirming it is stale.

The link exists only in the current Live ISO session. It is expected to disappear after reboot; the installed system does not require it for normal startup.

7. Run the Final Gate and Start Installation

Verify the Live root, mounts, target link, network, and DNS one final time:

findmnt -n -o SOURCE,FSTYPE,TARGET /
findmnt -rn -o SOURCE,TARGET | grep -E '^/dev/(sd|mapper/)' || \
  echo NO_PHYSICAL_DISK_MOUNTS
readlink -f /dev/elemental-install-target
test -b /dev/elemental-install-target
ip -br addr
ip route show default
getent hosts <global-domain>

Start the installer only after every check passes:

systemctl unmask elemental-register-install.service
systemctl reset-failed elemental-register-install.service
systemctl start elemental-register-install.service
journalctl -fu elemental-register-install.service

In the log, confirm that registration succeeds, /dev/elemental-install-target resolves to the intended WWN disk, partitioning and installation complete, and the configured eject/reboot action runs.

Verify the Installed Host

After installation triggers a reboot:

  1. Eject the BMC virtual media and restore normal disk-first boot order.

  2. Confirm that the host does not return to the Live ISO.

  3. Verify the new MachineInventory on the Global cluster:

    kubectl -n cpaas-system get machineinventories.elemental.cattle.io -o wide
    kubectl -n cpaas-system describe machineinventory <inventory-name>
  4. Confirm that the inventory is Ready=True, reports the expected network, and has only one current Elemental disk layout.

  5. Add the inventory to a MachineInventoryPool only after it is ready.

  6. After Cluster API allocates the host, verify the BaremetalMachine, workload Node, control-plane components, and CNI as described in Creating Clusters on Bare Metal.

Troubleshooting

SymptomCause and action
The install service fails before you select a disk.This is the expected fail-closed behavior while /dev/elemental-install-target is absent. Stop and mask the service, complete the checks, create the link, then reset and start the service.
test -b /dev/elemental-install-target fails.The WWN path is wrong, missing, or does not resolve to a whole block device. Recheck lsblk and /dev/disk/by-id; do not start installation.
More than one disk still has COS_STATE or COS_PERSISTENT.A previous Elemental layout remains. Stop installation and clean every approved reinstall disk until wipefs, blkid, and lsblk all pass.
The same physical disk has a different /dev/sdX name after reboot.This is expected on some storage controllers. Compare WWN, serial number, size, and controller address instead of the kernel name.
The MachineRegistration was patched, but the ISO still uses the old target.Rebuild the SeedImage and download the newly generated ISO. MachineRegistration changes are not applied retroactively to an existing ISO.
Registration works in the Live ISO, but the installed host has no network after reprovision.Diagnose installed-system cloud-init and NetworkManager activation separately. The Live ISO nmcli profile is temporary and does not prove that persistent reprovision networking succeeded.

Limitations

  • This workflow intentionally requires one console action per host. It prevents automatic selection; it does not provide fully unattended heterogeneous disk selection.
  • MachineRegistration metadata labels are not interpolated into install.device.
  • A device-selector based only on disk size is safe only if exactly one disk can match, and current selection does not enforce uniqueness. The WWN gate is preferred for hosts with multiple equal-sized disks.
  • The target must be a whole disk. Do not point the gate at a partition.