Skip to content

MachineClaim: allocate N Machines by label selector (split inventory from intent) #12

Description

@tjjh89017

Machine currently carries two different things in one object:

  • Physical identity / inventorybmc.address, bootMACAddress, networkSite
  • Deployment intentimageRef, dataImages, postHookRefs, params, afterDeploy, ezio tuning

That works for the naming-a-specific-machine workflow ("install this image on these three hosts"), which is the current use case. It does not express the fleet workflow: "deploy this image to 20 machines at site A, I do not care which 20."

The state machine already anticipates the split

Enrolling -> Inspecting -> Available -> Provisioning -> Provisioned already has an Available state, whose meaning is "inspected, idle, ready to be given work" — a purely inventory notion. What actually moves a Machine out of it today is a user editing spec.imageRef (the spec-vs-status diff that triggers provisioning). So the inventory semantics are half-built: the state exists, but nothing allocates into it.

Shape and name

A MachineClaim holding the intent plus a count and a selector, matched against Available Machines by a binding controller. The closest in-tree analogue is PersistentVolume / PersistentVolumeClaim: admin-provided inventory, a claim describing what is wanted, and a controller that binds them.

Named MachineClaim, not MachineRequest. "Claim" is the term Kubernetes already uses for this exact relationship — a PersistentVolumeClaim holds a volume until released, and DRA's ResourceClaim is the current core API for "allocate devices matching criteria". "Request" reads as a one-shot imperative ask; "claim" carries the binding-and-holding semantics that are actually wanted here, so the lifecycle (bound, released, re-bindable) is legible from the name alone. Metal3 (BareMetalHost consumed by a CAPI Machine) and Ironic (its Allocation resource with resource_class / traits) are the same pattern in this problem domain, so the operator's mental model transfers.

On a split, imageRef, dataImages, postHookRefs, params, afterDeploy and the ezio tuning move to the claim; Machine keeps physical identity, status, and a binding reference recording which claim holds it.

Selection: labels only, at least initially

Match on Machine labels with a standard label selector, and let users apply the labels themselves. Hardware-fact matching is explicitly not the starting point: status.hardware only exists after the agent registers (the machine must boot and be inspected first), and today it carries just disks, NICs and a CPU count — too thin to select on usefully. Operator-applied labels (site=a, role=worker, ram=64g) need no new fact model and no inspection dependency, and they let the user encode whatever distinctions actually matter in their environment. Richer fact-based selection can come later if labels prove insufficient.

Semantics to settle before building

  • Binding under contention — two claims wanting the same Machine. Needs a claim reference on the Machine written with optimistic concurrency, in the PV/PVC style.
  • Release — after a deploy completes, does the Machine return to Available, or stay held by the claim until it is deleted?
  • Insufficient capacity — fewer matching Machines than claimed: wait, fail, or partially satisfy and keep trying?
  • Re-provisioning — under the current model this is editing spec.imageRef; with a claim layer, what does changing a bound request's image mean for machines already provisioned by it?

Scope note

Not planned for now. The current named-machine flow covers the immediate use case, and this adds a controller with real allocation semantics. It is recorded because the split point is already clear and because the existing state machine was built in a way that leaves room for it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions