Managing Nodes on Bare Metal
This document explains how to deploy worker nodes, scale them up and down, replace specific machines, and recover failed nodes on the bare-metal provider. Node management uses Cluster API Machine resources orchestrated through MachineDeployment; the provider binds each Machine to one MachineInventory from a pool and drives the host through clean / reprovision plans.
TOC
PrerequisitesOverviewWorker Node DeploymentStep 1: Confirm the Worker Pool CapacityStep 2: Configure the WorkerBaremetalMachineTemplateStep 3: Configure the Bootstrap TemplateStep 4: Configure the MachineDeploymentNode Management OperationsScaling Worker NodesAdding Worker NodesRemoving Worker NodesReplacing a Single Failed NodeUpgrading Machine InfrastructureUpdating Bootstrap TemplatesUpgrading Kubernetes VersionPool and Inventory ObservabilityCommon Failure ModesNext StepsPrerequisites
Important Prerequisites
- The control plane must already be running. See Create Cluster.
- The worker
MachineInventoryPoolmust contain at least as manyAvailableinventories as the target replica count, plus the headroom required by the rollout strategy. - The target
Machine.spec.versionmust be a key in theelemental-image-catalogConfigMap.
Configuration Guidelines
When working with the configurations in this document:
- Only modify values enclosed in
<>brackets. - Replace placeholder values with your environment-specific settings.
- Preserve all other default configurations unless explicitly required.
Overview
The four resources that compose a worker node group:
MachineInventoryPool(<cluster-name>-worker-pool) — the allowed set ofMachineInventorynames. Already created in Create Cluster → Step 2.BaremetalMachineTemplate(<cluster-name>-worker-template) — points at the worker pool. CAPI requires that this template be replaced (newmetadata.name) every time the underlying pool reference or allocation policy changes.KubeadmConfigTemplate(<cluster-name>-worker-bootstrap) — cloud-inituser-dataforkubeadm join. The bare-metal provider normalizes this user-data at reprovision time (hostname,provider-id,criSocket); operators should not pre-fill those fields.MachineDeployment— controls replica count, version, rollout strategy.
The Cluster API contract for templates: the running Machine set keeps an in-memory snapshot of the previous template, so editing a template in place does not trigger a rollout. Worker upgrades create a new BaremetalMachineTemplate and patch MachineDeployment.spec.template.spec.infrastructureRef.name to point at it.
Worker Node Deployment
Step 1: Confirm the Worker Pool Capacity
status.available must be at least the target replica count. If you need additional capacity, register more hosts (boot the SeedImage ISO on them — see Create Cluster → Step 1) and add their MachineInventory names to spec.machineInventories.
Step 2: Configure the Worker BaremetalMachineTemplate
Key parameters:
allocationPolicy is reserved for future expansion. The provider currently treats every pool as Ordered — it picks the first Available inventory in declaration order.
Step 3: Configure the Bootstrap Template
The provider applies a minimal normalization to bootstrap user-data before writing it into the reprovision plan, so leave the following fields out of the template:
- Hostname / FQDN — set automatically from
MachineInventoryPool.spec.machineInventories[].hostname(or the inventory name when omitted). kubeletExtraArgs.provider-id— set automatically tobaremetal:///<inventory-name>.nodeRegistration.criSocket— set automatically tounix:///var/run/containerd/containerd.sockwhen unset.
The normalized user-data is also written back into the bootstrap secret under data["resolved-value"] for debugging; the original data["value"] is left untouched.
Step 4: Configure the MachineDeployment
Key parameters:
Apply and watch:
Node Management Operations
Scaling Worker Nodes
Adding Worker Nodes
Use Case: Increase cluster capacity.
Prerequisites:
- The worker pool has enough
Availableinventories. If not, register the additional hosts (boot the SeedImage ISO and confirm the newMachineInventoryobjects) and append them toMachineInventoryPool.spec.machineInventories[].
Procedure:
-
Check current state
Confirm that
MachineInventoryPool.status.availableis high enough for the planned increment. -
Extend the worker pool when more inventories are needed
Append the new
MachineInventorynames — they must already be registered and Ready. Save and exit; the pool reconciler picks up the change and increasesstatus.totalandstatus.available. -
Scale up the
MachineDeployment -
Monitor
New
BaremetalMachineobjects advancePending → Allocated → Reprovisioning → Running; the pool'savailablecounter decreases as new nodes are bound.
Removing Worker Nodes
Two strategies are supported, identical in shape to the upstream Cluster API contract:
Inventory recycling
A clean plan stops kubelet, clears CRI workload, and stops containerd. It does not wipe Kubernetes persistent directories or reset the OS — that work happens later, when the same or a different inventory is picked for a new BaremetalMachine and runs the reprovision plan. Until then, the inventory returns to Available and may be allocated to another cluster.
Random Removal
CAPI selects machines for deletion in its standard order. Each selected BaremetalMachine moves to Preparing, the provider writes a clean plan, and once the plan reports Applied, the inventory returns to Available.
Targeted Removal
-
Identify the machines
-
Annotate the target machines
Repeat for every machine you want to remove.
-
Scale down by exactly the number of annotated machines
Reducing by fewer leaves annotated machines in place; reducing by more sends random machines through the
cleanplan as well. -
Verify cleanup
The released inventory must show
baremetal.alauda.io/allocation-state=Available, thebaremetal.alauda.io/owner-*annotations must be cleared, and the pool annotation must remain.MachineInventoryitself is not deleted.
Replacing a Single Failed Node
If a BaremetalMachine lands in Failed, the safest recovery is to delete the failed Machine. CAPI immediately creates a replacement Machine (because replicas did not change), and the bare-metal provider picks an Available inventory from the same pool. Most often the replacement is a different MachineInventory; the provider does not guarantee that the freshly released inventory will be re-picked.
Investigate the original failure separately: read BaremetalMachine.status.conditions, MachineInventory.status.plan.state, and the failing plan secret's failed-output key on the host that ran the plan. Common root causes are documented in the Common Failure Modes section below.
Upgrading Machine Infrastructure
BaremetalMachineTemplate carries only the pool reference and allocation policy — there is no CPU / memory / disk spec to revisit. Infrastructure-side changes that require a template swap are limited to:
- Moving a
MachineDeploymentto a different pool. - Adjusting allocation policy (when more policies are added).
To swap templates safely:
-
Create a new
BaremetalMachineTemplatewith a newmetadata.namereferencing the new pool. -
Apply the new template.
-
Patch the
MachineDeployment: -
Watch the rolling replacement complete (
maxSurge=0, one node at a time).
Updating Bootstrap Templates
KubeadmConfigTemplate is an immutable template in the same sense as BaremetalMachineTemplate. Modifying an existing template in place does not roll out existing machines; only newly created machines pick up the changes.
To roll out a bootstrap change:
-
Export the existing template:
-
Change
metadata.name, remove server-generated fields (resourceVersion,uid,creationTimestamp,managedFields,kubectl.kubernetes.io/last-applied-configuration) and the entirestatus, and edit the desired fields. -
Apply the new template:
-
Patch the
MachineDeploymentto reference the new template:This triggers a rolling replacement.
Upgrading Kubernetes Version
For Kubernetes upgrades on bare-metal, see Upgrading Clusters on Bare Metal. The upgrade path always replaces nodes — there is no in-place kubeadm upgrade step.
Pool and Inventory Observability
The annotations the provider maintains on each MachineInventory are the authoritative source for "what is this host being used for right now":
Each BaremetalMachine.status.planSecretRef plan secret also carries baremetal.alauda.io/plan.type=clean|reprovision so you can distinguish which plan is currently being driven.
Common Failure Modes
For the full operator-side state machine reference, see Provider Overview → BaremetalMachine.