CAPI-based MachinePool Lifecycle
This page describes MachinePool lifecycle management for Cluster API (CAPI) based cluster setups. The generic drain primitive it relies on the taint-based eviction that works independently of CAPI and is documented in Machine Eviction.
A CAPI compute node backs an IronCore MachinePool, and the IronCore VMs of that pool run on it. So when CAPI replaces or deletes such a node for instance during a rolling upgrade or scale-down, deleting it while those VMs are still running would drop their workloads. This controller holds the node deletion until the pool has been drained.
It builds directly on the Machine Eviction mechanism: draining is performed by tainting the MachinePool with a NoExecute maintenance taint and waiting for the eviction to complete.
The controller reconciles the external CAPI Machine together with IronCore MachinePool/Machine.
A CAPI Machine is linked to the MachinePool it backs through its status.nodeRef.name, which matches the MachinePool name.
The Pre-Drain Hook
CAPI supports pre-drain lifecycle hooks: an annotation on a CAPI Machine that pauses deletion before the node is drained until the annotation is removed. The controller uses this to interpose IronCore eviction.
For every CAPI Machine matching the configured selector, the controller ensures two things while the machine is alive:
metadata:
finalizers:
- maintenance.ironcore.dev/machinepool-cleanup
annotations:
pre-drain.delete.hook.machine.cluster.x-k8s.io/ironcore-maintenance: ironcore-maintenance- The finalizer keeps the controller in the loop when the CAPI
Machineis deleted, so it can run its cleanup before the object disappears. - The pre-drain hook blocks CAPI from draining and removing the node until the controller clears it.
Which CAPI Machines are managed is restricted by the --capi-machine-selector label selector (empty selects all).
Lifecycle Flow
When CAPI decides to delete a Machine (setting its deletionTimestamp), it stalls at the pre-drain hook and the controller takes over:
The controller resolves the
MachinePoolfrom the CAPIMachine'sstatus.nodeRef.name.It ensures the maintenance taints on that
MachinePool, adding both effects under the keymaintenance.ironcore.dev:yamlspec: taints: - key: maintenance.ironcore.dev effect: NoSchedule - key: maintenance.ironcore.dev effect: NoExecuteNoSchedulestops new machines from landing on the pool while it is draining;NoExecutetriggers eviction of every boundMachinethat does not tolerate the taint.It checks whether any non-tolerating
Machines are still bound to the pool. As long as some remain, it holds the pre-drain hook and requeues. The node stays up while VMs shut down gracefully.Once the pool is drained (only tolerating machines, if any, remain), the controller removes the pre-drain hook, allowing CAPI to drain the Kubernetes node and delete it.
After CAPI has removed its own
Machinefinalizer, the controller deletes the now-emptyMachinePoolobject.Finally, it removes its own finalizer from the CAPI
Machine, letting the object be garbage collected.
If a CAPI Machine has no status.nodeRef (it never became a node), there is nothing to drain: the controller simply clears the pre-drain hook and its finalizer.
Relationship to Eviction and Health
This controller is the automation layer that turns an infrastructure-level node deletion into an ordered IronCore drain. It leans on two lower-level mechanisms:
- Machine Eviction provides the
NoExecutetaint semantics and the per-Machinegraceful shutdown that the controller drives. - MachinePool Health provides the pool status the broader system relies on; note that this controller reacts to planned CAPI node deletions, not to a pool becoming unhealthy on its own.