From b79687515b6fa3a9b3edbe4a0c120e491cb7435f Mon Sep 17 00:00:00 2001 From: Gang Wang Date: Fri, 14 Aug 2026 15:13:18 +0800 Subject: [PATCH] docs: add multi-disk bare-metal install guide --- docs/en/create-cluster/bare-metal.mdx | 5 +- ...onfigure-fixed-install-disk-bare-metal.mdx | 350 ++++++++++++++++++ 2 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 docs/en/how-to/configure-fixed-install-disk-bare-metal.mdx diff --git a/docs/en/create-cluster/bare-metal.mdx b/docs/en/create-cluster/bare-metal.mdx index 7a606134..cd45bd3e 100644 --- a/docs/en/create-cluster/bare-metal.mdx +++ b/docs/en/create-cluster/bare-metal.mdx @@ -75,6 +75,7 @@ Prepare **every** disk and virtual disk (VD) on each host before you boot the `S - Wipe all disks so that no bootable previous operating system remains. The host must boot the ISO, not an old on-disk OS. - Remove residual Elemental partition labels — `COS_STATE`, `COS_PERSISTENT`, `COS_OEM`, `COS_RECOVERY` — from **all** disks, not only the intended install disk. Elemental resolves partitions by label (`blkid -L COS_STATE`); a stale label left on a second disk (for example from a previous install or a leftover multipath member) makes it resolve the wrong device and the reprovision snapshotter fails. - On hosts where the same disk can appear through more than one path (multipath), make sure none of those paths exposes a disk that still carries a `COS_*` label; a residual label on any path can be resolved ahead of the intended install disk. Clean the disk rather than disabling multipath — the image keeps it enabled for network-attached storage boot. +- On a host with multiple disks, do not leave `install.device` empty and do not use `/dev/sda` as a persistent identity. Follow [Select a Fixed System Disk on Multi-Disk Bare-Metal Hosts](../how-to/configure-fixed-install-disk-bare-metal.mdx) to reuse one ISO while selecting each host's system disk by WWN. - Set the boot order so the host boots the virtual CD / ISO first. --- @@ -114,7 +115,7 @@ The example manifests below use `` syntax for environment-specific | `` | Same ConfigMap entry, with `-iso` appended to the repository. Tag/digest matches the catalog value. | See the [SeedImage step](#step-1-machineregistration-seedimage). | | `` | Platform registry (same value as `global.registry.address` on the install chart). | `kubectl get cluster global -n cpaas-system -o jsonpath='{.metadata.annotations.cpaas\.io/registry-address}'` (when one exists). | | `` / `` / `` | Operator-supplied. The VIP must be free in the control-plane Layer-2 domain; `` must be unique in that domain. | n/a | -| `` | Target disk for `elemental install`, such as `/dev/vda`, `/dev/sda`, or `/dev/nvme0n1`. | Confirm from the host console or inventory hardware data. Do not leave this implicit in virtualized tests. | +| `` | Whole-disk target for `elemental install`. A direct kernel path is suitable only when its identity is stable and unambiguous. For multi-disk bare-metal hosts that reuse one ISO, use `/dev/elemental-install-target`. | Confirm the disk by WWN from the host console. See [Select a Fixed System Disk on Multi-Disk Bare-Metal Hosts](../how-to/configure-fixed-install-disk-bare-metal.mdx). | | `` / `` | Component versions baked into the bare-metal base image for ``. | See [OS Support Matrix](../overview/os-support-matrix.mdx). | | `` | The `acp/chart-cpaas-kube-ovn` chart version matching the selected ACP and Kubernetes release. | Use the **kube-ovn (chart)** value from the [OS Support Matrix](../overview/os-support-matrix.mdx), not the Kube-OVN component version. | | `` | Operator-supplied when the first-boot registration path needs an explicit resolver. | Prefer `MachineRegistration.config.cloud-config` or later kubeadm cloud-init. Do not write `/etc/resolv.conf` from `SeedImage.cloud-config`. | @@ -191,7 +192,7 @@ spec: Do not add `/etc/resolv.conf` to `SeedImage.spec.cloud-config`. Keep the ISO generic, and put site-specific resolver configuration in `MachineRegistration.spec.config.cloud-config` only when the first-boot registration path needs it. During the tested Global deployment flow, the ISO did not carry resolver files; node DNS was configured later by the kubeadm bootstrap data. -`install.device`, `install.eject-cd`, and `install.reboot` are intentional. If the target disk is omitted, `elemental install` can select the live ISO device in VM-based tests. If `eject-cd` or `reboot` is false, a host can remain in the live environment after the first install and never become usable inventory for Cluster API. +`install.device`, `install.eject-cd`, and `install.reboot` are intentional. If the target disk is omitted, `elemental install` can select an unintended device. On multi-disk physical hosts, use the [fixed system disk workflow](../how-to/configure-fixed-install-disk-bare-metal.mdx) instead of a changing `/dev/sdX` name. If `eject-cd` or `reboot` is false, a host can remain in the live environment after the first install and never become usable inventory for Cluster API. Apply the manifest and wait for the SeedImage build to finish: diff --git a/docs/en/how-to/configure-fixed-install-disk-bare-metal.mdx b/docs/en/how-to/configure-fixed-install-disk-bare-metal.mdx new file mode 100644 index 00000000..8da083f1 --- /dev/null +++ b/docs/en/how-to/configure-fixed-install-disk-bare-metal.mdx @@ -0,0 +1,350 @@ +--- +weight: 28 +title: Select a Fixed System Disk on Multi-Disk Bare-Metal Hosts +queries: + - select fixed install disk bare metal + - elemental install device multiple disks + - reuse seedimage iso different system disks + - pin bare metal system disk by wwn + - clean stale elemental cos labels +--- + +# 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](../create-cluster/bare-metal.mdx) 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. + +```yaml title="MachineRegistration install settings" +apiVersion: elemental.cattle.io/v1beta1 +kind: MachineRegistration +metadata: + name: -registration + namespace: cpaas-system +spec: + machineName: "-${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: + +```bash +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: + +```bash +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 + +```bash +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: + +```bash +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`. + +```bash +nmcli device status +nmcli connection show +ip -br link +``` + +Configure the selected connection with the values assigned to this host: + +```bash +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: + +```bash +ip -br addr +ip route +cat /etc/resolv.conf +ping -c 2 -W 2 192.168.254.1 +getent hosts +curl -ksS --connect-timeout 10 \ + -o /dev/null -w 'REG_HTTP=%{http_code}\n' \ + 'https:///' +``` + +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: + +```bash +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: + +```bash +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. + +```bash +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: + +```bash +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: + +```bash +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: + +```bash +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: + +```bash +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: + +```bash +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 +``` + +Start the installer only after every check passes: + +```bash +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: + + ```bash + kubectl -n cpaas-system get machineinventories.elemental.cattle.io -o wide + kubectl -n cpaas-system describe machineinventory + ``` + +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](../create-cluster/bare-metal.mdx). + +## Troubleshooting + +| Symptom | Cause 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.