fix(talos): install from the Image Factory metal installer #614

Merged
k.renner merged 1 commits from talos-factory-installer into master 2026-08-26 04:36:58 +00:00
Member

machine.install.image was never set, so every node installed from the stock ghcr.io/siderolabs/installer that talosctl gen config defaults to. Extensions live in the installer image, which makes the schematic a property of the boot media alone — nothing lands on disk.

Measured on all three nodes:

$ talosctl -n k8s-1,k8s-2,k8s-3 get extensions
NODE   NAMESPACE   TYPE   ID   VERSION   NAME   VERSION
(empty)

What is missing

The cold-rebuild runbook already explains why each was chosen for bare metal:

extension why it matters here
siderolabs/intel-ucode CPU microcode. On a VM the hypervisor supplied it; on bare metal nothing does except the BIOS.
siderolabs/thunderbolt Inert until machine.kernel.modules asks for it. Present so enabling the MS-01 mesh later needs neither a new image nor a reinstall — precisely the property that installing without it destroys.

The Thunderbolt one is the sharper loss: its whole purpose was to keep that option open without a reinstall, and right now taking it would require exactly that.

The change

install:
  image: factory.talos.dev/metal-installer/a21cec8f…:v1.12.6

Set in the shared cluster.yaml patch rather than per node — all three are bare metal now and want the same image. Schematic a21cec8f is the bare-metal one from RUNBOOK-cold-rebuild.md: same net.ifnames=1 as the Proxmox schematic (the predictable interface names the per-node VLAN parents match against), minus qemu-guest-agent.

metal-installer rather than installer is the v1.12 path for bare metal — verified against the Talos docs, and the schematic contents verified against the Factory API rather than assumed.

Verified the merged config still generates and validates:

$ talosctl validate --config <generated> --mode metal
... is valid for metal mode

Applying it is a separate job

install.image is read only at install and upgrade time. Merging changes nothing on a running node — the three stay without extensions until a deliberate rolling talosctl upgrade, which wants drain + HEALTH_OK between nodes and should not be run unattended. Filing the config fix now so the next upgrade picks it up correctly.

Also note the tag must track the Talos version; leaving it behind turns an upgrade into a downgrade.

`machine.install.image` was never set, so every node installed from the stock `ghcr.io/siderolabs/installer` that `talosctl gen config` defaults to. **Extensions live in the installer image**, which makes the schematic a property of the boot media alone — nothing lands on disk. Measured on all three nodes: ``` $ talosctl -n k8s-1,k8s-2,k8s-3 get extensions NODE NAMESPACE TYPE ID VERSION NAME VERSION (empty) ``` ## What is missing The cold-rebuild runbook already explains why each was chosen for bare metal: | extension | why it matters here | | --- | --- | | `siderolabs/intel-ucode` | CPU microcode. On a VM the hypervisor supplied it; on bare metal nothing does except the BIOS. | | `siderolabs/thunderbolt` | Inert until `machine.kernel.modules` asks for it. Present so enabling the MS-01 mesh later needs **neither a new image nor a reinstall** — precisely the property that installing without it destroys. | The Thunderbolt one is the sharper loss: its whole purpose was to keep that option open without a reinstall, and right now taking it would require exactly that. ## The change ```yaml install: image: factory.talos.dev/metal-installer/a21cec8f…:v1.12.6 ``` Set in the shared `cluster.yaml` patch rather than per node — all three are bare metal now and want the same image. Schematic `a21cec8f` is the bare-metal one from `RUNBOOK-cold-rebuild.md`: same `net.ifnames=1` as the Proxmox schematic (the predictable interface names the per-node VLAN parents match against), minus `qemu-guest-agent`. `metal-installer` rather than `installer` is the v1.12 path for bare metal — verified against the Talos docs, and the schematic contents verified against the Factory API rather than assumed. Verified the merged config still generates and validates: ``` $ talosctl validate --config <generated> --mode metal ... is valid for metal mode ``` ## Applying it is a separate job `install.image` is read only at install and upgrade time. **Merging changes nothing on a running node** — the three stay without extensions until a deliberate rolling `talosctl upgrade`, which wants drain + `HEALTH_OK` between nodes and should not be run unattended. Filing the config fix now so the next upgrade picks it up correctly. Also note the tag must track the Talos version; leaving it behind turns an upgrade into a downgrade.
claude-bot added 1 commit 2026-08-26 00:41:28 +00:00
fix(talos): install from the Image Factory metal installer
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was successful
f84df3b188
machine.install.image was never set, so every node installed from the stock
ghcr.io/siderolabs/installer that talosctl gen config defaults to. Extensions
live in the installer image, which makes the schematic a property of the boot
media alone — nothing lands on disk. talosctl get extensions returns empty on
all three nodes.

Two extensions are missing as a result, and the cold-rebuild runbook explains
why each was chosen for bare metal:

  siderolabs/intel-ucode   CPU microcode. On a VM the hypervisor supplied it;
                           on bare metal nothing does except the BIOS.
  siderolabs/thunderbolt   Inert until machine.kernel.modules asks for it.
                           Present so enabling the MS-01 mesh later needs
                           neither a new image nor a reinstall — precisely the
                           property installing without it destroys.

Set in the shared cluster patch rather than per node: all three are bare metal
now and want the same image. Schematic a21cec8f is the bare-metal one from
RUNBOOK-cold-rebuild.md — same net.ifnames=1 as the Proxmox schematic, minus
qemu-guest-agent.

