Skip to content
Merged
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
5 changes: 3 additions & 2 deletions docs/en/create-cluster/bare-metal.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,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.

---
Expand Down Expand Up @@ -117,7 +118,7 @@ The example manifests below use `<placeholder>` syntax for environment-specific
| `<control-plane-load-balancer-type>` | Operator decision. Use `Internal` for provider-managed Alive or `External` for an existing load balancer. | Review [Plan the Control Plane Endpoint](../how-to/control-plane-endpoint.mdx). |
| `<control-plane-vip>` / `<control-plane-port>` | Operator-supplied stable endpoint. For `Internal`, use an unused IPv4 VIP in the control-plane Layer-2 domain. For `External`, use the load balancer frontend address. | n/a |
| `<vrid>` | Operator-supplied VRID for `Internal` only. It must be unique in the control-plane Layer-2 domain. Remove the field for `External`. | n/a |
| `<install-device>` | 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. |
| `<install-device>` | 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). |
| `<dns-image-tag>` / `<etcd-image-tag>` | Component versions baked into the bare-metal base image for `<kubernetes-version>`. | See [OS Support Matrix](../overview/os-support-matrix.mdx). |
| `<kube-ovn-version>` | 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. |
| `<dns-server>` | Operator-supplied when the first-boot registration path needs an explicit resolver. | Prefer `MachineRegistration.config.cloud-config` or later `KubeadmControlPlane` bootstrap data (`format: cloud-config`). Do not write `/etc/resolv.conf` from `SeedImage.cloud-config`. |
Expand Down Expand Up @@ -194,7 +195,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:

Expand Down
350 changes: 350 additions & 0 deletions docs/en/how-to/configure-fixed-install-disk-bare-metal.mdx
Original file line number Diff line number Diff line change
@@ -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: <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:

```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 <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:

```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 <global-domain>
```

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 <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](../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.