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. - Any inventory with non-empty
spec.storage.volumes[]must already reportstatus.storage.phase=PreparedandStoragePrepared=Truebefore it can count asAvailable. Follow Manage Data Disks on Bare-Metal Hosts before adding a newly registered storage-managed inventory to the worker pool.
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.
Managed data disks are not part of BaremetalMachineTemplate. Their declaration and retained data belong to each long-lived MachineInventory, so two members of the same worker pool may expose different host-local datasets unless operators standardize and verify their storage declarations.
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), prepare any managed storage while each inventory is still unallocated, and then add their 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
imagePullCredentialsVerificationPolicy: NeverVerify is required only starting with Kubernetes 1.35. Omit this parameter when creating workers with Kubernetes 1.34 or earlier.
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), prepare any managed storage, 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. Inventories with managed volumes must also be Prepared; otherwise they increasestatus.totalbut remain unavailable for allocation. Save and exit, then confirm the expected increase instatus.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, deactivates declared storage mounts, clears CRI workload, and stops containerd. It does not wipe managed filesystems, Kubernetes persistent directories, or reset the OS — OS cleanup 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 again. Deleting a Machine performs Deactivate, not storage Release, so the storage declaration, filesystem UUIDs, and data remain on that inventory.
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. If it declares managed volumes, it must return tostatus.storage.phase=PreparedwithStorageActive=False/Inactive; its business mount paths must be inactive while filesystem UUIDs and data remain unchanged.
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. Host-local managed data does not follow the replacement Machine. If the application must reuse a specific inventory's data, use a dedicated or deliberately ordered pool and verify BaremetalMachine.status.machineInventoryRef before relying on that data.
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, or disk declaration on the template. Managed storage is changed separately on an unallocated, inactive MachineInventory; see Manage Data Disks on Bare-Metal Hosts. 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. For Kubernetes 1.35 or later, add the required kubelet patch settings to/etc/kubernetes/patches/kubeletconfiguration0+strategic.json. -
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 inventory's default plan secret also carries baremetal.alauda.io/plan.type. Normal node lifecycle uses clean or reprovision; inventory storage reconciliation additionally uses storage-prepare and storage-release. Inspect MachineInventory.status.storage.conditions and .operation together with the plan type when diagnosing storage.
Common Failure Modes
For the full operator-side state machine reference, see Provider Overview → BaremetalMachine.