Config-only. install.image is read at install and upgrade time, so no running
node changes until it is upgraded; the three nodes stay without extensions
until a deliberate rolling upgrade is scheduled.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
review-bot left a comment
Member

🤖 Automated review — model claude-sonnet-5 (complexity: normal), commit f84df3b1884525daaf3ea541118665da7b225894.

Advisory review by the review-bot pipeline. It never approves; a human merges. Push new commits to get a fresh review.


Summary

Adds machine.install.image to the shared kubernetes/talos/patches/cluster.yaml patch so all three bare-metal nodes install from the Image Factory metal-installer schematic (with intel-ucode and thunderbolt extensions) instead of the stock siderolabs/installer. I checked the schematic ID and Talos version against kubernetes/RUNBOOK-cold-rebuild.md:90 and both match exactly, verified none of the per-node patches (k8s-1.yaml, k8s-2.yaml, k8s-3.yaml) set install.image (so there's no override conflict), and confirmed the patch application order in kubernetes/bootstrap.sh:125-128 applies cluster.yaml before the per-node patches, consistent with the stated intent. No blocking issues.

🟡 Suggestions

  • The schematic contents themselves (that a21cec8f… actually bundles intel-ucode + thunderbolt + net.ifnames=1 and omits qemu-guest-agent) can't be verified from this checkout — that requires querying factory.talos.dev, which I don't have network access to in this review. The ID matches RUNBOOK-cold-rebuild.md:90 verbatim, so this is at worst a repeat of whatever was verified when that runbook was written, not a new risk introduced by this PR.
  • The version tag (v1.12.6) matches the value already pinned in .woodpecker/deploy-infrastructure.yml:140, so there's no drift today, but as the PR body itself notes, this and that file (plus the Proxmox schematic reference at the same line) now have to be bumped together on every Talos upgrade. Worth a one-line pointer between them (or a shared variable) if a future PR touches this again, so the two don't silently diverge — not something to hold this PR for.

Tests

This is a Talos machine-config patch; the repo has no automated validation of it in CI (.woodpecker/deploy-infrastructure.yml doesn't run talosctl validate against these patches). The PR body reports a manual talosctl validate --mode metal run against the merged config, which is the standard/only verification path this repo uses for this kind of change, and is consistent with how the sibling per-node patches are described. The PR body is also explicit that merging this alone changes nothing on the running nodes until a deliberate rolling upgrade — correctly reflected in the new inline comment (cluster.yaml:28-30) and accurate given install.image is only consulted at install/upgrade time.

Recommendation

Looks reasonable — no blocking issues; comments above are optional.

🤖 **Automated review** — model `claude-sonnet-5` (complexity: normal), commit `f84df3b1884525daaf3ea541118665da7b225894`. > Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review. --- ## Summary Adds `machine.install.image` to the shared `kubernetes/talos/patches/cluster.yaml` patch so all three bare-metal nodes install from the Image Factory `metal-installer` schematic (with `intel-ucode` and `thunderbolt` extensions) instead of the stock `siderolabs/installer`. I checked the schematic ID and Talos version against `kubernetes/RUNBOOK-cold-rebuild.md:90` and both match exactly, verified none of the per-node patches (`k8s-1.yaml`, `k8s-2.yaml`, `k8s-3.yaml`) set `install.image` (so there's no override conflict), and confirmed the patch application order in `kubernetes/bootstrap.sh:125-128` applies `cluster.yaml` before the per-node patches, consistent with the stated intent. No blocking issues. ## 🟡 Suggestions - The schematic contents themselves (that `a21cec8f…` actually bundles `intel-ucode` + `thunderbolt` + `net.ifnames=1` and omits `qemu-guest-agent`) can't be verified from this checkout — that requires querying `factory.talos.dev`, which I don't have network access to in this review. The ID matches `RUNBOOK-cold-rebuild.md:90` verbatim, so this is at worst a repeat of whatever was verified when that runbook was written, not a new risk introduced by this PR. - The version tag (`v1.12.6`) matches the value already pinned in `.woodpecker/deploy-infrastructure.yml:140`, so there's no drift today, but as the PR body itself notes, this and that file (plus the Proxmox schematic reference at the same line) now have to be bumped together on every Talos upgrade. Worth a one-line pointer between them (or a shared variable) if a future PR touches this again, so the two don't silently diverge — not something to hold this PR for. ## Tests This is a Talos machine-config patch; the repo has no automated validation of it in CI (`.woodpecker/deploy-infrastructure.yml` doesn't run `talosctl validate` against these patches). The PR body reports a manual `talosctl validate --mode metal` run against the merged config, which is the standard/only verification path this repo uses for this kind of change, and is consistent with how the sibling per-node patches are described. The PR body is also explicit that merging this alone changes nothing on the running nodes until a deliberate rolling upgrade — correctly reflected in the new inline comment (`cluster.yaml:28-30`) and accurate given `install.image` is only consulted at install/upgrade time. ## Recommendation Looks reasonable — no blocking issues; comments above are optional. <!-- pr-review:sha=f84df3b1884525daaf3ea541118665da7b225894 -->
k.renner merged commit e33b0f584a into master 2026-08-26 04:36:58 +00:00
Sign in to join this conversation.