API Reference¶
Every banlieue Custom Resource Definition, generated from the Rust types that are the schema's source of truth. Field descriptions are the rustdoc comments on those types.
banlieue.io
infrastructure.banlieue.io
- CloudHypervisorMachine
- CloudHypervisorMachineTemplate
- LibvirtMachine
- LibvirtMachineTemplate
- ProxmoxMachine
- ProxmoxMachineTemplate
- VSphereCluster
- VSphereMachine
- VSphereMachineTemplate
Provider¶
API: banlieue.io/v1alpha1 · Kind: Provider · Scope: Namespaced · Short names: prov
Provider — one backend instance registered with banlieue.
A Provider represents a single place VMs can run: one vCenter, one Proxmox
cluster, or one libvirt host. It carries the connection details and an
admin-curated declaration of the storage classes, network classes, and
features that backend exposes. Its controller logs in, verifies those
capabilities, and publishes the reachable status.failureDomains[].
Why create one
- Make a backend schedulable. A VirtualMachine can only be placed on a Provider — no Provider, nowhere to run.
- Declare capabilities explicitly.
spec.capabilitiesmaps abstract class names (the ones VMClass / VMImage request) to concrete backend targets (a datastore, a port group). That mapping is the contract the scheduler matches against — capabilities are declared, not guessed. - Model many backends, including duplicates. A cluster can hold many
Providers of the same class (
prod-vsphere,dr-vsphere) and mix classes freely.
The provider's controller talks to the backend; banlieue's main controller never does. Communication between them is CRD-only.
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| Class | string | .spec.providerClassRef.name |
0 |
| Endpoint | string | .spec.connection.endpoint |
1 |
| Ready | string | .status.conditions[?(@.type=='Ready')].status |
0 |
| Heartbeat | string | .status.workload.heartbeat |
0 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
attestation |
object | Attestation trust anchors for this backend's vTPMs (ADR-0049 Decision 10). Admin-supplied, never discovered: an anchor read off the hypervisor would let whoever controls the hypervisor choose the anchor that vouches for its own guests. Optional — a Provider that runs no tpmEnabled classes has no reason to set it. |
|
capabilities |
object | Admin-defined capability mappings. Every storage / network class that VMClass and VMImage may request MUST be listed here for this provider to be considered by the scheduler. | |
connection |
object | Yes | Connection details for the backend. |
failureDomainNameOverrides |
object[] | Explicit overrides for individual discovered failure domains' generated name. The auto-computed, collision-safe name (<provider>-<datacenter>-<cluster>, hashed when too long) is always the fallback for any (datacenter, cluster) pair with no matching entry here — this is opt-in, never required. See ADR-0023. |
|
paused |
boolean | Suspend reconciliation. Equivalent to setting the cluster.x-k8s.io/paused annotation but in-band. |
|
providerClassRef |
object | Yes | Reference to a ProviderClass that identifies the backend type. |
scheduling |
object | How the scheduler places VMs on this backend (ADR-0107). Optional: without it the defaults apply. | |
useContentLibrary |
boolean | vSphere only: import Url-kind VMImages through a vCenter Content Library rather than the default datastore-upload + MarkAsTemplate path. Defaults to false (no Content Library required), matching environments where CL is not enabled. Ignored by non-vSphere classes. See ADR-0020. |
.spec.attestation¶
Attestation trust anchors for this backend's vTPMs (ADR-0049
Decision 10). Admin-supplied, never discovered: an anchor read off
the hypervisor would let whoever controls the hypervisor choose the
anchor that vouches for its own guests. Optional — a Provider that
runs no tpmEnabled classes has no reason to set it.
| Field | Type | Required | Description |
|---|---|---|---|
ekTrustBundle |
object | Yes | PEM bundle of CA certificates trusted to issue this backend's vTPM endorsement-key certificates. Provenance differs per backend (ADR-0045): on vSphere the issuing CA is vCenter's; on libvirt it is each host's swtpm_localca issuer certificate, one entry per host. |
.spec.attestation.ekTrustBundle¶
PEM bundle of CA certificates trusted to issue this backend's vTPM
endorsement-key certificates. Provenance differs per backend
(ADR-0045): on vSphere the issuing CA is vCenter's; on libvirt it is
each host's swtpm_localca issuer certificate, one entry per host.
Same value-or-source shape as connection.caBundle: exactly one of
inline, configMapRef, secretRef must be set (see
[CABundleSource]); references resolve in the Provider's namespace.
Removal of an issuer from this bundle is the revocation mechanism on
libvirt — swtpm EK certificates never expire.
| Field | Type | Required | Description |
|---|---|---|---|
configMapRef |
object | Key in a ConfigMap in the referrer's namespace (key defaults to ca.crt). |
|
inline |
string | Inline PEM (one or more concatenated certificates). | |
secretRef |
object | Key in a Secret in the referrer's namespace (key defaults to ca.crt). |
.spec.attestation.ekTrustBundle.configMapRef¶
Key in a ConfigMap in the referrer's namespace (key defaults to ca.crt).
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Key within the object's data. Defaults are caller-defined. |
|
name |
string | Yes | Name of the ConfigMap / Secret in the referrer's namespace. |
.spec.attestation.ekTrustBundle.secretRef¶
Key in a Secret in the referrer's namespace (key defaults to ca.crt).
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Key within the object's data. Defaults are caller-defined. |
|
name |
string | Yes | Name of the ConfigMap / Secret in the referrer's namespace. |
.spec.capabilities¶
Admin-defined capability mappings. Every storage / network class that VMClass and VMImage may request MUST be listed here for this provider to be considered by the scheduler.
| Field | Type | Required | Description |
|---|---|---|---|
features |
string[] | Feature flags admin asserts are available. Provider's controller may downgrade these in status if introspection finds otherwise. Well-known values: hotAddCPU, hotAddMemory, efiSecureBoot, nestedVirtualization, gpuPassthrough. | |
networkClasses |
object[] | Network classes the admin asserts are available on this backend. | |
storageClasses |
object[] | Storage classes the admin asserts are available on this backend. Each entry maps an abstract class name to a provider-interpreted concrete target. |
.spec.capabilities.networkClasses[]¶
Network classes the admin asserts are available on this backend.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Abstract name referenced by VMClass.network.interfaces[].networkClass. |
perZone |
object[] | Per-(datacenter, cluster) overrides of target (ADR-0030). |
|
perZoneSubnet |
object[] | Per-(datacenter, cluster) overrides of subnet (ADR-0032). |
|
subnet |
object | Default subnet shape (gateway/nameservers/domain) for this network class, used in any zone per_zone_subnet does not cover. A port group implies a subnet, so this lives alongside target/per_zone rather than on VMClass — it lets a static-addressing VirtualMachine omit gateway/nameservers/domain entirely and have them resolved from whichever zone the scheduler picked (ADR-0032). |
|
target |
map[string]string | Default concrete target, used in any zone per_zone does not cover. None means this class resolves ONLY in the zones per_zone lists. Free-form per provider class. Examples: vsphere: { portGroup: "vmnet-prod" } { distributedPortGroup: "dvs-prod-vlan100" } proxmox: { bridge: "vmbr0", vlan: "100" } libvirt: { network: "br-prod" } |
.spec.capabilities.networkClasses[].perZone[]¶
Per-(datacenter, cluster) overrides of target (ADR-0030).
| Field | Type | Required | Description |
|---|---|---|---|
cluster |
string | Yes | Cluster name as vCenter reports it. |
datacenter |
string | Yes | Datacenter name as vCenter reports it. |
target |
map[string]string | Yes | Concrete backend target for this zone, same shape as [StorageClassMapping::target] / [NetworkClassMapping::target]. |
.spec.capabilities.networkClasses[].perZoneSubnet[]¶
Per-(datacenter, cluster) overrides of subnet (ADR-0032).
| Field | Type | Required | Description |
|---|---|---|---|
cluster |
string | Yes | Cluster name as vCenter reports it. |
datacenter |
string | Yes | Datacenter name as vCenter reports it. |
subnet |
object | Yes | Subnet shape for this zone. |
# .spec.capabilities.networkClasses[].perZoneSubnet[].subnet¶
Subnet shape for this zone.
| Field | Type | Required | Description |
|---|---|---|---|
domain |
string | ||
gateway |
string | ||
nameservers |
string[] |
.spec.capabilities.networkClasses[].subnet¶
Default subnet shape (gateway/nameservers/domain) for this network
class, used in any zone per_zone_subnet does not cover. A port
group implies a subnet, so this lives alongside target/per_zone
rather than on VMClass — it lets a static-addressing
VirtualMachine omit gateway/nameservers/domain entirely and have
them resolved from whichever zone the scheduler picked (ADR-0032).
| Field | Type | Required | Description |
|---|---|---|---|
domain |
string | ||
gateway |
string | ||
nameservers |
string[] |
.spec.capabilities.storageClasses[]¶
Storage classes the admin asserts are available on this backend. Each entry maps an abstract class name to a provider-interpreted concrete target.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Abstract name referenced by VMClass.hardware.disks[].storageClass. |
perZone |
object[] | Per-(datacenter, cluster) overrides of target (ADR-0030). |
|
target |
map[string]string | Default concrete target, used in any zone per_zone does not cover. None means this class resolves ONLY in the zones per_zone lists. Free-form per provider class; the provider's controller interprets it. Examples by provider class: vsphere: { datastore: "ds-fast-01" } { datastoreCluster: "dsc-gold" } { tagCategory: "tier", tag: "gold" } proxmox: { storage: "ceph-pool-1" } libvirt: { pool: "nvme-pool" } |
.spec.capabilities.storageClasses[].perZone[]¶
Per-(datacenter, cluster) overrides of target (ADR-0030).
| Field | Type | Required | Description |
|---|---|---|---|
cluster |
string | Yes | Cluster name as vCenter reports it. |
datacenter |
string | Yes | Datacenter name as vCenter reports it. |
target |
map[string]string | Yes | Concrete backend target for this zone, same shape as [StorageClassMapping::target] / [NetworkClassMapping::target]. |
.spec.connection¶
Connection details for the backend.
| Field | Type | Required | Description |
|---|---|---|---|
caBundle |
object | Optional CA bundle to validate the endpoint's TLS certificate. | |
credentialsRef |
object | Reference to a Secret in the Provider's namespace containing the credentials. Required keys depend on provider class: vsphere: username, password proxmox: username (the full API token id, user@realm!tokenid), tokenValue (API tokens only; password/ticket auth is not supported, ADR-0074) libvirt: tls.crt, tls.key (mutual TLS, ADR-0011) | |
endpoint |
string | Yes | Endpoint URL or URI. Format depends on provider class: vsphere: https://vcenter.example.com/sdk proxmox: https://pve.example.com:8006 libvirt: qemu+ssh://kvm-host.example.com/system |
insecureSkipTLSVerify |
boolean | Skip TLS verification. Applies to vsphere and proxmox. |
.spec.connection.caBundle¶
Optional CA bundle to validate the endpoint's TLS certificate.
A value-or-source: inline PEM, or a configMapRef / secretRef naming a
key (default ca.crt) in the Provider's namespace. Exactly one source
must be set; see [CABundleSource]. Resolved by the provider controller
and injected into the HTTP client (ADR-0008, BYOC). When unset, the
system trust roots are used.
| Field | Type | Required | Description |
|---|---|---|---|
configMapRef |
object | Key in a ConfigMap in the referrer's namespace (key defaults to ca.crt). |
|
inline |
string | Inline PEM (one or more concatenated certificates). | |
secretRef |
object | Key in a Secret in the referrer's namespace (key defaults to ca.crt). |
.spec.connection.caBundle.configMapRef¶
Key in a ConfigMap in the referrer's namespace (key defaults to ca.crt).
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Key within the object's data. Defaults are caller-defined. |
|
name |
string | Yes | Name of the ConfigMap / Secret in the referrer's namespace. |
.spec.connection.caBundle.secretRef¶
Key in a Secret in the referrer's namespace (key defaults to ca.crt).
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Key within the object's data. Defaults are caller-defined. |
|
name |
string | Yes | Name of the ConfigMap / Secret in the referrer's namespace. |
.spec.connection.credentialsRef¶
Reference to a Secret in the Provider's namespace containing the credentials. Required keys depend on provider class: vsphere: username, password proxmox: username (the full API token id, user@realm!tokenid), tokenValue (API tokens only; password/ticket auth is not supported, ADR-0074) libvirt: tls.crt, tls.key (mutual TLS, ADR-0011)
Required by every backend that authenticates to a remote endpoint, and
refused by cloud-hypervisor, whose provider runs on the hypervisor
host and must read no Secret at all (ADR-0060 Decision 4). When unset
the operator grants no Secret access whatsoever.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.spec.failureDomainNameOverrides[]¶
Explicit overrides for individual discovered failure domains'
generated name. The auto-computed, collision-safe name
(<provider>-<datacenter>-<cluster>, hashed when too long) is
always the fallback for any (datacenter, cluster) pair with no
matching entry here — this is opt-in, never required. See ADR-0023.
| Field | Type | Required | Description |
|---|---|---|---|
cluster |
string | Yes | Cluster name as vCenter reports it. |
datacenter |
string | Yes | Datacenter name as vCenter reports it (matches discover_inventory's walk, not an operator-chosen alias). |
name |
string | Yes | The name to use instead of the auto-computed one, e.g. cluster-01. Slugified the same way auto-computed names are, so Cluster 01 still produces a valid Kubernetes name. |
.spec.providerClassRef¶
Reference to a ProviderClass that identifies the backend type.
For v1alpha1 the ProviderClass CRD is deferred; treat this as a name
drawn from a well-known set: vsphere, proxmox, libvirt. A future
ProviderClass CRD will provide install metadata (image, RBAC) without
changing this reference.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.spec.scheduling¶
How the scheduler places VMs on this backend (ADR-0107). Optional: without it the defaults apply.
| Field | Type | Required | Description |
|---|---|---|---|
cpuOvercommitRatio |
integer | vCPUs the scheduler may place per CPU a failure domain publishes in attributes.capacity.cpus. 1 means no overcommit. CPU contention only slows guests, so the default allows 4; memory is never overcommitted. Unset: 4. |
.status¶
Observed state of a Provider: the failure domains its controller discovered and the health / reachability conditions.
| Field | Type | Required | Description |
|---|---|---|---|
conditions |
object[] | Standard Kubernetes conditions. The Ready condition reflects overall provider health. The ProviderReachable condition reflects connection state to the backend. |
|
ekCaCertificates |
string[] | PEM certificates of the CAs that issue this backend's vTPM endorsement key certificates: on a Cloud Hypervisor host, the host's own swtpm_localca (ADR-0065 Decision 6). A verifier trusts a guest's EK only through the host that created it; this is the input ekTrustBundle needs (ADR-0049). Empty when the backend offers no vTPM or publishes no anchor. |
|
failureDomains |
object[] | Failure domains ("availability zones" — the terms are synonyms; failureDomain was kept to align with CAPI v1beta2's own vocabulary) discovered by the provider's controller within this backend. The scheduler matches against labels and filters by attributes.availableStorageClasses / availableNetworkClasses. |
|
observedGeneration |
integer | The generation of the spec that the controller has reconciled. | |
workload |
object | The provider workload banlieue-operator created for this Provider. |
.status.conditions[]¶
Standard Kubernetes conditions. The Ready condition reflects overall
provider health. The ProviderReachable condition reflects connection
state to the backend.
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
.status.failureDomains[]¶
Failure domains ("availability zones" — the terms are synonyms;
failureDomain was kept to align with CAPI v1beta2's own vocabulary)
discovered by the provider's controller within this backend. The
scheduler matches against labels and filters by
attributes.availableStorageClasses / availableNetworkClasses.
| Field | Type | Required | Description |
|---|---|---|---|
attributes |
object | Attributes the provider's controller resolved for this domain, including the subset of admin-listed classes that are actually reachable from here. | |
labels |
map[string]string | Labels used by the scheduler's failureDomainSelector and by VirtualMachine anti-affinity topologyKey matching. Recommended keys: datacenter, cluster, rack, env. Every provider also sets name to this failure domain's own resolved name above (auto-computed, or an ADR-0023 override) — name above is a top-level field a LabelSelector cannot match directly, so without this mirror, targeting a specific zone by its friendly override name (rather than a raw backend-reported label like cluster) would be impossible. |
|
name |
string | Yes | Stable name. Conventionally <provider>-<cluster-or-zone>. |
.status.failureDomains[].attributes¶
Attributes the provider's controller resolved for this domain, including the subset of admin-listed classes that are actually reachable from here.
| Field | Type | Required | Description |
|---|---|---|---|
availableNetworkClasses |
string[] | Subset of spec.capabilities.networkClasses[].name reachable here. | |
availableStorageClasses |
string[] | Subset of spec.capabilities.storageClasses[].name reachable here. | |
capacity |
object | What guests may use in this failure domain, as the provider measured it (ADR-0107). The scheduler fits each VM against it; a domain that publishes none is not filtered on capacity. | |
features |
string[] | Feature flags actually present here. Always a subset of spec.capabilities.features. | |
raw |
map[string]string | Provider-specific resolved attributes; for vSphere this typically includes datacenter, cluster, resourcePool. Used by the provider's controller when filling in the infrastructure CR. |
.status.failureDomains[].attributes.capacity¶
What guests may use in this failure domain, as the provider measured it (ADR-0107). The scheduler fits each VM against it; a domain that publishes none is not filtered on capacity.
| Field | Type | Required | Description |
|---|---|---|---|
cpus |
integer | Logical CPUs guests may use. vCPUs are placed up to this times the Provider's scheduling.cpuOvercommitRatio. |
|
memoryMiB |
integer | Memory guests may use, MiB: the host's, or a smaller budget the host declares for guests (a Cloud Hypervisor host's guests' slice, ADR-0105). Never overcommitted. | |
memoryOverheadMiBPerVM |
integer | Memory each VM costs beyond its class's memoryMiB (its VMM), MiB. |
.status.workload¶
The provider workload banlieue-operator created for this Provider.
Written only by the operator's field manager
(banlieue.io/operator); the provider's own controller never touches
it. This split is deliberate: conditions is a plain list with no
x-kubernetes-list-type: map marker, so two field managers writing into
it would contend over the whole array rather than merging per entry.
Giving the operator a disjoint field keeps server-side apply
conflict-free (ADR-0012).
| Field | Type | Required | Description |
|---|---|---|---|
deploymentName |
string | Name of the Deployment running this Provider's controller. Conventionally banlieue-provider-<class>-<provider-name>. Unset for External: there is no Deployment. |
|
heartbeat |
string | A provider's liveness, from its leader-election Lease (ADR-0102). Allowed: Alive, Stale, Absent. |
|
lastHeartbeatTime |
string | The Lease's last renewTime, when there is a Lease. |
|
mode |
string | Whether the operator runs this provider (Managed) or only gave it an identity (External, ADR-0060 Decision 3). Absent on objects written before the field existed, which were all Managed. Allowed: Managed, External. |
|
namespace |
string | Yes | Namespace the Deployment was created in — the ProviderClass's workloadNamespace, or the operator's own namespace when unset. |
observedGeneration |
integer | The Provider generation the operator had observed when it last applied this workload. | |
readyReplicas |
integer | Ready replicas reported by that Deployment. Zero means the backend's controller is not currently running, whatever the Provider's other conditions say. Unset for External: there is no Deployment, and whether the provider is running is heartbeat (ADR-0102). |
ProviderClass¶
API: banlieue.io/v1alpha1 · Kind: ProviderClass · Scope: Cluster · Short names: pc
ProviderClass — what banlieue runs for a class of backends.
A ProviderClass carries the install metadata for one backend type: which
banlieue provider <backend> role to run, from which image, with what pod
shape and extra permissions. It names no endpoint and holds no credentials
— that is a Provider's job.
Why create one
- Make backends self-provisioning. With a ProviderClass in place,
registering a backend is
kubectl applyof a Provider CR:banlieue-operatorcreates that Provider's Deployment, ServiceAccount, Role and RoleBinding for you. No manifest editing, no helm values. - Decide the image once. Every Provider of this class runs the image pinned here, so upgrading a fleet of backends is a one-object edit instead of one edit per backend.
- Separate the two jobs. Deciding what banlieue runs (a platform owner, cluster-scoped) is not the same as registering a vCenter (a backend admin, namespaced) — different people, different privileges.
How it is used
Provider.spec.providerClassRef.name points at a ProviderClass by name.
The operator resolves it, then applies one workload set per Provider, each
owned by its Provider CR so deleting the Provider garbage-collects the
workload. Each spawned pod runs a server-side filtered watch scoped to its
own Provider, so one hung backend cannot stall another (ADR-0003).
Cluster-scoped: one ProviderClass serves Providers in any namespace.
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| Backend | string | .spec.backend |
0 |
| Image | string | .spec.image.tag |
0 |
| Deployment | string | .spec.deployment |
0 |
| Providers | integer | .status.providers |
0 |
| Ready | string | .status.conditions[?(@.type=='Ready')].status |
0 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
additionalRules |
object[] | Extra RBAC rules appended to the per-instance Role the operator generates for each Provider of this class. | |
backend |
string | Yes | Which provider backend this class instantiates — the banlieue provider <backend> subcommand spawned Deployments run. |
deployment |
string | How a class's providers run (ADR-0060 Decision 3). Allowed: Managed, External. |
|
image |
object | Container image every provider workload of this class runs. | |
logging |
object | Log level and format passed to spawned workloads. | |
nodeSelector |
map[string]string | Node selector applied to provider pods. Useful when backend access is only routable from particular nodes. | |
paused |
boolean | Suspend lifecycle reconciliation for every Provider of this class. Existing workloads are left running untouched. | |
replicas |
integer | Replicas for each provider Deployment. Defaults to [DEFAULT_PROVIDER_REPLICAS]. Provider controllers are leader-elected, so values above one provide failover, not parallelism. |
|
resources |
object | Resource requests and limits for the provider container. When unset the operator applies its own conservative defaults. | |
tolerations |
object[] | Tolerations applied to provider pods. | |
workloadNamespace |
string | Namespace to create provider workloads in. |
.spec.additionalRules[]¶
Extra RBAC rules appended to the per-instance Role the operator generates for each Provider of this class.
Note that Kubernetes forbids granting permissions the grantor does not itself hold: a rule listed here also has to be present in the operator's own ClusterRole, or the RoleBinding is rejected (ADR-0012).
| Field | Type | Required | Description |
|---|---|---|---|
apiGroups |
string[] | apiGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups. | |
nonResourceURLs |
string[] | nonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both. | |
resourceNames |
string[] | resourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. | |
resources |
string[] | resources is a list of resources this rule applies to. '*' represents all resources. | |
verbs |
string[] | Yes | verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs. |
.spec.image¶
Container image every provider workload of this class runs.
Required when deployment is Managed (the default), and must be
unset when it is External: nothing is deployed, so there is no image
to run. The operator and the admission policy both enforce this
(ADR-0060 Decision 3).
| Field | Type | Required | Description |
|---|---|---|---|
digest |
string | Image digest, e.g. sha256:0f756fa0…. When set it is what actually gets pulled, and any tag becomes documentation of intent. |
|
pullPolicy |
string | Image pull policy, spelled exactly as Kubernetes spells it. Allowed: Always, IfNotPresent, Never. |
|
pullSecrets |
object[] | Secrets used to pull the image, for private or mirrored registries. | |
repository |
string | Yes | Image repository without a tag, e.g. ghcr.io/firestoned/banlieue. |
tag |
string | Yes | Image tag, e.g. v0.1.0. Never use latest in production — a mutable tag makes the running version unknowable and defeats rollback. |
.spec.image.pullSecrets[]¶
Secrets used to pull the image, for private or mirrored registries.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.spec.logging¶
Log level and format passed to spawned workloads.
| Field | Type | Required | Description |
|---|---|---|---|
format |
string | Log format: json for SIEM-friendly structured output, anything else for the human-readable text formatter. |
|
level |
string | Log level, e.g. info or debug,kube=warn. Passed through as the workload's log-level flag. |
.spec.resources¶
Resource requests and limits for the provider container. When unset the operator applies its own conservative defaults.
| Field | Type | Required | Description |
|---|---|---|---|
claims |
object[] | Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. | |
limits |
map[string]object | Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | |
requests |
map[string]object | Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ |
.spec.resources.claims[]¶
Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.
This field depends on the DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. |
request |
string | Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. |
.spec.tolerations[]¶
Tolerations applied to provider pods.
| Field | Type | Required | Description |
|---|---|---|---|
effect |
string | Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. | |
key |
string | Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. | |
operator |
string | Operator represents a key's relationship to the value. Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). | |
tolerationSeconds |
integer | TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. | |
value |
string | Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. |
.status¶
Observed state of a ProviderClass.
| Field | Type | Required | Description |
|---|---|---|---|
conditions |
object[] | Standard Kubernetes conditions. Ready reflects whether the class is usable: its backend is compiled into the running operator and its image reference is well-formed. |
|
observedGeneration |
integer | The generation of the spec the operator has reconciled. | |
providers |
integer | Number of Provider CRs currently referencing this class. |
.status.conditions[]¶
Standard Kubernetes conditions. Ready reflects whether the class is
usable: its backend is compiled into the running operator and its image
reference is well-formed.
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
VirtualMachine¶
API: banlieue.io/v1alpha1 · Kind: VirtualMachine · Scope: Namespaced · Short names: vm
VirtualMachine — the user-facing request for a running VM.
This is the one resource end users create. It expresses intent: which
VMClass (shape) and VMImage (OS) to use, optional placement constraints,
the desired power state, and optional guest user-data. banlieue's
controller schedules it onto a Provider + failure domain, creates the
matching provider infrastructure CR (e.g. VSphereMachine), and mirrors
that CR's status back here.
Why create one
- Declare a VM the Kubernetes way. Describe the VM you want; the controller reconciles reality toward it, including power state.
- Stay backend-agnostic. You reference a class and an image by name, not a datastore or a port group. Where it lands is the scheduler's job.
- Compose with policy. Label / anti-affinity selectors and a migration policy steer placement and drift handling without coupling to a specific Provider.
Independent of Cluster API: a VirtualMachine is not a clusterv1.
Machine. It can coexist with CAPI but does not depend on it.
Namespaced: candidate Providers are drawn from the VM's own namespace.
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| Class | string | .spec.classRef.name |
0 |
| Image | string | .spec.imageRef.name |
0 |
| Provider | string | .status.scheduled.providerName |
0 |
| FailureDomain | string | .status.scheduled.failureDomain |
1 |
| Power | string | .status.observedPowerState |
0 |
| Ready | string | .status.conditions[?(@.type=='Ready')].status |
0 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
classRef |
object | Yes | Reference to a (cluster-scoped) VMClass. |
desiredPowerState |
string | Desired power state. Defaults to PoweredOn. Allowed: PoweredOn, PoweredOff, Suspended. |
|
folder |
string | Destination folder for the provisioned VM (e.g. apps/prod on vSphere). When unset, the provider defaults to organizing the VM the same way it organizes its source template — on vSphere, the same per-zone folder the template lives in (ADR-0020 Decision #5). |
|
hardwareOverride |
object | Per-VM override for the VMClass's hardware shape — CPUs, memory, and disk sizes. |
|
imageRef |
object | Yes | Reference to a (cluster-scoped) VMImage. |
migrationPolicy |
string | What to do when current placement no longer satisfies the spec. Allowed: automatic, manual, never. |
|
networkOverrides |
object[] | Per-VM overrides for specific VMClass-declared network interfaces (ADR-0024). Keyed by NetworkInterfaceSpec.name; an interface with no entry here uses its VMClass's own ipam verbatim (commonly dhcp). Lets many VMs share one VMClass while each still gets its own static address — a VMClass-level ipam.static cannot express that, since a class is shared by design. |
|
paused |
boolean | Suspend reconciliation in-band. | |
placement |
object | Placement intent. If unset, the scheduler considers every Provider in the VM's namespace and every failure domain. | |
userData |
object | Optional user-data delivered to the guest via the image's guestAgent (cloud-init / ignition / sysprep). |
.spec.classRef¶
Reference to a (cluster-scoped) VMClass.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.spec.hardwareOverride¶
Per-VM override for the VMClass's hardware shape — CPUs, memory,
and disk sizes.
This is a delta, not the primary definition. The VMClass is the
authoritative source for a VM's hardware shape: its spec.hardware
is fixed and shared by every VM that references the class. This
field applies on top of the class — only the fields you set here
replace the class value; everything else is inherited verbatim.
Use this sparingly. Its primary purpose is to accommodate the rare
VM that genuinely needs a different CPU, memory, or disk budget than
its class defines — for example, a database primary bumped to 16 CPUs
while all other replicas use the 4-CPU class shape, or one VM that
needs a larger data disk. If you find yourself setting the same
override on every VM of a given class, create a new VMClass instead.
| Field | Type | Required | Description |
|---|---|---|---|
cpus |
integer | Override the VMClass's spec.hardware.cpus. If absent, the class value is used unchanged. |
|
diskOverrides |
object[] | Per-disk size overrides, keyed by DiskSpec.name. Only sizeGiB can be overridden per VM; the disk's storageClass and provisioning are class-level concerns. |
|
memoryMiB |
integer | Override the VMClass's spec.hardware.memoryMiB. If absent, the class value is used unchanged. |
.spec.hardwareOverride.diskOverrides[]¶
Per-disk size overrides, keyed by DiskSpec.name.
Only sizeGiB can be overridden per VM; the disk's storageClass
and provisioning are class-level concerns.
This is a delta, not the primary definition. A disk with no
entry here inherits the VMClass's size verbatim.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Matches a VMClass.spec.hardware.disks[].name. |
sizeGiB |
integer | Yes | Override the disk's sizeGiB. Must be ≥ the class value (the provider will reject a shrink). If absent, the class size is used. |
.spec.imageRef¶
Reference to a (cluster-scoped) VMImage.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.spec.networkOverrides[]¶
Per-VM overrides for specific VMClass-declared network interfaces
(ADR-0024). Keyed by NetworkInterfaceSpec.name; an interface with
no entry here uses its VMClass's own ipam verbatim (commonly
dhcp). Lets many VMs share one VMClass while each still gets its
own static address — a VMClass-level ipam.static cannot express
that, since a class is shared by design.
This is a delta, not the primary definition. The VMClass is the
authoritative source for the VM's network shape. Entries here are
layered on top: only the named interface's ipam is replaced;
every other interface is inherited from the class unchanged.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Matches a VMClass.spec.network.interfaces[].name. |
static |
object | Yes | The static address to use for this interface, overriding whatever the VMClass's own ipam declares. |
.spec.networkOverrides[].static¶
The static address to use for this interface, overriding whatever
the VMClass's own ipam declares.
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | |
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer | Yes |
.spec.placement¶
Placement intent. If unset, the scheduler considers every Provider in the VM's namespace and every failure domain.
| Field | Type | Required | Description |
|---|---|---|---|
antiAffinity |
object[] | Anti-affinity rules against other VirtualMachines in the same namespace. Evaluated at scheduling time. | |
failureDomainSelector |
object | Match failure domains by their status.failureDomains[].labels. Across all candidate Providers, only failure domains whose labels match are considered. |
|
providerSelector |
object | Match Providers by their metadata.labels. A Provider is a candidate only if its labels match this selector. |
.spec.placement.antiAffinity[]¶
Anti-affinity rules against other VirtualMachines in the same namespace. Evaluated at scheduling time.
| Field | Type | Required | Description |
|---|---|---|---|
labelSelector |
object | Yes | Other VMs (by their own metadata.labels) to spread away from. |
mode |
string | Strictness. required filters candidates; preferred is best-effort. Allowed: required, preferred. |
|
topologyKey |
string | Yes | A label key from the failure domain's labels. Spreading is required across distinct values of this key. Common keys: cluster, rack, host, dc. |
.spec.placement.antiAffinity[].labelSelector¶
Other VMs (by their own metadata.labels) to spread away from.
| Field | Type | Required | Description |
|---|---|---|---|
matchExpressions |
object[] | ||
matchLabels |
map[string]string |
# .spec.placement.antiAffinity[].labelSelector.matchExpressions[]¶
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | |
operator |
string | Yes | Allowed: In, NotIn, Exists, DoesNotExist. |
values |
string[] |
.spec.placement.failureDomainSelector¶
Match failure domains by their status.failureDomains[].labels.
Across all candidate Providers, only failure domains whose labels
match are considered.
| Field | Type | Required | Description |
|---|---|---|---|
matchExpressions |
object[] | ||
matchLabels |
map[string]string |
.spec.placement.failureDomainSelector.matchExpressions[]¶
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | |
operator |
string | Yes | Allowed: In, NotIn, Exists, DoesNotExist. |
values |
string[] |
.spec.placement.providerSelector¶
Match Providers by their metadata.labels. A Provider is a candidate
only if its labels match this selector.
| Field | Type | Required | Description |
|---|---|---|---|
matchExpressions |
object[] | ||
matchLabels |
map[string]string |
.spec.placement.providerSelector.matchExpressions[]¶
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | |
operator |
string | Yes | Allowed: In, NotIn, Exists, DoesNotExist. |
values |
string[] |
.spec.userData¶
Optional user-data delivered to the guest via the image's
guestAgent (cloud-init / ignition / sysprep).
| Field | Type | Required | Description |
|---|---|---|---|
configMapRef |
object | Key in a ConfigMap in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]). |
|
secretRef |
object | Key in a Secret in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]). |
.spec.userData.configMapRef¶
Key in a ConfigMap in the VirtualMachine's namespace (key defaults to
[DEFAULT_USER_DATA_KEY]).
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Key within the object's data. Defaults are caller-defined. |
|
name |
string | Yes | Name of the ConfigMap / Secret in the referrer's namespace. |
.spec.userData.secretRef¶
Key in a Secret in the VirtualMachine's namespace (key defaults to
[DEFAULT_USER_DATA_KEY]).
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Key within the object's data. Defaults are caller-defined. |
|
name |
string | Yes | Name of the ConfigMap / Secret in the referrer's namespace. |
.status¶
Observed state of a VirtualMachine: the scheduling decision, the infra CR it owns, mirrored provisioning / address / power state, and conditions.
| Field | Type | Required | Description |
|---|---|---|---|
addresses |
object[] | Mirrored from the infra CR's status.addresses. |
|
conditions |
object[] | Standard Kubernetes conditions. Required types: Ready — overall readiness Scheduled — placement decision exists and is current PlacementValid — current placement satisfies the spec InfrastructureReady — mirrors the infra CR's Ready condition Optional: Migrating — true while a migration is in progress Paused — present (True) only while spec.paused suspends reconciliation |
|
heldAddresses |
object[] | Static addresses this VM's infrastructure CR was last applied with (ADR-0083). Written by the controller only when it applies the infra CR, and carried forward unchanged otherwise, so it records what the guest is configured with: it survives guest reboots and is the same on every backend. A held address is never given to another VM. | |
infrastructureRef |
object | Reference to the provider-specific infrastructure CR (e.g. infrastructure.banlieue.io/v1alpha1/VSphereMachine). Set after scheduling, owned by this VirtualMachine. |
|
initialization |
object | Mirrored from the infra CR's status.initialization. |
|
observedGeneration |
integer | ||
observedPowerState |
string | Observed power state from the provider. Allowed: PoweredOn, PoweredOff, Suspended, null. |
|
scheduled |
object | Current scheduling decision. Absent until first successful schedule. | |
tpmEndorsementCertificates |
string[] | Mirrored from the infra CR's status.tpmEndorsementCertificates (ADR-0045). The anchor a verifier checks an attestation quote against; mirrored onward onto a bound VirtualMachineClaim so a consumer needs one GET. |
.status.addresses[]¶
Mirrored from the infra CR's status.addresses.
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | The address itself. |
type |
string | Yes | Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. |
.status.conditions[]¶
Standard Kubernetes conditions. Required types:
Ready — overall readiness
Scheduled — placement decision exists and is current
PlacementValid — current placement satisfies the spec
InfrastructureReady — mirrors the infra CR's Ready condition
Optional:
Migrating — true while a migration is in progress
Paused — present (True) only while spec.paused
suspends reconciliation
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
.status.heldAddresses[]¶
Static addresses this VM's infrastructure CR was last applied with (ADR-0083). Written by the controller only when it applies the infra CR, and carried forward unchanged otherwise, so it records what the guest is configured with: it survives guest reboots and is the same on every backend. A held address is never given to another VM.
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | The address, normalised (an IP is re-printed in canonical form). |
interface |
string | Yes | The VMClass interface the address is on. |
networkClass |
string | Yes | That interface's networkClass: the network the address is unique on. |
.status.infrastructureRef¶
Reference to the provider-specific infrastructure CR
(e.g. infrastructure.banlieue.io/v1alpha1/VSphereMachine).
Set after scheduling, owned by this VirtualMachine.
| Field | Type | Required | Description |
|---|---|---|---|
apiGroup |
string | Yes | |
kind |
string | Yes | |
name |
string | Yes | |
namespace |
string |
.status.initialization¶
Mirrored from the infra CR's status.initialization.
| Field | Type | Required | Description |
|---|---|---|---|
provisioned |
boolean | True when the infrastructure provider reports that the resource's infrastructure is fully provisioned. |
.status.scheduled¶
Current scheduling decision. Absent until first successful schedule.
| Field | Type | Required | Description |
|---|---|---|---|
failureDomain |
string | Yes | Failure domain name (one of the Provider's status.failureDomains[].name). |
providerClass |
string | Yes | Provider's ProviderClass (denormalized for convenience in printer columns). |
providerName |
string | Yes | Provider name (in the VM's namespace). |
resolvedNetworks |
object[] | Resolved network class → concrete backend identifier mappings. | |
resolvedStorage |
object[] | Resolved storage class → concrete backend identifier mappings. | |
scheduledAt |
string | Time the placement decision was made. |
.status.scheduled.resolvedNetworks[]¶
Resolved network class → concrete backend identifier mappings.
| Field | Type | Required | Description |
|---|---|---|---|
backendId |
string | Yes | Backend identifier the provider resolved to (e.g. "ds-fast-01", "vmnet-prod"). |
className |
string | Yes | Class name as referenced in the VMClass (e.g. "gold", "prod"). |
.status.scheduled.resolvedStorage[]¶
Resolved storage class → concrete backend identifier mappings.
| Field | Type | Required | Description |
|---|---|---|---|
backendId |
string | Yes | Backend identifier the provider resolved to (e.g. "ds-fast-01", "vmnet-prod"). |
className |
string | Yes | Class name as referenced in the VMClass (e.g. "gold", "prod"). |
VirtualMachinePool¶
API: banlieue.io/v1alpha1 · Kind: VirtualMachinePool · Scope: Namespaced · Short names: vmpool
VirtualMachinePool: a self-refilling set of warm, single-use VMs.
Why create one
- Hide install latency. A
tpmEnabledclass must pair with aninstallMode: Deferredimage, so every VM pays a full install on first boot. The pool pays that ahead of time. - Single use by construction. Members are handed out through
VirtualMachineClaimand destroyed when the claim ends. There is no code path that returns a used member to the warm set. - Follow the image. When the referenced
VMImageis rebuilt, warm members from the old build are replaced surge-style without dropping claimable capacity.
Namespaced: members are created in the pool's own namespace, which is also where the scheduler looks for candidate Providers.
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| Warm | integer | .spec.warmReplicas |
0 |
| Available | integer | .status.available |
0 |
| Provisioning | integer | .status.provisioning |
0 |
| Claimed | integer | .status.claimed |
0 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
addressing |
object | Per-member static addressing. Omit for DHCP or class-level IPAM. Interim until the CAPI IPAM contract lands (ADR-0033); at that point this gains a poolRef alternative and the inline range stays as the zero-dependency option. |
|
maxIdleSeconds |
integer | Replace a Ready member that has sat unclaimed this long. Bounds how stale an unpatched warm VM can get between image rebuilds. | |
maxReplicas |
integer | Yes | Hard ceiling on members of any phase, claimed ones included. Leave headroom above warmReplicas plus expected concurrent claims, or image rollouts have to trade warm capacity for replacements. |
maxSurge |
integer | Most members allowed to be provisioning at once. Bounds the install load a refill puts on the hosts that claimed members are running on. | |
provisioningTimeoutSeconds |
integer | A member still provisioning after this long is treated as poisoned and deleted, never repaired. | |
readiness |
string | Yes | Which member condition makes it claimable. See [PoolReadiness]. Allowed: GuestReady, InfrastructureReady. |
recycleOnImageChange |
boolean | Replace warm members when the referenced VMImage's build changes. |
|
template |
object | Yes | Template for each member. spec.networkOverrides entries for the interface named in addressing are replaced per member; everything else is copied verbatim. |
warmReplicas |
integer | Yes | How many Ready, unclaimed members to keep available. |
.spec.addressing¶
Per-member static addressing. Omit for DHCP or class-level IPAM.
Interim until the CAPI IPAM contract lands (ADR-0033); at that point
this gains a poolRef alternative and the inline range stays as the
zero-dependency option.
| Field | Type | Required | Description |
|---|---|---|---|
domain |
string | ||
gateway |
string | ||
interface |
string | Yes | Name of the VMClass network interface to stamp, matching NetworkInterfaceOverride.name. |
nameservers |
string[] | ||
pool |
string[] | Yes | The addresses members are drawn from, in the order to draw them (ADR-0056). Each entry is one of: |
prefix |
integer | Yes |
.spec.template¶
Template for each member. spec.networkOverrides entries for the
interface named in addressing are replaced per member; everything
else is copied verbatim.
| Field | Type | Required | Description |
|---|---|---|---|
annotations |
map[string]string | Extra annotations stamped on each member. | |
labels |
map[string]string | Extra labels stamped on each member, in addition to the pool's own. | |
spec |
object | Yes | VirtualMachine — the user-facing request for a running VM. |
.spec.template.spec¶
VirtualMachine — the user-facing request for a running VM.
This is the one resource end users create. It expresses intent: which
VMClass (shape) and VMImage (OS) to use, optional placement constraints,
the desired power state, and optional guest user-data. banlieue's
controller schedules it onto a Provider + failure domain, creates the
matching provider infrastructure CR (e.g. VSphereMachine), and mirrors
that CR's status back here.
Why create one
- Declare a VM the Kubernetes way. Describe the VM you want; the controller reconciles reality toward it, including power state.
- Stay backend-agnostic. You reference a class and an image by name, not a datastore or a port group. Where it lands is the scheduler's job.
- Compose with policy. Label / anti-affinity selectors and a migration policy steer placement and drift handling without coupling to a specific Provider.
Independent of Cluster API: a VirtualMachine is not a clusterv1.
Machine. It can coexist with CAPI but does not depend on it.
Namespaced: candidate Providers are drawn from the VM's own namespace.
| Field | Type | Required | Description |
|---|---|---|---|
classRef |
object | Yes | Reference to a (cluster-scoped) VMClass. |
desiredPowerState |
string | Desired power state. Defaults to PoweredOn. Allowed: PoweredOn, PoweredOff, Suspended. |
|
folder |
string | Destination folder for the provisioned VM (e.g. apps/prod on vSphere). When unset, the provider defaults to organizing the VM the same way it organizes its source template — on vSphere, the same per-zone folder the template lives in (ADR-0020 Decision #5). |
|
hardwareOverride |
object | Per-VM override for the VMClass's hardware shape — CPUs, memory, and disk sizes. |
|
imageRef |
object | Yes | Reference to a (cluster-scoped) VMImage. |
migrationPolicy |
string | What to do when current placement no longer satisfies the spec. Allowed: automatic, manual, never. |
|
networkOverrides |
object[] | Per-VM overrides for specific VMClass-declared network interfaces (ADR-0024). Keyed by NetworkInterfaceSpec.name; an interface with no entry here uses its VMClass's own ipam verbatim (commonly dhcp). Lets many VMs share one VMClass while each still gets its own static address — a VMClass-level ipam.static cannot express that, since a class is shared by design. |
|
paused |
boolean | Suspend reconciliation in-band. | |
placement |
object | Placement intent. If unset, the scheduler considers every Provider in the VM's namespace and every failure domain. | |
userData |
object | Optional user-data delivered to the guest via the image's guestAgent (cloud-init / ignition / sysprep). |
.spec.template.spec.classRef¶
Reference to a (cluster-scoped) VMClass.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.spec.template.spec.hardwareOverride¶
Per-VM override for the VMClass's hardware shape — CPUs, memory,
and disk sizes.
This is a delta, not the primary definition. The VMClass is the
authoritative source for a VM's hardware shape: its spec.hardware
is fixed and shared by every VM that references the class. This
field applies on top of the class — only the fields you set here
replace the class value; everything else is inherited verbatim.
Use this sparingly. Its primary purpose is to accommodate the rare
VM that genuinely needs a different CPU, memory, or disk budget than
its class defines — for example, a database primary bumped to 16 CPUs
while all other replicas use the 4-CPU class shape, or one VM that
needs a larger data disk. If you find yourself setting the same
override on every VM of a given class, create a new VMClass instead.
| Field | Type | Required | Description |
|---|---|---|---|
cpus |
integer | Override the VMClass's spec.hardware.cpus. If absent, the class value is used unchanged. |
|
diskOverrides |
object[] | Per-disk size overrides, keyed by DiskSpec.name. Only sizeGiB can be overridden per VM; the disk's storageClass and provisioning are class-level concerns. |
|
memoryMiB |
integer | Override the VMClass's spec.hardware.memoryMiB. If absent, the class value is used unchanged. |
# .spec.template.spec.hardwareOverride.diskOverrides[]¶
Per-disk size overrides, keyed by DiskSpec.name.
Only sizeGiB can be overridden per VM; the disk's storageClass
and provisioning are class-level concerns.
This is a delta, not the primary definition. A disk with no
entry here inherits the VMClass's size verbatim.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Matches a VMClass.spec.hardware.disks[].name. |
sizeGiB |
integer | Yes | Override the disk's sizeGiB. Must be ≥ the class value (the provider will reject a shrink). If absent, the class size is used. |
.spec.template.spec.imageRef¶
Reference to a (cluster-scoped) VMImage.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.spec.template.spec.networkOverrides[]¶
Per-VM overrides for specific VMClass-declared network interfaces
(ADR-0024). Keyed by NetworkInterfaceSpec.name; an interface with
no entry here uses its VMClass's own ipam verbatim (commonly
dhcp). Lets many VMs share one VMClass while each still gets its
own static address — a VMClass-level ipam.static cannot express
that, since a class is shared by design.
This is a delta, not the primary definition. The VMClass is the
authoritative source for the VM's network shape. Entries here are
layered on top: only the named interface's ipam is replaced;
every other interface is inherited from the class unchanged.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Matches a VMClass.spec.network.interfaces[].name. |
static |
object | Yes | The static address to use for this interface, overriding whatever the VMClass's own ipam declares. |
# .spec.template.spec.networkOverrides[].static¶
The static address to use for this interface, overriding whatever
the VMClass's own ipam declares.
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | |
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer | Yes |
.spec.template.spec.placement¶
Placement intent. If unset, the scheduler considers every Provider in the VM's namespace and every failure domain.
| Field | Type | Required | Description |
|---|---|---|---|
antiAffinity |
object[] | Anti-affinity rules against other VirtualMachines in the same namespace. Evaluated at scheduling time. | |
failureDomainSelector |
object | Match failure domains by their status.failureDomains[].labels. Across all candidate Providers, only failure domains whose labels match are considered. |
|
providerSelector |
object | Match Providers by their metadata.labels. A Provider is a candidate only if its labels match this selector. |
# .spec.template.spec.placement.antiAffinity[]¶
Anti-affinity rules against other VirtualMachines in the same namespace. Evaluated at scheduling time.
| Field | Type | Required | Description |
|---|---|---|---|
labelSelector |
object | Yes | Other VMs (by their own metadata.labels) to spread away from. |
mode |
string | Strictness. required filters candidates; preferred is best-effort. Allowed: required, preferred. |
|
topologyKey |
string | Yes | A label key from the failure domain's labels. Spreading is required across distinct values of this key. Common keys: cluster, rack, host, dc. |
## .spec.template.spec.placement.antiAffinity[].labelSelector¶
Other VMs (by their own metadata.labels) to spread away from.
| Field | Type | Required | Description |
|---|---|---|---|
matchExpressions |
object[] | ||
matchLabels |
map[string]string |
### .spec.template.spec.placement.antiAffinity[].labelSelector.matchExpressions[]¶
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | |
operator |
string | Yes | Allowed: In, NotIn, Exists, DoesNotExist. |
values |
string[] |
# .spec.template.spec.placement.failureDomainSelector¶
Match failure domains by their status.failureDomains[].labels.
Across all candidate Providers, only failure domains whose labels
match are considered.
| Field | Type | Required | Description |
|---|---|---|---|
matchExpressions |
object[] | ||
matchLabels |
map[string]string |
## .spec.template.spec.placement.failureDomainSelector.matchExpressions[]¶
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | |
operator |
string | Yes | Allowed: In, NotIn, Exists, DoesNotExist. |
values |
string[] |
# .spec.template.spec.placement.providerSelector¶
Match Providers by their metadata.labels. A Provider is a candidate
only if its labels match this selector.
| Field | Type | Required | Description |
|---|---|---|---|
matchExpressions |
object[] | ||
matchLabels |
map[string]string |
## .spec.template.spec.placement.providerSelector.matchExpressions[]¶
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | |
operator |
string | Yes | Allowed: In, NotIn, Exists, DoesNotExist. |
values |
string[] |
.spec.template.spec.userData¶
Optional user-data delivered to the guest via the image's
guestAgent (cloud-init / ignition / sysprep).
| Field | Type | Required | Description |
|---|---|---|---|
configMapRef |
object | Key in a ConfigMap in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]). |
|
secretRef |
object | Key in a Secret in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]). |
# .spec.template.spec.userData.configMapRef¶
Key in a ConfigMap in the VirtualMachine's namespace (key defaults to
[DEFAULT_USER_DATA_KEY]).
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Key within the object's data. Defaults are caller-defined. |
|
name |
string | Yes | Name of the ConfigMap / Secret in the referrer's namespace. |
# .spec.template.spec.userData.secretRef¶
Key in a Secret in the VirtualMachine's namespace (key defaults to
[DEFAULT_USER_DATA_KEY]).
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Key within the object's data. Defaults are caller-defined. |
|
name |
string | Yes | Name of the ConfigMap / Secret in the referrer's namespace. |
.status¶
| Field | Type | Required | Description |
|---|---|---|---|
available |
integer | Ready and unclaimed: what a claim can bind right now. | |
claimed |
integer | ||
conditions |
object[] | ||
imageRevision |
string | Image revision new members are currently being built from. | |
observedGeneration |
integer | ||
provisioning |
integer | ||
replicas |
integer | Members of any phase, excluding ones already being deleted. |
.status.conditions[]¶
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
VirtualMachineClaim¶
API: banlieue.io/v1alpha1 · Kind: VirtualMachineClaim · Scope: Namespaced · Short names: vmclaim
VirtualMachineClaim: one subject's exclusive, time-boxed hold on one pool member.
What a claim guarantees
- Bound once, ever. The member it binds is never handed to another subject, never returned to the warm set, and never reused. Release is always destruction.
- Deleting the claim destroys the VM, and the claim object does not disappear until it has.
ttlSecondsis a hard deadline, not a grace period. At expiry the member is deleted whether or not the consumer is finished.
What a claim is not
It is not a credential channel. spec.subject records who the member
is for so the binding is auditable in the API server's own audit log; it
is opaque to banlieue, and a token must never be placed in it. Delivering
the subject's token to the guest is the consumer's job, over its own
attested channel, anchored on the bound member's EK certificate
(status.tpmEndorsementCertificates, ADR-0045, ADR-0049).
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| Pool | string | .spec.poolRef.name |
0 |
| VM | string | .status.virtualMachineRef.name |
0 |
| Phase | string | .status.phase |
0 |
| Expires | string | .status.expiresAt |
0 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
poolRef |
object | Yes | The pool to take a member from. Same namespace as the claim. |
subject |
object | Yes | Who this member is for. Opaque to banlieue: recorded, mirrored onto the member as annotations, and never interpreted. |
ttlSeconds |
integer | Yes | Hard lifetime in seconds, counted from binding rather than from creation — a claim that waited ten minutes for capacity still gets its full TTL. Required, with no default: a claim without a deadline is a leaked VM, and the right value is a property of the workload. |
.spec.poolRef¶
The pool to take a member from. Same namespace as the claim.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.spec.subject¶
Who this member is for. Opaque to banlieue: recorded, mirrored onto the member as annotations, and never interpreted.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Stable subject identifier within that issuer (the sub / oid claim), not a display name or e-mail. |
issuer |
string | Yes | Token issuer the subject was authenticated by, e.g. an OIDC issuer URL. |
.status¶
| Field | Type | Required | Description |
|---|---|---|---|
addresses |
object[] | Mirrored from the bound member so a consumer needs one GET. | |
boundAt |
string | Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers. | |
conditions |
object[] | ||
expiresAt |
string | bound_at + spec.ttlSeconds. The member is deleted at this instant. |
|
nonce |
string | Deprecated, never set since v0.4.14. It was a per-claim value for ADR-0049's quote-over-nonce handshake, which SPIRE's TPM node attestation superseded (ADR-0049, amended 2026-11-05). Kept so an existing claim's status still parses; removed with the next API version. | |
observedGeneration |
integer | ||
phase |
string | Where a claim is in its one-way lifecycle. Allowed: Pending, Bound, Releasing, Failed. |
|
tpmEndorsementCertificates |
string[] | PEM vTPM endorsement key certificate(s) of the bound member, mirrored from the infra CR (ADR-0045). Lets a verifier check that an attestation comes from the VM banlieue itself created for this claim. Populated since ADR-0045, from the bound member's VirtualMachine.status, which mirrors its infrastructure CR. Empty for a member with no vTPM. |
|
virtualMachineRef |
object | The bound member. Set once, at bind time, and never rewritten. |
.status.addresses[]¶
Mirrored from the bound member so a consumer needs one GET.
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | The address itself. |
type |
string | Yes | Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. |
.status.conditions[]¶
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
.status.virtualMachineRef¶
The bound member. Set once, at bind time, and never rewritten.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
VMClass¶
API: banlieue.io/v1alpha1 · Kind: VMClass · Scope: Cluster · Short names: vmc
VMClass — a reusable, cluster-scoped catalog of VM "shapes".
A VMClass is to a VirtualMachine what a Kubernetes StorageClass is to a
PersistentVolumeClaim: a named, admin-curated template that captures how
much machine you get and what the backend must support, without naming
any particular backend. A VirtualMachine references a VMClass by name
(spec.classRef) instead of restating CPU / memory / disk / network on
every VM.
Why create one
- Standardize sizing. Define a small set of tiers (
small,db-prod,gpu-trainer) once; users pick a tier instead of hand-tuning hardware. - Decouple intent from backend. A VMClass requests abstract storage
and network classes plus feature flags (e.g.
efiSecureBoot). The scheduler only places a VM on a Provider + failure domain that actually advertises those capabilities, so a class stays portable across vSphere, Proxmox, and libvirt. - Govern capabilities. Because requirements live on the class, cluster admins control which hardware shapes and features tenants may request.
How it is used
At schedule time the controller intersects this class's requirements with
each candidate Provider's spec.capabilities and each failure domain's
resolved attributes. A Provider that lacks the requested storage class,
network class, firmware, or a required feature is filtered out.
Cluster-scoped: a VMClass is shared by VirtualMachines in any namespace.
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| CPUs | integer | .spec.hardware.cpus |
0 |
| MemoryMiB | integer | .spec.hardware.memoryMiB |
0 |
| Firmware | string | .spec.firmware |
0 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
features |
string[] | Required feature flags. The scheduler will only select a Provider + failure domain whose features is a superset of this list. |
|
firmware |
string | Firmware. Providers / failure domains that lack support for the requested firmware are filtered out by the scheduler. Allowed: bios, efi, efi-secure. |
|
hardware |
object | Yes | Virtual hardware shape — CPU, memory, and disks — every VM of this class is given. |
network |
object | Yes | Network shape — the ordered interfaces (and their abstract network classes) every VM of this class is given. |
tpmEnabled |
boolean | Attach a virtual TPM (vTPM) device to every VM of this class (ADR-0039). A class-level capability, like firmware — not a per-VM override (VirtualMachineSpec.hardwareOverride has no tpmEnabled counterpart, for the same reason it has none for firmware). The scheduler only selects a Provider/failure domain advertising the vtpm feature when this is true. Used by Kairos's kcrypt to seal LUKS keys to the VM's own TPM at install time; the device must exist before first boot, which the vSphere provider guarantees by attaching it between clone and power-on. |
.spec.hardware¶
Virtual hardware shape — CPU, memory, and disks — every VM of this class is given.
| Field | Type | Required | Description |
|---|---|---|---|
cpus |
integer | Yes | Number of virtual CPUs. |
disks |
object[] | Yes | Disks in attachment order. The first disk is the OS disk and is backed by the VMImage resolved for the VirtualMachine; subsequent disks are blank and created with the requested size and storage class. |
memoryMiB |
integer | Yes | Memory in MiB. |
.spec.hardware.disks[]¶
Disks in attachment order. The first disk is the OS disk and is backed by the VMImage resolved for the VirtualMachine; subsequent disks are blank and created with the requested size and storage class.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Stable name within the VM; used in status to report resolved backend identifiers. |
provisioning |
string | Disk provisioning hint. Providers honor on a best-effort basis. Allowed: thin, thick, eagerZeroed. |
|
sizeGiB |
integer | Yes | Size in GiB. For the OS disk this is the minimum size; if the image is larger, the provider grows accordingly. |
storageClass |
string | Yes | Abstract storage class name. MUST be advertised in the chosen Provider's spec.capabilities.storageClasses. |
.spec.network¶
Network shape — the ordered interfaces (and their abstract network classes) every VM of this class is given.
| Field | Type | Required | Description |
|---|---|---|---|
interfaces |
object[] | Yes | Network interfaces in attachment order. |
.spec.network.interfaces[]¶
Network interfaces in attachment order.
| Field | Type | Required | Description |
|---|---|---|---|
ipam |
object | Yes | IPAM configuration. Uses [IpamShape] (not [IpamSpec]) because a VMClass is shared by many VMs — there is no per-VM address at this level. Per-VM static addresses are provided via VirtualMachine.spec.networkOverrides. |
mtu |
integer | Optional MTU override. Provider may ignore if unsupported. | |
name |
string | Yes | Stable name within the VM. |
networkClass |
string | Yes | Abstract network class name. MUST be advertised in the chosen Provider's spec.capabilities.networkClasses. |
.spec.network.interfaces[].ipam¶
IPAM configuration. Uses [IpamShape] (not [IpamSpec]) because a
VMClass is shared by many VMs — there is no per-VM address at this
level. Per-VM static addresses are provided via
VirtualMachine.spec.networkOverrides.
| Field | Type | Required | Description |
|---|---|---|---|
pool |
object | Pool-based IPAM parameters. | |
static |
object | Shared subnet parameters (prefix, gateway, nameservers, domain) — not a per-VM address. |
# .spec.network.interfaces[].ipam.pool¶
Pool-based IPAM parameters.
| Field | Type | Required | Description |
|---|---|---|---|
poolRef |
object | Yes | Typed reference (apiGroup + kind + name + optional namespace). |
## .spec.network.interfaces[].ipam.pool.poolRef¶
Typed reference (apiGroup + kind + name + optional namespace).
Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we
want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's
default) or future banlieue-native pool types.
| Field | Type | Required | Description |
|---|---|---|---|
apiGroup |
string | Yes | |
kind |
string | Yes | |
name |
string | Yes | |
namespace |
string |
# .spec.network.interfaces[].ipam.static¶
Shared subnet parameters (prefix, gateway, nameservers, domain) — not a per-VM address.
| Field | Type | Required | Description |
|---|---|---|---|
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer |
VMImage¶
API: banlieue.io/v1alpha1 · Kind: VMImage · Scope: Cluster · Short names: vmi
VMImage — a cluster-scoped, backend-agnostic catalog entry for a bootable guest image.
A VMImage names an operating system (family / distribution / version /
architecture) once, then lists — per provider class — where that image
actually lives on each backend (spec.sources). A VirtualMachine
references a VMImage by name (spec.imageRef); the scheduler and the
chosen provider resolve it to a concrete template / backing file / import
URL at provisioning time.
Why create one
- One name, many backends. "ubuntu-22.04" can map to a vSphere template, a Proxmox template VMID, and a libvirt qcow2 — users reference a single VMImage regardless of where the VM lands.
- Explicit, auditable image sourcing. Sources (and optional checksums) are declared, not auto-discovered, so what actually boots is reviewable.
- Readiness gating. The image controller records per-Provider
readiness in
status; the scheduler refuses to place a VM until the image is confirmed available (or importable) on a candidate Provider.
Cluster-scoped: a VMImage is shared by VirtualMachines in any namespace.
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| OS | string | .spec.osDistribution |
0 |
| Version | string | .spec.osVersion |
0 |
| Arch | string | .spec.architecture |
0 |
| Ready | string | .status.conditions[?(@.type=='Ready')].status |
0 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
architecture |
string | Yes | Guest CPU architecture. Failure domains whose hosts cannot run this architecture are filtered out by the scheduler. Allowed: amd64, arm64. |
cloudConfigs |
object[] | Layered cloud-configs baked into the built artifact for Url-kind sources (ADR-0037). banlieue-imagebuilder fetches each referenced Secret in list order, deep-merges their YAML content (maps deep-merge, lists concatenate, type-mismatch errors), SSA-applies a single merged Secret (<vmimage-name>-cloud-config-merged), and passes that to the kairos-operator OSArtifact as cloudConfigRef (auroraboot build-iso --cloud-config). Empty list = no cloud-config. Index 0 is the base; each subsequent entry layers on top. SecretRef-first; see [CloudConfigSource] and ADR-0020. Ignored for non-Url sources. |
|
firstBootSealing |
object | Declares that every clone of this image seals the listed partitions to its own vTPM on its first boot (ADR-0088), which is what lets a VMClass with tpmEnabled: true use an Immediate (pre-installed) image. Without it that pairing is refused, because the template was installed before any per-VM vTPM existed (ADR-0048). |
|
guestAgent |
string | Guest agent contract this image is built to support; determines how VirtualMachine.spec.userData is delivered. Allowed: cloud-init, ignition, sysprep, none. |
|
isoOverlay |
object | Additional files overlaid onto a built ISO for Url-kind vSphere sources (e.g. a hand-verified grub.cfg). Resolved by banlieue-imagebuilder into the kairos-operator OSArtifact's spec.volumes[] + spec.artifacts.overlayISOVolume — the same auroraboot build-iso --overlay-iso mechanism a hand-run ISO-build pipeline would use. See [IsoOverlaySource] and ADR-0022. Ignored for cloudImage-kind builds and non-Url sources. |
|
osDistribution |
string | Yes | Free-form distribution string. Examples: ubuntu, rhel, debian, fedora-coreos, windows-server. |
osFamily |
string | Yes | Broad operating-system family. Coarser than osDistribution; lets providers apply high-level guest handling. Allowed: linux, windows, bsd, other. |
osVersion |
string | Yes | Free-form version string. Examples: "22.04", "9.4", "2022". |
prelay |
object | Pre-lay the built image (ADR-0113): banlieue-imagebuilder boots the raw cloudImage once, at build time, through the Kairos recovery reset every clone would otherwise run on its first boot, so each clone boots straight into the installed system. Only for a Url source built as a cloudImage; an iso build is refused (PrelayNeedsCloudImage). The pre-lay Job runs the published banlieue-prelay image (banlieue-imagebuilder --prelay-image) and needs /dev/kvm on the build node. The published artifact is the pre-laid file, with a checksum the builder computed after verifying the built file against the source's checksum. |
|
sources |
object[] | Yes | Per-provider source mappings — one backend binding for this catalog entry per providerClass you intend to schedule VMs onto ("one name, many backends", see the type-level doc comment above). |
template |
object | How the backend template is built from a Url source (root folder, network, disk, CPU / memory / firmware / NIC, force knobs). Every field is optional and falls back to a built-in default. Only meaningful for Url sources, with one exception: for a vSphere Template source (an existing template banlieue adopts and never builds) only rootFolder is read, to find the template in <rootFolder>/<failure-domain>; every other field is ignored. Ignored for BackingFile. See [VMImageTemplate], ADR-0020 and ADR-0104. |
|
trustedBoot |
object | Requests a Trusted Boot (UKI) artifact instead of a classic kernel+initrd one, for Url-kind vSphere sources. Resolved by banlieue-imagebuilder into the kairos-operator OSArtifact's spec.artifacts.uki.{iso,keysVolume} (replacing the plain artifacts.iso request) — the auroraboot build-uki mechanism. See [TrustedBootSource] and ADR-0051. Ignored for cloudImage-kind builds and non-Url sources. |
.spec.cloudConfigs[]¶
Layered cloud-configs baked into the built artifact for Url-kind
sources (ADR-0037). banlieue-imagebuilder fetches each referenced
Secret in list order, deep-merges their YAML content (maps deep-merge,
lists concatenate, type-mismatch errors), SSA-applies a single merged
Secret (<vmimage-name>-cloud-config-merged), and passes that to
the kairos-operator OSArtifact as cloudConfigRef
(auroraboot build-iso --cloud-config). Empty list = no cloud-config.
Index 0 is the base; each subsequent entry layers on top.
SecretRef-first; see [CloudConfigSource] and ADR-0020.
Ignored for non-Url sources.
| Field | Type | Required | Description |
|---|---|---|---|
secretRef |
object | Key in a Secret in the imagebuild namespace holding the cloud-config YAML (key defaults to [DEFAULT_CLOUD_CONFIG_KEY]). |
.spec.cloudConfigs[].secretRef¶
Key in a Secret in the imagebuild namespace holding the cloud-config
YAML (key defaults to [DEFAULT_CLOUD_CONFIG_KEY]).
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Key within the object's data. Defaults are caller-defined. |
|
name |
string | Yes | Name of the ConfigMap / Secret in the referrer's namespace. |
.spec.firstBootSealing¶
Declares that every clone of this image seals the listed partitions
to its own vTPM on its first boot (ADR-0088), which is what lets a
VMClass with tpmEnabled: true use an Immediate (pre-installed)
image. Without it that pairing is refused, because the template was
installed before any per-VM vTPM existed (ADR-0048).
For a Url source banlieue-imagebuilder writes the sealing policy
into the built image itself (status.firstBootSealing: Built); for a
Template or BackingFile source the image must already carry it, and
this field is an operator assertion (Asserted). Either way every
clone's GuestReady waits for the guest to report each listed
partition sealed. Needs a source image on Kairos v4.4.0 or later.
Honoured unless banlieue-controller runs with
--enable-first-boot-sealing=false, which refuses a VirtualMachine
of this image (FirstBootSealingDisabled). Not combinable with
trustedBoot.
| Field | Type | Required | Description |
|---|---|---|---|
partitions |
string[] | Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal. |
|
timeoutSeconds |
integer | Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed. |
.spec.isoOverlay¶
Additional files overlaid onto a built ISO for Url-kind vSphere
sources (e.g. a hand-verified grub.cfg). Resolved by
banlieue-imagebuilder into the kairos-operator OSArtifact's
spec.volumes[] + spec.artifacts.overlayISOVolume — the same
auroraboot build-iso --overlay-iso mechanism a hand-run ISO-build
pipeline would use. See [IsoOverlaySource] and ADR-0022. Ignored for
cloudImage-kind builds and non-Url sources.
| Field | Type | Required | Description |
|---|---|---|---|
files |
object[] | Explicit key -> ISO-relative-path mapping. At least one entry expected; an empty list is accepted but wires nothing into the OSArtifact. |
|
secretRef |
object | Yes | Secret in the imagebuild namespace holding the overlay file contents. |
.spec.isoOverlay.files[]¶
Explicit key -> ISO-relative-path mapping. At least one entry expected;
an empty list is accepted but wires nothing into the OSArtifact.
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | Key within the overlay Secret holding this file's content. |
path |
string | Yes | Destination path, relative to the ISO root (e.g. boot/grub2/grub.cfg). |
.spec.isoOverlay.secretRef¶
Secret in the imagebuild namespace holding the overlay file contents.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.spec.prelay¶
Pre-lay the built image (ADR-0113): banlieue-imagebuilder boots the
raw cloudImage once, at build time, through the Kairos recovery
reset every clone would otherwise run on its first boot, so each
clone boots straight into the installed system. Only for a Url
source built as a cloudImage; an iso build is refused
(PrelayNeedsCloudImage). The pre-lay Job runs the published
banlieue-prelay image (banlieue-imagebuilder --prelay-image) and
needs /dev/kvm on the build node. The published artifact is the pre-laid file, with a
checksum the builder computed after verifying the built file against
the source's checksum.
| Field | Type | Required | Description |
|---|---|---|---|
diskSizeGiB |
integer | Yes | The clones' OS disk size, in GiB. COS_PERSISTENT fills a disk of this size and does not grow on a larger one, and a smaller one cannot hold the image: give the classes that use this image this disk size (ADR-0113 Decision 4). |
.spec.sources[]¶
Per-provider source mappings — one backend binding for this catalog
entry per providerClass you intend to schedule VMs onto ("one
name, many backends", see the type-level doc comment above).
x-kubernetes-list-type: map keyed on providerClass: the API
server rejects a second entry for a providerClass that already
has one, rather than leaving it to find_url_source /
find_vsphere_source to silently pick whichever came first.
| Field | Type | Required | Description |
|---|---|---|---|
checksum |
string | Optional checksum for imported images. Format: <alg>:<hex>, e.g. sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b.... Supported algorithms: sha256, sha512. Provider import Jobs verify the built artifact against this value before writing it to the backend and fail closed on mismatch or an unsupported algorithm. |
|
importFrom |
string | Optional source URL. When set, providers that support image import will pull from here if the image isn't already present locally. | |
kind |
string | Yes | What kind of backend artifact ref refers to. Allowed: Template, BackingFile, Url. |
providerClass |
string | Yes | Name of the ProviderClass this source applies to. Conventional values: vsphere, proxmox, libvirt. |
ref |
string | Yes | Provider-interpreted reference: vsphere + Template: template name e.g. "ubuntu-22.04-cloudinit" proxmox + Template: template VMID e.g. "9000" libvirt + BackingFile: path e.g. "/var/lib/libvirt/images/ubuntu.qcow2" * + Url: ignored; uses importFrom |
.spec.template¶
How the backend template is built from a Url source (root
folder, network, disk, CPU / memory / firmware / NIC, force knobs).
Every field is optional and falls back to a built-in default. Only
meaningful for Url sources, with one exception: for a vSphere
Template source (an existing template banlieue adopts and never
builds) only rootFolder is read, to find the template in
<rootFolder>/<failure-domain>; every other field is ignored.
Ignored for BackingFile. See [VMImageTemplate], ADR-0020 and
ADR-0104.
| Field | Type | Required | Description |
|---|---|---|---|
cpus |
integer | Virtual CPU count of the template (govc vm.create -c). When unset, defaults to 2. vSphere-only. |
|
disk |
object | Install disk of the template (the clone source's disk). When unset, a thin 100 GiB disk on a pvscsi controller is used. | |
firmware |
string | Firmware for the template (govc vm.create -firmware). Reuses the backend-agnostic [Firmware] hint (bios / efi / efi-secure). When unset, defaults to efi. vSphere maps efi-secure to EFI with secure boot enabled. Allowed: bios, efi, efi-secure, null. |
|
forceCreate |
boolean | Recreate the template even if one of that name already exists, destroying the existing one first. Threaded as --force-create. |
|
forceUpload |
boolean | Re-upload the built ISO even if one of that name already exists on the backend, deleting the existing one first (the vСenter datastore file API does not overwrite in place). Threaded as --force-upload. |
|
guestId |
string | vCenter guestId for the template (govc vm.create -g, e.g. rhel9_64Guest, ubuntu64Guest). When unset, it is derived from the VMImage's osFamily / osDistribution / osVersion. vSphere-only. |
|
installMode |
string | How the template's install step is driven. See [InstallMode] and ADR-0021 / ADR-0040. Allowed: immediate, deferred, manual. |
|
installTimeoutSeconds |
integer | Bound, in seconds, on how long the import Job waits for the unattended Kairos install to finish and the VM to power itself off (install.poweroff: true in the cloud-config) before failing the Job. When unset, defaults to 1800 (30 min). See ADR-0021: the golden disk is never rebooted by the build, so this bounds only the (typically 8-12 min) unattended-install window, not a boot cycle. |
|
memoryMib |
integer | Memory of the template, in MiB (govc vm.create -m). When unset, defaults to 4096. vSphere-only. |
|
network |
object[] | The template's network interfaces. Empty means exactly one NIC, using every per-entry default below — the same behavior this field had before it became a list (ADR-0031). vSphere-only. | |
retainOnDelete |
boolean | Keep the per-zone vCenter template(s) this VMImage caused to be built when the VMImage itself is deleted. When unset (the default), deleting a VMImage also destroys every per-zone template it owns — declarative deletion, matching VirtualMachine's own cascade onto its VSphereMachine (ADR-0026). Set true to opt out — e.g. the template is still referenced by another generation, or its lifecycle is managed by hand outside banlieue. vSphere-only; ignored by any other provider. See ADR-0028. |
|
rootFolder |
string | Root vCenter inventory folder (path under the datacenter's VM folder, e.g. templates/kairos); created if missing. When unset, the datacenter's VM-folder root is the root. vSphere-only. Read for both Url (where the template is created) and Template (where the existing template is looked up) sources (ADR-0104). |
.spec.template.disk¶
Install disk of the template (the clone source's disk). When unset, a thin 100 GiB disk on a pvscsi controller is used.
| Field | Type | Required | Description |
|---|---|---|---|
controller |
string | Disk controller type. Defaults to pvscsi. Allowed: pvscsi, lsiLogic, lsiLogicSas, busLogic. |
|
size |
integer | Disk size, in GiB. Defaults to 100 when unset. | |
type |
string | Provisioning hint: thin (default), thick, or eagerZeroed. Reuses the backend-agnostic [DiskProvisioning] shared with VMClass / VSphereMachine; eager-zeroing is the eagerZeroed variant, not a separate flag. Providers honor it on a best-effort basis. Allowed: thin, thick, eagerZeroed. |
.spec.template.network[]¶
The template's network interfaces. Empty means exactly one NIC, using every per-entry default below — the same behavior this field had before it became a list (ADR-0031). vSphere-only.
| Field | Type | Required | Description |
|---|---|---|---|
adapter |
string | Virtual NIC adapter type for the template (govc vm.create -net.adapter). Allowed: vmxnet3, vmxnet2, e1000, e1000e. |
|
network |
string | Port group this NIC attaches to. When unset, the zone's first reachable network class (ADR-0019) is used. | |
pciSlot |
integer | PCI slot number for this NIC (ethernetN.pciSlotNumber). Slot 192 on the first NIC yields a stable ens192 interface name in the guest. When unset, defaults to 192 + this NIC's index in VMImageTemplate.network — so a template with several NICs and no explicit slots still gets predictable, non-colliding ens192/ens193/ens194/... naming. |
.spec.trustedBoot¶
Requests a Trusted Boot (UKI) artifact instead of a classic
kernel+initrd one, for Url-kind vSphere sources. Resolved by
banlieue-imagebuilder into the kairos-operator OSArtifact's
spec.artifacts.uki.{iso,keysVolume} (replacing the plain
artifacts.iso request) — the auroraboot build-uki mechanism. See
[TrustedBootSource] and ADR-0051. Ignored for cloudImage-kind
builds and non-Url sources.
| Field | Type | Required | Description |
|---|---|---|---|
secretRef |
object | Yes | Secret in the imagebuild namespace holding the six files auroraboot build-uki requires: PK.auth, KEK.auth, db.auth, db.key, db.pem, tpm2-pcr-private.pem. Generated out-of-band via auroraboot genkey — banlieue never generates or manages this key material. |
.spec.trustedBoot.secretRef¶
Secret in the imagebuild namespace holding the six files
auroraboot build-uki requires: PK.auth, KEK.auth, db.auth,
db.key, db.pem, tpm2-pcr-private.pem. Generated out-of-band via
auroraboot genkey — banlieue never generates or manages this key
material.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.status¶
Observed availability of a VMImage across the Providers that can serve it. Maintained by the image controller; read by the scheduler.
| Field | Type | Required | Description |
|---|---|---|---|
buildArtifact |
object | Progress of the shared, provider-agnostic image build for Url-kind sources — set exclusively by banlieue-imagebuilder (field manager banlieue.io/imagebuilder), never by a provider. Typed by kind (cloudImage for libvirt, iso for vSphere). None when no Url source exists on this VMImage or the build hasn't started. See ADR-0010 and ADR-0020. |
|
conditions |
object[] | Ready is True iff every per-provider entry is ready. |
|
firstBootSealing |
string | How banlieue knows an image seals itself on first boot (ADR-0088). Allowed: Built, Asserted. |
|
observedGeneration |
integer | ||
perProvider |
object[] | Per-Provider readiness. One entry per Provider that supports this image's providerClass and has reconciled at least once. |
.status.buildArtifact¶
Progress of the shared, provider-agnostic image build for Url-kind
sources — set exclusively by banlieue-imagebuilder (field manager
banlieue.io/imagebuilder), never by a provider. Typed by kind
(cloudImage for libvirt, iso for vSphere). None when no Url
source exists on this VMImage or the build hasn't started. See
ADR-0010 and ADR-0020.
| Field | Type | Required | Description |
|---|---|---|---|
checksum |
string | Expected checksum (<alg>:<hex>) of the built artifact, copied from the Url source the build serves. Consumers that stream the artifact to a backend MUST verify it against this value and fail closed on mismatch (security review 2026-07-31, SEC-004) — the value lives here, next to the PVC reference, so no consumer has to re-derive which source the shared build came from. |
|
file |
string | File name of the artifact within the artifacts PVC (kairos-operator convention: <osArtifactRef>.raw for cloudImage, <osArtifactRef>.iso for iso). Populated at phase Ready. |
|
firstBootSealingLayer |
boolean | Whether this build carries the banlieue-generated first-boot sealing layer (ADR-0088): set when spec.firstBootSealing was honoured by the merged cloud-config this artifact was built from. Omitted when false. |
|
kind |
string | Yes | What kind of artifact was built, aligned with kairos-operator's own OSArtifactKind. Determines the file extension and which provider class consumes it. Allowed: cloudImage, iso. |
message |
string | Long human-readable detail, e.g. the OSArtifact.status.message on failure. |
|
ociArtifact |
object | The same artifact, pushed to an OCI registry for providers that run outside the cluster and cannot mount the artifacts PVC (ADR-0064). Set only when a cloud-hypervisor Url source exists; None otherwise, so installs without a host-resident provider need no registry. |
|
osArtifactRef |
string | Yes | Name of the OSArtifact CR banlieue-imagebuilder created for this VMImage (same namespace as the artifacts PVC below). |
osArtifactUid |
string | metadata.uid of the OSArtifact named by os_artifact_ref, once observed. Each provider's per-zone import Job sets this as its own ownerReference so a rebuilt (deleted-and-recreated) OSArtifact garbage-collects the stale Job — and the artifacts PVC mount it holds — instead of the Job outliving it for up to its ttlSecondsAfterFinished (ADR-0027). Absent until the OSArtifact has actually been observed once. |
|
phase |
string | Yes | Current build phase. Allowed: Pending, Building, Ready, Failed. |
prelaidDiskSizeGiB |
integer | The disk size, in GiB, the artifact was pre-laid for (ADR-0113), when spec.prelay was honoured: file is then the pre-laid image and checksum its digest, computed by the builder. Omitted otherwise. |
|
pvcRef |
object | Reference to the PVC kairos-operator created holding the built artifact, once known. Populated no earlier than phase Building. |
|
reason |
string | Short reason, mirroring the stable-string convention used elsewhere in this status (e.g. ImagePerProviderStatus.reason). |
.status.buildArtifact.ociArtifact¶
The same artifact, pushed to an OCI registry for providers that run
outside the cluster and cannot mount the artifacts PVC (ADR-0064).
Set only when a cloud-hypervisor Url source exists; None
otherwise, so installs without a host-resident provider need no
registry.
| Field | Type | Required | Description |
|---|---|---|---|
message |
string | Human-readable detail, e.g. why the push failed. | |
phase |
string | Yes | Current push phase. Allowed: Pushing, Ready, Failed. |
reference |
string | Digest-pinned reference, registry/repository@sha256:<hex>, once the push succeeded. Consumers pull by this digest and nothing else: integrity comes from content addressing, so a tag moved after the push cannot change what a host boots. |
.status.buildArtifact.pvcRef¶
Reference to the PVC kairos-operator created holding the built artifact,
once known. Populated no earlier than phase Building.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.status.conditions[]¶
Ready is True iff every per-provider entry is ready.
Written only by banlieue-controller (field manager
banlieue.io/controller), which is the only component with a
whole-image view. A provider cannot compute "ready everywhere" from
rows it does not own, so it writes its perProvider entry and nothing
here (ADR-0015). Merge-keyed on type, per Kubernetes convention.
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
.status.perProvider[]¶
Per-Provider readiness. One entry per Provider that supports this image's providerClass and has reconciled at least once.
Merge-keyed, and it must stay that way (ADR-0015). Several
providers write this list concurrently, each applying only its own
entry. Without x-kubernetes-list-type: map server-side apply treats
the array as atomic — one manager owns the whole thing and force()
hands it over wholesale, silently discarding every other provider's
row. That was a real, reproduced bug, not a theoretical one.
| Field | Type | Required | Description |
|---|---|---|---|
message |
string | Long human-readable detail. | |
providerName |
string | Yes | Name of the Provider. |
providerNamespace |
string | Yes | Namespace of the Provider. |
ready |
boolean | Yes | True when the image can be used to clone/create a VM on this provider. |
reason |
string | Short reason if not ready. Stable values from condition_reasons::IMAGE_*. |
|
resolvedRef |
string | Resolved concrete reference on the backend, for backends with one reference per provider. Proxmox: VMID. Libvirt: path. Unset for vSphere, whose per-zone references are in [Self::zones] (ADR-0104). |
|
zones |
object[] | Per-zone (per-Provider.status.failureDomains[]) readiness. Populated by the vSphere provider for both Url sources (import progress) and Template sources (whether the adopted template exists in each zone's folder, ADR-0104). For Url, ready means every zone is ready; for Template it means at least one zone is, and the scheduler places VMs only in ready zones. Empty for backends without zones (libvirt, Proxmox). |
.status.perProvider[].zones[]¶
Per-zone (per-Provider.status.failureDomains[]) readiness. Populated
by the vSphere provider for both Url sources (import progress) and
Template sources (whether the adopted template exists in each zone's
folder, ADR-0104). For Url, ready means every zone is ready; for
Template it means at least one zone is, and the scheduler places
VMs only in ready zones. Empty for backends without zones (libvirt,
Proxmox).
| Field | Type | Required | Description |
|---|---|---|---|
message |
string | ||
name |
string | Yes | Name of the failure domain, matching Provider.status.failureDomains[].name. |
ready |
boolean | Yes | True once the template is usable in this zone (import finished for Url; template found in the zone's folder for Template). |
reason |
string | ||
resolvedRef |
string | The template's bare display name within this zone once ready — the value a provider passes to a name-based template lookup. NOT a decorated string (no [dc]/folder prefix): the folder lives in [Self::template_folder], kept separate so a lookup can be built from structured fields instead of parsing this one. |
|
templateFolder |
string | The vCenter folder path (relative to the datacenter's VM folder, e.g. templates/cluster-01) the template in [Self::resolved_ref] lives in: <spec.template.rootFolder>/<zone> for both Url imports (ADR-0020 Decision #5) and Template sources (ADR-0104). Unset while the zone is not ready. |
CloudHypervisorMachine¶
API: infrastructure.banlieue.io/v1alpha1 · Kind: CloudHypervisorMachine · Scope: Namespaced · Short names: chm
CloudHypervisorMachine — the concrete, scheduled VM request for a Cloud Hypervisor host.
You normally do not create this by hand: banlieue's controller does, owned
by the VirtualMachine it was scheduled from, and the host-resident
provider on the chosen host runs it as a Cloud Hypervisor guest.
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| Provider | string | .spec.providerRef.name |
0 |
| Provisioned | boolean | .status.initialization.provisioned |
0 |
| Power | string | .status.observedPowerState |
0 |
| Image | string | .spec.bootSource.image |
1 |
| ProviderID | string | .spec.providerID |
1 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
bootSource |
object | Yes | Where the OS disk comes from. |
cpus |
object | Yes | Virtual CPUs. |
desiredPowerState |
string | Desired power state, resolved from the parent VirtualMachine. Allowed: PoweredOn, PoweredOff, Suspended. |
|
failureDomain |
string | CAPI contract (optional): failure domain placement. One host is one failure domain on this backend, as on libvirt. | |
firstBootSealing |
object | First-boot sealing the guest must report before GuestReady (ADR-0088, ADR-0112), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. The guest reports over its vsock (sealed= beside phase=installed). None for every other machine, which keeps today's GuestReady meaning unchanged. |
|
memory |
object | Yes | Guest memory. |
nics |
object[] | Yes | Network interfaces. |
osDiskSizeGiB |
integer | Yes | OS disk size in GiB. Required, and grown to before first boot; never shrunk. Must be at least the image's size. |
providerID |
string | CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: cloudhypervisor://<provider-name>/<machine-uid>. Set by the provider once the guest exists. |
|
providerRef |
object | Yes | The Provider for the one host that runs this machine (ADR-0060). |
storageClass |
string | Yes | Storage class the machine's disks live in. A name the host declares in its local config and publishes on its failure domain; never a path. |
tpmEnabled |
boolean | Attach a vTPM (swtpm), resolved from the VM's VMClass.spec.tpmEnabled. Requires [ChBootSourceKind::InstallMedia] (ADR-0040, ADR-0048, ADR-0065), or an image that seals itself on first boot ([Self::first_boot_sealing], ADR-0088, ADR-0112). |
|
userData |
string | Guest bootstrap payload, already resolved and placeholder-substituted by banlieue-controller (ADR-0025, ADR-0038). Rendered into a NoCloud CIDATA seed disk; the provider reads no Secret or ConfigMap. |
.spec.bootSource¶
Where the OS disk comes from.
| Field | Type | Required | Description |
|---|---|---|---|
image |
string | Yes | The image in the host's image cache: an installed raw disk for Image, the installer ISO for InstallMedia. |
kind |
string | Yes | Which provisioning shape this machine uses. Allowed: image, installMedia. |
.spec.cpus¶
Virtual CPUs.
| Field | Type | Required | Description |
|---|---|---|---|
boot |
integer | Yes | vCPUs the guest boots with. |
max |
integer | Hotplug headroom: the most vCPUs the guest may be resized to. Fixed when the VM is created. None means no headroom. |
.spec.firstBootSealing¶
First-boot sealing the guest must report before GuestReady
(ADR-0088, ADR-0112), copied by banlieue-controller from the parent
VirtualMachine's VMImage.spec.firstBootSealing when the class is
tpmEnabled. The guest reports over its vsock (sealed= beside
phase=installed). None for every other machine, which keeps
today's GuestReady meaning unchanged.
| Field | Type | Required | Description |
|---|---|---|---|
partitions |
string[] | Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal. |
|
timeoutSeconds |
integer | Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed. |
.spec.memory¶
Guest memory.
| Field | Type | Required | Description |
|---|---|---|---|
hugepages |
boolean | Back guest memory with hugepages. The host reports hugepages as their own capacity, since they are reserved rather than allocated on demand. | |
sizeMiB |
integer | Yes | Guest memory in MiB. |
.spec.nics[]¶
Network interfaces.
| Field | Type | Required | Description |
|---|---|---|---|
ipam |
object | Yes | IP address management for this interface. |
macAddress |
string | Optional MAC address. The provider derives a stable one from the machine UID otherwise, so the address survives a restart. | |
name |
string | Yes | Stable NIC name; echoed in status. |
networkClass |
string | Yes | Network class: a name the host resolves to one of its bridges. Never a bridge name from the cluster. |
.spec.nics[].ipam¶
IP address management for this interface.
| Field | Type | Required | Description |
|---|---|---|---|
pool |
object | Pool-based IPAM parameters. | |
static |
object | Static IPAM parameters (address, prefix, gateway, nameservers, domain). |
.spec.nics[].ipam.pool¶
Pool-based IPAM parameters.
| Field | Type | Required | Description |
|---|---|---|---|
poolRef |
object | Yes | Typed reference (apiGroup + kind + name + optional namespace). |
# .spec.nics[].ipam.pool.poolRef¶
Typed reference (apiGroup + kind + name + optional namespace).
Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we
want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's
default) or future banlieue-native pool types.
| Field | Type | Required | Description |
|---|---|---|---|
apiGroup |
string | Yes | |
kind |
string | Yes | |
name |
string | Yes | |
namespace |
string |
.spec.nics[].ipam.static¶
Static IPAM parameters (address, prefix, gateway, nameservers, domain).
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | |
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer | Yes |
.spec.providerRef¶
The Provider for the one host that runs this machine (ADR-0060).
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.status¶
Observed state of a CloudHypervisorMachine, shaped to the CAPI v1beta2
InfraMachine status contract. The non-contract fields mean what they mean
on LibvirtMachineStatus, so the controller's status mirror treats both
backends alike.
| Field | Type | Required | Description |
|---|---|---|---|
addressSource |
string | Which source answered the provider's address lookup. Allowed: static, neighbour. |
|
addresses |
object[] | CAPI contract field (optional): VM addresses. | |
conditions |
object[] | Standard Kubernetes conditions. | |
failureDomain |
string | CAPI contract field (optional): observed failure domain. | |
guestInstalled |
boolean | Whether the installed guest has announced itself (ADR-0043). Sticky once true. | |
hostUid |
integer | The unprivileged host uid this machine's units run as (ADR-0063 Decision 3). Recorded so the provider re-adopts a running guest without trusting its own memory. | |
initialization |
object | CAPI contract field. | |
installMediaDetached |
boolean | Whether the installer has been removed, live and for future starts (ADR-0044, ADR-0065 Decision 4). Sticky once true; None when there was never an installer. |
|
observedGeneration |
integer | The metadata.generation this status was computed from. |
|
observedPowerState |
string | The VM's last observed run state. Allowed: PoweredOn, PoweredOff, Suspended, null. |
|
sealedPartitions |
string[] | Partitions the guest has reported sealed, as LUKS containers, on a first-boot sealing machine (ADR-0088, ADR-0112): from the sealed= line of its vsock report. Sticky: the report is re-sent every boot, and a powered-off machine has not become unsealed. Empty until reported, and on every machine without spec.firstBootSealing. Guest-supplied, so it is only ever used to withhold GuestReady. |
|
tpmAttached |
boolean | Whether a vTPM was attached, when spec.tpmEnabled is set. |
|
tpmEndorsementCertificates |
string[] | PEM EK certificates, validated against this machine (ADR-0045, ADR-0065). |
.status.addresses[]¶
CAPI contract field (optional): VM addresses.
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | The address itself. |
type |
string | Yes | Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. |
.status.conditions[]¶
Standard Kubernetes conditions.
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
.status.initialization¶
CAPI contract field.
| Field | Type | Required | Description |
|---|---|---|---|
provisioned |
boolean | True when the infrastructure provider reports that the resource's infrastructure is fully provisioned. |
CloudHypervisorMachineTemplate¶
API: infrastructure.banlieue.io/v1alpha1 · Kind: CloudHypervisorMachineTemplate · Scope: Namespaced · Short names: chmt
CloudHypervisorMachineTemplate — a stamped-out CloudHypervisorMachine spec.
CAPI requires an InfraMachineTemplate so a MachineSet or MachineDeployment can mint identical machines. A spec template, not a disk template: nothing clones a guest, which is what keeps per-VM vTPMs unique (ADR-0040).
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
template |
object | Yes | The spec stamped into every machine created from this template. |
.spec.template¶
The spec stamped into every machine created from this template.
| Field | Type | Required | Description |
|---|---|---|---|
spec |
object | Yes | The CloudHypervisorMachine spec for machines created from this template. |
.spec.template.spec¶
The CloudHypervisorMachine spec for machines created from this template.
| Field | Type | Required | Description |
|---|---|---|---|
bootSource |
object | Yes | Where the OS disk comes from. |
cpus |
object | Yes | Virtual CPUs. |
desiredPowerState |
string | Desired power state, resolved from the parent VirtualMachine. Allowed: PoweredOn, PoweredOff, Suspended. |
|
failureDomain |
string | CAPI contract (optional): failure domain placement. One host is one failure domain on this backend, as on libvirt. | |
firstBootSealing |
object | First-boot sealing the guest must report before GuestReady (ADR-0088, ADR-0112), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. The guest reports over its vsock (sealed= beside phase=installed). None for every other machine, which keeps today's GuestReady meaning unchanged. |
|
memory |
object | Yes | Guest memory. |
nics |
object[] | Yes | Network interfaces. |
osDiskSizeGiB |
integer | Yes | OS disk size in GiB. Required, and grown to before first boot; never shrunk. Must be at least the image's size. |
providerID |
string | CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: cloudhypervisor://<provider-name>/<machine-uid>. Set by the provider once the guest exists. |
|
providerRef |
object | Yes | The Provider for the one host that runs this machine (ADR-0060). |
storageClass |
string | Yes | Storage class the machine's disks live in. A name the host declares in its local config and publishes on its failure domain; never a path. |
tpmEnabled |
boolean | Attach a vTPM (swtpm), resolved from the VM's VMClass.spec.tpmEnabled. Requires [ChBootSourceKind::InstallMedia] (ADR-0040, ADR-0048, ADR-0065), or an image that seals itself on first boot ([Self::first_boot_sealing], ADR-0088, ADR-0112). |
|
userData |
string | Guest bootstrap payload, already resolved and placeholder-substituted by banlieue-controller (ADR-0025, ADR-0038). Rendered into a NoCloud CIDATA seed disk; the provider reads no Secret or ConfigMap. |
.spec.template.spec.bootSource¶
Where the OS disk comes from.
| Field | Type | Required | Description |
|---|---|---|---|
image |
string | Yes | The image in the host's image cache: an installed raw disk for Image, the installer ISO for InstallMedia. |
kind |
string | Yes | Which provisioning shape this machine uses. Allowed: image, installMedia. |
.spec.template.spec.cpus¶
Virtual CPUs.
| Field | Type | Required | Description |
|---|---|---|---|
boot |
integer | Yes | vCPUs the guest boots with. |
max |
integer | Hotplug headroom: the most vCPUs the guest may be resized to. Fixed when the VM is created. None means no headroom. |
.spec.template.spec.firstBootSealing¶
First-boot sealing the guest must report before GuestReady
(ADR-0088, ADR-0112), copied by banlieue-controller from the parent
VirtualMachine's VMImage.spec.firstBootSealing when the class is
tpmEnabled. The guest reports over its vsock (sealed= beside
phase=installed). None for every other machine, which keeps
today's GuestReady meaning unchanged.
| Field | Type | Required | Description |
|---|---|---|---|
partitions |
string[] | Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal. |
|
timeoutSeconds |
integer | Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed. |
.spec.template.spec.memory¶
Guest memory.
| Field | Type | Required | Description |
|---|---|---|---|
hugepages |
boolean | Back guest memory with hugepages. The host reports hugepages as their own capacity, since they are reserved rather than allocated on demand. | |
sizeMiB |
integer | Yes | Guest memory in MiB. |
.spec.template.spec.nics[]¶
Network interfaces.
| Field | Type | Required | Description |
|---|---|---|---|
ipam |
object | Yes | IP address management for this interface. |
macAddress |
string | Optional MAC address. The provider derives a stable one from the machine UID otherwise, so the address survives a restart. | |
name |
string | Yes | Stable NIC name; echoed in status. |
networkClass |
string | Yes | Network class: a name the host resolves to one of its bridges. Never a bridge name from the cluster. |
# .spec.template.spec.nics[].ipam¶
IP address management for this interface.
| Field | Type | Required | Description |
|---|---|---|---|
pool |
object | Pool-based IPAM parameters. | |
static |
object | Static IPAM parameters (address, prefix, gateway, nameservers, domain). |
## .spec.template.spec.nics[].ipam.pool¶
Pool-based IPAM parameters.
| Field | Type | Required | Description |
|---|---|---|---|
poolRef |
object | Yes | Typed reference (apiGroup + kind + name + optional namespace). |
### .spec.template.spec.nics[].ipam.pool.poolRef¶
Typed reference (apiGroup + kind + name + optional namespace).
Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we
want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's
default) or future banlieue-native pool types.
| Field | Type | Required | Description |
|---|---|---|---|
apiGroup |
string | Yes | |
kind |
string | Yes | |
name |
string | Yes | |
namespace |
string |
## .spec.template.spec.nics[].ipam.static¶
Static IPAM parameters (address, prefix, gateway, nameservers, domain).
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | |
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer | Yes |
.spec.template.spec.providerRef¶
The Provider for the one host that runs this machine (ADR-0060).
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
LibvirtMachine¶
API: infrastructure.banlieue.io/v1alpha1 · Kind: LibvirtMachine · Scope: Namespaced · Short names: lvm
LibvirtMachine — the concrete, scheduled VM request for a libvirt/KVM host.
You normally do not create this by hand: banlieue's controller does, owned
by the VirtualMachine it was scheduled from, and the libvirt provider
reconciles it into a real domain.
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| Provider | string | .spec.providerRef.name |
0 |
| Provisioned | boolean | .status.initialization.provisioned |
0 |
| Power | string | .status.observedPowerState |
0 |
| Domain | string | .spec.domainName |
1 |
| ProviderID | string | .spec.providerID |
1 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
bootSource |
object | Yes | How this machine's OS disk comes into being. |
desiredPowerState |
string | Desired power state, resolved from the parent VirtualMachine's spec.desiredPowerState (ADR-0024). Allowed: PoweredOn, PoweredOff, Suspended. |
|
disks |
object[] | Yes | Disks. The first is the OS disk; the rest are blank data disks. |
domainName |
string | Yes | libvirt domain name. Unique per host, and the handle every domain procedure takes. |
failureDomain |
string | CAPI contract (optional): failure domain placement. The banlieue scheduler writes the chosen failure domain here. | |
firmware |
string | Yes | Firmware. EFI requires OVMF on the host; EfiSecure additionally requires a .secboot.fd variant and pre-enrolled keys. Allowed: bios, efi, efi-secure. |
firstBootSealing |
object | First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged. |
|
machineType |
string | QEMU machine type (q35, pc, …). None lets libvirt pick its default for the host's architecture, which is the right answer unless an image needs a specific chipset. |
|
memoryMiB |
integer | Yes | Memory in MiB. |
network |
object[] | Yes | Network interfaces. |
pool |
string | Yes | Storage pool that holds this machine's volumes, resolved from the storage class by the scheduler. |
providerID |
string | CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: libvirt://<provider-name>/<domain-uuid>. Set by the provider controller after the domain is defined. |
|
providerRef |
object | Yes | Reference to the banlieue Provider whose connection details describe the target libvirt host. |
tpmEnabled |
boolean | Attach an emulated TPM 2.0 device (swtpm), resolved from the VM's VMClass.spec.tpmEnabled (ADR-0039). |
|
userData |
string | Guest bootstrap payload, already resolved from the parent VirtualMachine's spec.userData Secret or ConfigMap (ADR-0038) and placeholder-substituted by banlieue-controller (ADR-0025). The provider renders it into a NoCloud cidata volume — it never reads a Secret or ConfigMap itself. |
|
vcpus |
integer | Yes | Number of virtual CPUs. |
.spec.bootSource¶
How this machine's OS disk comes into being.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
string | Yes | Which of the two provisioning shapes this machine uses. Allowed: backingVolume, installMedia. |
volume |
string | Yes | Volume name within [LibvirtMachineSpec::pool]: the backing image for BackingVolume, or the installer ISO for InstallMedia. |
.spec.disks[]¶
Disks. The first is the OS disk; the rest are blank data disks.
| Field | Type | Required | Description |
|---|---|---|---|
bus |
string | Controller bus. Allowed: virtio, scsi, sata. |
|
name |
string | Yes | Stable disk name; echoed in status and used to name the volume. |
sizeGiB |
integer | Yes | Disk size in GiB. For an overlay OS disk this is a floor — the overlay is created at least this large. |
.spec.firstBootSealing¶
First-boot sealing the guest must report before GuestReady
(ADR-0088), copied by banlieue-controller from the parent
VirtualMachine's VMImage.spec.firstBootSealing when the class is
tpmEnabled. None for every other machine, which keeps today's
GuestReady meaning unchanged.
| Field | Type | Required | Description |
|---|---|---|---|
partitions |
string[] | Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal. |
|
timeoutSeconds |
integer | Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed. |
.spec.network[]¶
Network interfaces.
| Field | Type | Required | Description |
|---|---|---|---|
ipam |
object | Yes | IP address management for this interface. |
macAddress |
string | Optional MAC address (otherwise libvirt generates one). | |
model |
string | Device model. None means virtio, which is what every image banlieue builds expects. |
|
name |
string | Yes | Stable NIC name; echoed in status. |
source |
object | Yes | Resolved bridge or libvirt network. |
.spec.network[].ipam¶
IP address management for this interface.
| Field | Type | Required | Description |
|---|---|---|---|
pool |
object | Pool-based IPAM parameters. | |
static |
object | Static IPAM parameters (address, prefix, gateway, nameservers, domain). |
.spec.network[].ipam.pool¶
Pool-based IPAM parameters.
| Field | Type | Required | Description |
|---|---|---|---|
poolRef |
object | Yes | Typed reference (apiGroup + kind + name + optional namespace). |
# .spec.network[].ipam.pool.poolRef¶
Typed reference (apiGroup + kind + name + optional namespace).
Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we
want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's
default) or future banlieue-native pool types.
| Field | Type | Required | Description |
|---|---|---|---|
apiGroup |
string | Yes | |
kind |
string | Yes | |
name |
string | Yes | |
namespace |
string |
.spec.network[].ipam.static¶
Static IPAM parameters (address, prefix, gateway, nameservers, domain).
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | |
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer | Yes |
.spec.network[].source¶
Resolved bridge or libvirt network.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
string | Yes | Whether name names a host bridge or a libvirt network. Allowed: network, bridge. |
name |
string | Yes | The bridge interface (br0) or libvirt network (default). |
.spec.providerRef¶
Reference to the banlieue Provider whose connection details describe
the target libvirt host.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.status¶
Observed state of a LibvirtMachine, shaped to the CAPI v1beta2 InfraMachine status contract (plus libvirt-specific diagnostics).
| Field | Type | Required | Description |
|---|---|---|---|
addressSource |
string | Which source answered when the provider looked up the guest's addresses (ADR-0050 Decision 8). Allowed: guestAgent, dhcpLease, arpTable, static. |
|
addresses |
object[] | CAPI contract field (optional): VM addresses. | |
conditions |
object[] | CAPI-compatible conditions. The Ready condition is mirrored as InfrastructureReady on the parent per contract. |
|
domainUuid |
string | libvirt's UUID for the domain, in its 36-character textual form. The domain's real identity — stable across rename and host restart — and the source for spec.providerID. Not part of the CAPI contract. |
|
failureDomain |
string | CAPI contract field (optional): observed failure domain — the host the domain actually landed on. | |
guestInstalled |
boolean | Whether the installed guest has announced itself (ADR-0043). | |
initialization |
object | CAPI contract field: replaces the deprecated v1beta1 status.ready. |
|
installMediaDetached |
boolean | Whether the install medium has been ejected (ADR-0044). | |
observedGeneration |
integer | ||
observedPowerState |
string | The domain's last observed run state, mapped onto banlieue's backend-neutral [PowerState] (ADR-0034). The hypervisor's view, not a guest-OS-boot signal. Not part of the CAPI contract; mirrored onto the parent VirtualMachine's status.observedPowerState. Allowed: PoweredOn, PoweredOff, Suspended, null. |
|
sealedPartitions |
string[] | Partitions the guest has reported sealed, as LUKS containers, on a first-boot sealing machine (ADR-0088): from `/run/banlieue/sealed, read with the guest agent. **Sticky**: the report is re-asserted every boot but lives in volatile state, and a powered-off machine has not become unsealed. Empty until reported, and on every machine withoutspec.firstBootSealing. Guest-supplied, so it is only ever used to *withhold*GuestReady`. |
|
tpmAttached |
boolean | Whether an emulated TPM was attached, when spec.tpmEnabled is set (ADR-0039). None when tpmEnabled is false or the attach has not run yet. A failed attach surfaces through the conditions rather than a dedicated VirtualMachine-level mirror. |
|
tpmEndorsementCertificates |
string[] | PEM vTPM endorsement key certificate(s) reported by the guest and validated against this domain (ADR-0045). |
.status.addresses[]¶
CAPI contract field (optional): VM addresses.
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | The address itself. |
type |
string | Yes | Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. |
.status.conditions[]¶
CAPI-compatible conditions. The Ready condition is mirrored as
InfrastructureReady on the parent per contract.
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
.status.initialization¶
CAPI contract field: replaces the deprecated v1beta1 status.ready.
| Field | Type | Required | Description |
|---|---|---|---|
provisioned |
boolean | True when the infrastructure provider reports that the resource's infrastructure is fully provisioned. |
LibvirtMachineTemplate¶
API: infrastructure.banlieue.io/v1alpha1 · Kind: LibvirtMachineTemplate · Scope: Namespaced · Short names: lvmt
LibvirtMachineTemplate — a stamped-out LibvirtMachine spec.
CAPI requires an InfraMachineTemplate so higher-level controllers (a MachineSet / MachineDeployment) can mint many identical machines from one template. banlieue ships it for CAPI compatibility; standalone VirtualMachine users do not need it.
Note that a template is a spec template, not a disk template: nothing here clones a domain. That distinction matters on libvirt, because cloning a domain that carries TPM state would copy the state too, which is precisely ADR-0040's shared-vTPM problem.
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
template |
object | Yes | The LibvirtMachine spec stamped into every machine created from this template. |
.spec.template¶
The LibvirtMachine spec stamped into every machine created from this template.
| Field | Type | Required | Description |
|---|---|---|---|
spec |
object | Yes | The LibvirtMachine spec for machines created from this template. |
.spec.template.spec¶
The LibvirtMachine spec for machines created from this template.
| Field | Type | Required | Description |
|---|---|---|---|
bootSource |
object | Yes | How this machine's OS disk comes into being. |
desiredPowerState |
string | Desired power state, resolved from the parent VirtualMachine's spec.desiredPowerState (ADR-0024). Allowed: PoweredOn, PoweredOff, Suspended. |
|
disks |
object[] | Yes | Disks. The first is the OS disk; the rest are blank data disks. |
domainName |
string | Yes | libvirt domain name. Unique per host, and the handle every domain procedure takes. |
failureDomain |
string | CAPI contract (optional): failure domain placement. The banlieue scheduler writes the chosen failure domain here. | |
firmware |
string | Yes | Firmware. EFI requires OVMF on the host; EfiSecure additionally requires a .secboot.fd variant and pre-enrolled keys. Allowed: bios, efi, efi-secure. |
firstBootSealing |
object | First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged. |
|
machineType |
string | QEMU machine type (q35, pc, …). None lets libvirt pick its default for the host's architecture, which is the right answer unless an image needs a specific chipset. |
|
memoryMiB |
integer | Yes | Memory in MiB. |
network |
object[] | Yes | Network interfaces. |
pool |
string | Yes | Storage pool that holds this machine's volumes, resolved from the storage class by the scheduler. |
providerID |
string | CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: libvirt://<provider-name>/<domain-uuid>. Set by the provider controller after the domain is defined. |
|
providerRef |
object | Yes | Reference to the banlieue Provider whose connection details describe the target libvirt host. |
tpmEnabled |
boolean | Attach an emulated TPM 2.0 device (swtpm), resolved from the VM's VMClass.spec.tpmEnabled (ADR-0039). |
|
userData |
string | Guest bootstrap payload, already resolved from the parent VirtualMachine's spec.userData Secret or ConfigMap (ADR-0038) and placeholder-substituted by banlieue-controller (ADR-0025). The provider renders it into a NoCloud cidata volume — it never reads a Secret or ConfigMap itself. |
|
vcpus |
integer | Yes | Number of virtual CPUs. |
.spec.template.spec.bootSource¶
How this machine's OS disk comes into being.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
string | Yes | Which of the two provisioning shapes this machine uses. Allowed: backingVolume, installMedia. |
volume |
string | Yes | Volume name within [LibvirtMachineSpec::pool]: the backing image for BackingVolume, or the installer ISO for InstallMedia. |
.spec.template.spec.disks[]¶
Disks. The first is the OS disk; the rest are blank data disks.
| Field | Type | Required | Description |
|---|---|---|---|
bus |
string | Controller bus. Allowed: virtio, scsi, sata. |
|
name |
string | Yes | Stable disk name; echoed in status and used to name the volume. |
sizeGiB |
integer | Yes | Disk size in GiB. For an overlay OS disk this is a floor — the overlay is created at least this large. |
.spec.template.spec.firstBootSealing¶
First-boot sealing the guest must report before GuestReady
(ADR-0088), copied by banlieue-controller from the parent
VirtualMachine's VMImage.spec.firstBootSealing when the class is
tpmEnabled. None for every other machine, which keeps today's
GuestReady meaning unchanged.
| Field | Type | Required | Description |
|---|---|---|---|
partitions |
string[] | Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal. |
|
timeoutSeconds |
integer | Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed. |
.spec.template.spec.network[]¶
Network interfaces.
| Field | Type | Required | Description |
|---|---|---|---|
ipam |
object | Yes | IP address management for this interface. |
macAddress |
string | Optional MAC address (otherwise libvirt generates one). | |
model |
string | Device model. None means virtio, which is what every image banlieue builds expects. |
|
name |
string | Yes | Stable NIC name; echoed in status. |
source |
object | Yes | Resolved bridge or libvirt network. |
# .spec.template.spec.network[].ipam¶
IP address management for this interface.
| Field | Type | Required | Description |
|---|---|---|---|
pool |
object | Pool-based IPAM parameters. | |
static |
object | Static IPAM parameters (address, prefix, gateway, nameservers, domain). |
## .spec.template.spec.network[].ipam.pool¶
Pool-based IPAM parameters.
| Field | Type | Required | Description |
|---|---|---|---|
poolRef |
object | Yes | Typed reference (apiGroup + kind + name + optional namespace). |
### .spec.template.spec.network[].ipam.pool.poolRef¶
Typed reference (apiGroup + kind + name + optional namespace).
Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we
want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's
default) or future banlieue-native pool types.
| Field | Type | Required | Description |
|---|---|---|---|
apiGroup |
string | Yes | |
kind |
string | Yes | |
name |
string | Yes | |
namespace |
string |
## .spec.template.spec.network[].ipam.static¶
Static IPAM parameters (address, prefix, gateway, nameservers, domain).
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | |
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer | Yes |
# .spec.template.spec.network[].source¶
Resolved bridge or libvirt network.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
string | Yes | Whether name names a host bridge or a libvirt network. Allowed: network, bridge. |
name |
string | Yes | The bridge interface (br0) or libvirt network (default). |
.spec.template.spec.providerRef¶
Reference to the banlieue Provider whose connection details describe
the target libvirt host.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
ProxmoxMachine¶
API: infrastructure.banlieue.io/v1alpha1 · Kind: ProxmoxMachine · Scope: Namespaced · Short names: pvem
ProxmoxMachine — the concrete, scheduled VM request for the Proxmox backend.
You normally do not create this by hand: banlieue's controller does, owned
by the VirtualMachine it was scheduled from, and the Proxmox provider
clones the template into a VM and reports CAPI-shaped status.
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| Provider | string | .spec.providerRef.name |
0 |
| Node | string | .status.node |
0 |
| VMID | integer | .status.vmid |
0 |
| Provisioned | boolean | .status.initialization.provisioned |
0 |
| Power | string | .status.observedPowerState |
0 |
| ProviderID | string | .spec.providerID |
1 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
cores |
integer | Yes | Cores per socket. |
cpuType |
string | CPU model (host, x86-64-v2-AES, …). Proxmox's default applies when absent. |
|
dataDisks |
object[] | Additional blank disks, attached after the OS disk. | |
desiredPowerState |
string | Desired power state, resolved from the parent VirtualMachine. Allowed: PoweredOn, PoweredOff, Suspended. |
|
failureDomain |
string | CAPI contract (optional): failure domain placement. One node is one failure domain (roadmap 06). | |
firmware |
string | Firmware: bios selects SeaBIOS; efi and efi-secure select OVMF, the latter with Microsoft/distribution keys pre-enrolled. The template must be able to boot the chosen firmware. Allowed: bios, efi, efi-secure. |
|
isoStorage |
string | Storage the NoCloud seed ISO is uploaded to. Must allow iso content. Required whenever userData is set. |
|
memoryMiB |
integer | Yes | Memory in MiB. |
nics |
object[] | Yes | Network interfaces. |
node |
string | Yes | Node the VM is created on (resolved from the failure domain). |
osDiskSizeGiB |
integer | Yes | OS disk size in GiB: the cloned disk is grown to at least this, never shrunk. |
pool |
string | Proxmox resource pool to place the VM in. | |
providerID |
string | CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: proxmox://<provider-name>/<vmid>. Set by the provider once the VM exists. |
|
providerRef |
object | Yes | The Provider whose connection describes the target Proxmox cluster. |
sockets |
integer | CPU sockets. | |
storage |
string | Yes | Storage id for the cloned and new disks (resolved from the storage class). Must allow images content. |
templateVmid |
integer | Yes | VMID of the template VM to clone. Must be a template (ADR-0075 Decision 5a); the provider checks before cloning. |
tpmEnabled |
boolean | Attach a vTPM 2.0 (tpmstate0 on storage), resolved from VMClass.spec.tpmEnabled and attached before first boot. |
|
userData |
string | Guest bootstrap payload, already resolved and placeholder-substituted by banlieue-controller (ADR-0025, ADR-0038). Rendered into a NoCloud CIDATA ISO (ADR-0054); the provider reads no Secret or ConfigMap. |
.spec.dataDisks[]¶
Additional blank disks, attached after the OS disk.
| Field | Type | Required | Description |
|---|---|---|---|
discard |
boolean | Pass TRIM/discard to the storage. | |
iothread |
boolean | Dedicated I/O thread (virtio-scsi-single). | |
name |
string | Yes | Stable disk name; echoed in status. |
sizeGiB |
integer | Yes | Size in GiB. |
ssd |
boolean | Present as an SSD to the guest. | |
storage |
string | Storage id; defaults to the machine's storage. |
.spec.nics[]¶
Network interfaces.
| Field | Type | Required | Description |
|---|---|---|---|
bridge |
string | Yes | Bridge on the node (resolved from the network class), e.g. vmbr0. |
ipam |
object | Yes | IP address management for this interface. |
macAddress |
string | Optional MAC address (Proxmox generates one otherwise). | |
model |
string | Emulated NIC model. Allowed: virtio, e1000, rtl8139, vmxnet3. |
|
name |
string | Yes | Stable NIC name; echoed in status. |
vlan |
integer | 802.1Q VLAN tag. |
.spec.nics[].ipam¶
IP address management for this interface.
| Field | Type | Required | Description |
|---|---|---|---|
pool |
object | Pool-based IPAM parameters. | |
static |
object | Static IPAM parameters (address, prefix, gateway, nameservers, domain). |
.spec.nics[].ipam.pool¶
Pool-based IPAM parameters.
| Field | Type | Required | Description |
|---|---|---|---|
poolRef |
object | Yes | Typed reference (apiGroup + kind + name + optional namespace). |
# .spec.nics[].ipam.pool.poolRef¶
Typed reference (apiGroup + kind + name + optional namespace).
Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we
want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's
default) or future banlieue-native pool types.
| Field | Type | Required | Description |
|---|---|---|---|
apiGroup |
string | Yes | |
kind |
string | Yes | |
name |
string | Yes | |
namespace |
string |
.spec.nics[].ipam.static¶
Static IPAM parameters (address, prefix, gateway, nameservers, domain).
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | |
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer | Yes |
.spec.providerRef¶
The Provider whose connection describes the target Proxmox cluster.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.status¶
Observed state of a ProxmoxMachine, shaped to the CAPI v1beta2 InfraMachine status contract. The non-contract fields mean what they mean on the siblings, so the controller's status mirror treats backends alike.
| Field | Type | Required | Description |
|---|---|---|---|
addressSource |
string | Which source produced a machine's addresses. Allowed: static, guestAgent. |
|
addresses |
object[] | CAPI contract field (optional): VM addresses. | |
conditions |
object[] | Standard Kubernetes conditions. | |
failureDomain |
string | CAPI contract field (optional): observed failure domain. | |
initialization |
object | CAPI contract field. | |
node |
string | The node the VM was last seen on; a migration changes it. | |
observedGeneration |
integer | The metadata.generation this status was computed from. |
|
observedPowerState |
string | The VM's last observed run state. Allowed: PoweredOn, PoweredOff, Suspended, null. |
|
tpmAttached |
boolean | Whether a vTPM was attached, when spec.tpmEnabled is set. |
|
vmid |
integer | The VMID, recorded before the clone so a crash cannot allocate a second VM (ADR-0075 Decision 4). A cache, not the source of truth: the VM's name is the ownership marker. |
.status.addresses[]¶
CAPI contract field (optional): VM addresses.
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | The address itself. |
type |
string | Yes | Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. |
.status.conditions[]¶
Standard Kubernetes conditions.
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
.status.initialization¶
CAPI contract field.
| Field | Type | Required | Description |
|---|---|---|---|
provisioned |
boolean | True when the infrastructure provider reports that the resource's infrastructure is fully provisioned. |
ProxmoxMachineTemplate¶
API: infrastructure.banlieue.io/v1alpha1 · Kind: ProxmoxMachineTemplate · Scope: Namespaced · Short names: pvemt
ProxmoxMachineTemplate — a stamped-out ProxmoxMachine spec.
CAPI requires an InfraMachineTemplate so a MachineSet or MachineDeployment can mint identical machines. banlieue ships it for CAPI compatibility; standalone VirtualMachine users do not need it.
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
template |
object | Yes | The spec stamped into every machine created from this template. |
.spec.template¶
The spec stamped into every machine created from this template.
| Field | Type | Required | Description |
|---|---|---|---|
spec |
object | Yes | The ProxmoxMachine spec for machines created from this template. |
.spec.template.spec¶
The ProxmoxMachine spec for machines created from this template.
| Field | Type | Required | Description |
|---|---|---|---|
cores |
integer | Yes | Cores per socket. |
cpuType |
string | CPU model (host, x86-64-v2-AES, …). Proxmox's default applies when absent. |
|
dataDisks |
object[] | Additional blank disks, attached after the OS disk. | |
desiredPowerState |
string | Desired power state, resolved from the parent VirtualMachine. Allowed: PoweredOn, PoweredOff, Suspended. |
|
failureDomain |
string | CAPI contract (optional): failure domain placement. One node is one failure domain (roadmap 06). | |
firmware |
string | Firmware: bios selects SeaBIOS; efi and efi-secure select OVMF, the latter with Microsoft/distribution keys pre-enrolled. The template must be able to boot the chosen firmware. Allowed: bios, efi, efi-secure. |
|
isoStorage |
string | Storage the NoCloud seed ISO is uploaded to. Must allow iso content. Required whenever userData is set. |
|
memoryMiB |
integer | Yes | Memory in MiB. |
nics |
object[] | Yes | Network interfaces. |
node |
string | Yes | Node the VM is created on (resolved from the failure domain). |
osDiskSizeGiB |
integer | Yes | OS disk size in GiB: the cloned disk is grown to at least this, never shrunk. |
pool |
string | Proxmox resource pool to place the VM in. | |
providerID |
string | CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: proxmox://<provider-name>/<vmid>. Set by the provider once the VM exists. |
|
providerRef |
object | Yes | The Provider whose connection describes the target Proxmox cluster. |
sockets |
integer | CPU sockets. | |
storage |
string | Yes | Storage id for the cloned and new disks (resolved from the storage class). Must allow images content. |
templateVmid |
integer | Yes | VMID of the template VM to clone. Must be a template (ADR-0075 Decision 5a); the provider checks before cloning. |
tpmEnabled |
boolean | Attach a vTPM 2.0 (tpmstate0 on storage), resolved from VMClass.spec.tpmEnabled and attached before first boot. |
|
userData |
string | Guest bootstrap payload, already resolved and placeholder-substituted by banlieue-controller (ADR-0025, ADR-0038). Rendered into a NoCloud CIDATA ISO (ADR-0054); the provider reads no Secret or ConfigMap. |
.spec.template.spec.dataDisks[]¶
Additional blank disks, attached after the OS disk.
| Field | Type | Required | Description |
|---|---|---|---|
discard |
boolean | Pass TRIM/discard to the storage. | |
iothread |
boolean | Dedicated I/O thread (virtio-scsi-single). | |
name |
string | Yes | Stable disk name; echoed in status. |
sizeGiB |
integer | Yes | Size in GiB. |
ssd |
boolean | Present as an SSD to the guest. | |
storage |
string | Storage id; defaults to the machine's storage. |
.spec.template.spec.nics[]¶
Network interfaces.
| Field | Type | Required | Description |
|---|---|---|---|
bridge |
string | Yes | Bridge on the node (resolved from the network class), e.g. vmbr0. |
ipam |
object | Yes | IP address management for this interface. |
macAddress |
string | Optional MAC address (Proxmox generates one otherwise). | |
model |
string | Emulated NIC model. Allowed: virtio, e1000, rtl8139, vmxnet3. |
|
name |
string | Yes | Stable NIC name; echoed in status. |
vlan |
integer | 802.1Q VLAN tag. |
# .spec.template.spec.nics[].ipam¶
IP address management for this interface.
| Field | Type | Required | Description |
|---|---|---|---|
pool |
object | Pool-based IPAM parameters. | |
static |
object | Static IPAM parameters (address, prefix, gateway, nameservers, domain). |
## .spec.template.spec.nics[].ipam.pool¶
Pool-based IPAM parameters.
| Field | Type | Required | Description |
|---|---|---|---|
poolRef |
object | Yes | Typed reference (apiGroup + kind + name + optional namespace). |
### .spec.template.spec.nics[].ipam.pool.poolRef¶
Typed reference (apiGroup + kind + name + optional namespace).
Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we
want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's
default) or future banlieue-native pool types.
| Field | Type | Required | Description |
|---|---|---|---|
apiGroup |
string | Yes | |
kind |
string | Yes | |
name |
string | Yes | |
namespace |
string |
## .spec.template.spec.nics[].ipam.static¶
Static IPAM parameters (address, prefix, gateway, nameservers, domain).
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | |
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer | Yes |
.spec.template.spec.providerRef¶
The Provider whose connection describes the target Proxmox cluster.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
VSphereCluster¶
API: infrastructure.banlieue.io/v1alpha1 · Kind: VSphereCluster · Scope: Namespaced · Short names: vsc
VSphereCluster — banlieue's CAPI v1beta2 InfraCluster for vSphere backends.
It tells CAPI where a cluster's machines may be placed by aggregating the
failure domains of one or more Providers (vCenters) into the CAPI-shaped
status.failureDomains list. The control-plane endpoint is operator-supplied
(a VIP) or filled in by the control-plane provider (e.g. k0smotron).
Why it exists
- Cluster-side failure-domain spread. CAPI's control-plane / MachineSet
controllers balance machines across the FDs published here. "Spread across
all 6 domains" is simply
replicas: 6over aVSphereClusterthat advertises 6 FDs. - Multi-vCenter clusters. One Kubernetes cluster can span several
Providers — a capability beyond single-vCenter CAPV.
You do not create the resulting VMs by hand; CAPI mints VSphereMachines
(the InfraMachine) from a VSphereMachineTemplate. This object only
advertises where they may go.
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| Provisioned | boolean | .status.initialization.provisioned |
0 |
| Endpoint | string | .status.controlPlaneEndpoint.host |
1 |
| Ready | string | .status.conditions[?(@.type=='Ready')].status |
0 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
controlPlaneEndpoint |
object | CAPI contract (optional): the cluster's API-server endpoint. Operator- supplied control-plane VIP, or left unset for a control-plane provider (e.g. k0smotron) to manage. Mirrored to status.controlPlaneEndpoint. |
|
controlPlaneFailureDomainSelector |
object | Which aggregated failure domains are eligible to run control-plane nodes, matched against the Provider FD labels. When unset, all aggregated FDs are control-plane eligible. Use this to keep the etcd quorum to a bounded, odd set of domains while workers spread wider. |
|
paused |
boolean | Suspend reconciliation. Equivalent to the cluster.x-k8s.io/paused annotation but in-band. |
|
providerRefs |
object[] | Explicit list of Providers (in this namespace) to aggregate. Takes precedence over providerSelector when non-empty. Declaring the set explicitly is the preferred, "explicit over implicit" form. |
|
providerSelector |
object | Select Providers (in this namespace) to aggregate failure domains from, by matching their labels. Ignored when providerRefs is set. |
.spec.controlPlaneEndpoint¶
CAPI contract (optional): the cluster's API-server endpoint. Operator-
supplied control-plane VIP, or left unset for a control-plane provider
(e.g. k0smotron) to manage. Mirrored to status.controlPlaneEndpoint.
| Field | Type | Required | Description |
|---|---|---|---|
host |
string | Yes | Hostname or IP on which the API server is serving. |
port |
integer | Yes | Port on which the API server is serving. |
.spec.controlPlaneFailureDomainSelector¶
Which aggregated failure domains are eligible to run control-plane
nodes, matched against the Provider FD labels. When unset, all
aggregated FDs are control-plane eligible. Use this to keep the etcd
quorum to a bounded, odd set of domains while workers spread wider.
| Field | Type | Required | Description |
|---|---|---|---|
matchExpressions |
object[] | ||
matchLabels |
map[string]string |
.spec.controlPlaneFailureDomainSelector.matchExpressions[]¶
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | |
operator |
string | Yes | Allowed: In, NotIn, Exists, DoesNotExist. |
values |
string[] |
.spec.providerRefs[]¶
Explicit list of Providers (in this namespace) to aggregate. Takes
precedence over providerSelector when non-empty. Declaring the set
explicitly is the preferred, "explicit over implicit" form.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.spec.providerSelector¶
Select Providers (in this namespace) to aggregate failure domains
from, by matching their labels. Ignored when providerRefs is set.
| Field | Type | Required | Description |
|---|---|---|---|
matchExpressions |
object[] | ||
matchLabels |
map[string]string |
.spec.providerSelector.matchExpressions[]¶
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | |
operator |
string | Yes | Allowed: In, NotIn, Exists, DoesNotExist. |
values |
string[] |
.status¶
Observed state of a VSphereCluster, shaped to the CAPI v1beta2 InfraCluster status contract.
| Field | Type | Required | Description |
|---|---|---|---|
conditions |
object[] | CAPI-compatible conditions. The Ready condition is mirrored to the parent Cluster's InfrastructureReady; Paused reflects pause state. |
|
controlPlaneEndpoint |
object | CAPI contract field (optional): the resolved API-server endpoint, echoed from spec.controlPlaneEndpoint or set by the control-plane provider. |
|
failureDomains |
object[] | CAPI contract field: the failure domains machines may be placed in, aggregated from the selected Providers. A list per v1beta2. |
|
initialization |
object | CAPI contract field: replaces the deprecated v1beta1 status.ready. provisioned == true once the failure domains are resolved (and the control-plane endpoint is known, when one is required). |
|
observedGeneration |
integer | The generation of the spec the controller has reconciled. |
.status.conditions[]¶
CAPI-compatible conditions. The Ready condition is mirrored to the
parent Cluster's InfrastructureReady; Paused reflects pause state.
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
.status.controlPlaneEndpoint¶
CAPI contract field (optional): the resolved API-server endpoint,
echoed from spec.controlPlaneEndpoint or set by the control-plane
provider.
| Field | Type | Required | Description |
|---|---|---|---|
host |
string | Yes | Hostname or IP on which the API server is serving. |
port |
integer | Yes | Port on which the API server is serving. |
.status.failureDomains[]¶
CAPI contract field: the failure domains machines may be placed in,
aggregated from the selected Providers. A list per v1beta2.
| Field | Type | Required | Description |
|---|---|---|---|
attributes |
map[string]string | Arbitrary attributes for consumers. banlieue flattens the Provider FD's attributes.raw plus dc/cluster labels into this map. |
|
controlPlane |
boolean | Whether this failure domain is eligible to run control-plane nodes. None is treated by CAPI as "not control-plane eligible". |
|
name |
string | Yes | Unique failure-domain name (one of the Provider's status.failureDomains[].name). |
.status.initialization¶
CAPI contract field: replaces the deprecated v1beta1 status.ready.
provisioned == true once the failure domains are resolved (and the
control-plane endpoint is known, when one is required).
| Field | Type | Required | Description |
|---|---|---|---|
provisioned |
boolean | True when the infrastructure provider reports that the resource's infrastructure is fully provisioned. |
VSphereMachine¶
API: infrastructure.banlieue.io/v1alpha1 · Kind: VSphereMachine · Scope: Namespaced · Short names: vsm
VSphereMachine — the concrete, scheduled VM request for the vSphere backend.
This is banlieue's reference implementation of the CAPI v1beta2
InfraMachine contract. Where a VirtualMachine is abstract, every field here
is already resolved: a real vCenter template, datacenter, cluster,
datastore, and per-NIC portGroup. banlieue's main controller creates it
after scheduling; the vSphere provider reconciles it into a real VM and
reports CAPI-shaped status.
Why it exists
- It is the hand-off. A VirtualMachine says "an ubuntu db-prod VM somewhere reasonable"; a VSphereMachine says "clone template X in DC0 / cluster C0 onto datastore ds-fast-01" — the thing a provider can actually execute.
- CAPI-compatible by contract. Because it satisfies the InfraMachine
contract, it doubles as a Cluster API infrastructure provider: a
clusterv1.MachinewithinfrastructureRef.kind: VSphereMachinedrives it the same way.
You normally do not create this by hand — the controller does, owned by the
VirtualMachine. The CAPI contract label
cluster.x-k8s.io/v1beta2: v1alpha1 is emitted onto the generated CRD by
crdgen, since kube-derive cannot set CRD-level labels (ADR-0005).
Printer columns (kubectl get):
| Name | Type | JSON path | Priority |
|---|---|---|---|
| Provider | string | .spec.providerRef.name |
0 |
| Provisioned | boolean | .status.initialization.provisioned |
0 |
| Power | string | .status.observedPowerState |
0 |
| ProviderID | string | .spec.providerID |
1 |
| Cluster | string | .spec.cluster |
1 |
| Age | date | .metadata.creationTimestamp |
0 |
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
cluster |
string | Yes | Compute cluster within the datacenter. |
createdBy |
string | The principal that created the parent VirtualMachine, copied from its banlieue.io/created-by annotation when present (ADR-0089). That annotation is stamped by an optional MutatingAdmissionPolicy (deploy/admission/virtualmachine-created-by.yaml) from request.userInfo.username at VirtualMachine CREATE — None on a cluster that doesn't apply it, or for a VirtualMachine that predates it. Surfaced as the vCenter CreatedBy custom attribute by the provider; never a stand-in value when absent. |
|
datacenter |
string | Yes | Datacenter name. |
datastore |
string | Yes | Datastore or datastore cluster name (resolved from the storage class). |
desiredPowerState |
string | Desired power state, resolved from the parent VirtualMachine's spec.desiredPowerState (ADR-0024). Defaults to PoweredOn, matching VirtualMachineSpec's own default. Allowed: PoweredOn, PoweredOff, Suspended. |
|
disks |
object[] | Yes | Disks. The first disk is the template's OS disk (grown if needed); subsequent disks are blank. |
failureDomain |
string | CAPI contract (optional): failure domain placement. The banlieue scheduler writes the chosen failure domain here; for CAPI users the parent Machine's spec.failureDomain is what populates this. |
|
firmware |
string | Yes | Firmware. EFI / EFI Secure require the template to be EFI-capable. Allowed: bios, efi, efi-secure. |
firstBootSealing |
object | First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged. |
|
folder |
string | Destination vCenter folder path for the clone (not the source template — see template_folder). Optional; defaults to the datacenter VM root, or (once set by banlieue-controller) the same per-zone folder the template lives in. |
|
memoryMiB |
integer | Yes | Memory in MiB. |
network |
object[] | Yes | Network interfaces. |
numCpus |
integer | Yes | Number of virtual CPUs. |
providerID |
string | CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: vsphere://<vm-instance-uuid>. Set by the provider controller after the VM is created. |
|
providerRef |
object | Yes | Reference to the banlieue Provider whose connection details describe the target vCenter. |
resourcePool |
string | Resource pool path within the cluster. Optional; defaults to the cluster's root resource pool. | |
template |
string | Yes | vCenter template's bare display name (resolved from VMImage). Never a decorated string (no [dc]/folder prefix) — see template_folder for the scoping the lookup needs. |
templateFolder |
string | The per-zone vCenter folder the template in template lives in (resolved from VMImage.status, e.g. templates/cluster-01, ADR-0020 Decision #5). Set for both Url and Template vSphere sources (ADR-0104); None only for a row written by a provider that predates it, whose lookup is datacenter-wide. |
|
tpmEnabled |
boolean | Attach a virtual TPM (vTPM) device to this VM, resolved from the VM's VMClass.spec.tpmEnabled (ADR-0039). Consumed by the provider controller between clone_vm (which always clones powered off) and the power-on step, so the device exists before first boot — a hard requirement for Kairos's kcrypt to seal LUKS keys to it during unattended install. |
|
userData |
string | Guest bootstrap payload content — already resolved from the parent VirtualMachine's spec.userData Secret or ConfigMap (ADR-0038) and placeholder-substituted (ADR-0024's ${VM_NAME}/${FQDN}/etc. set) by banlieue-controller (ADR-0025). The provider delivers this verbatim (base64 into guestinfo.userdata) — it never reads a Secret or ConfigMap itself. |
.spec.disks[]¶
Disks. The first disk is the template's OS disk (grown if needed); subsequent disks are blank.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Stable disk name; echoed in status with resolved backend identifiers. |
provisioning |
string | Provisioning hint (thin / thick / eager-zeroed). Allowed: thin, thick, eagerZeroed. |
|
sizeGiB |
integer | Yes | Disk size in GiB. For the OS disk this is a floor — the template's disk is grown to at least this size. |
.spec.firstBootSealing¶
First-boot sealing the guest must report before GuestReady
(ADR-0088), copied by banlieue-controller from the parent
VirtualMachine's VMImage.spec.firstBootSealing when the class is
tpmEnabled. None for every other machine, which keeps today's
GuestReady meaning unchanged.
| Field | Type | Required | Description |
|---|---|---|---|
partitions |
string[] | Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal. |
|
timeoutSeconds |
integer | Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed. |
.spec.network[]¶
Network interfaces.
| Field | Type | Required | Description |
|---|---|---|---|
ipam |
object | Yes | IP address management for this interface. |
macAddress |
string | Optional MAC address (otherwise vCenter generates one). | |
name |
string | Yes | Stable NIC name; echoed in status. |
portGroup |
string | Yes | Resolved port group or distributed port group name. |
.spec.network[].ipam¶
IP address management for this interface.
| Field | Type | Required | Description |
|---|---|---|---|
pool |
object | Pool-based IPAM parameters. | |
static |
object | Static IPAM parameters (address, prefix, gateway, nameservers, domain). |
.spec.network[].ipam.pool¶
Pool-based IPAM parameters.
| Field | Type | Required | Description |
|---|---|---|---|
poolRef |
object | Yes | Typed reference (apiGroup + kind + name + optional namespace). |
# .spec.network[].ipam.pool.poolRef¶
Typed reference (apiGroup + kind + name + optional namespace).
Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we
want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's
default) or future banlieue-native pool types.
| Field | Type | Required | Description |
|---|---|---|---|
apiGroup |
string | Yes | |
kind |
string | Yes | |
name |
string | Yes | |
namespace |
string |
.spec.network[].ipam.static¶
Static IPAM parameters (address, prefix, gateway, nameservers, domain).
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | |
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer | Yes |
.spec.providerRef¶
Reference to the banlieue Provider whose connection details
describe the target vCenter.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |
.status¶
Observed state of a VSphereMachine, shaped to the CAPI v1beta2 InfraMachine status contract (plus a few vSphere-specific diagnostics).
| Field | Type | Required | Description |
|---|---|---|---|
addresses |
object[] | CAPI contract field (optional): VM addresses. Surfaced to the parent Machine's status.addresses once initialization is complete. |
|
conditions |
object[] | CAPI-compatible conditions (using metav1.Condition). The Ready condition is mirrored as InfrastructureReady on the parent (clusterv1.Machine or banlieue VirtualMachine) per contract. |
|
failureDomain |
string | CAPI contract field (optional): observed failure domain. Surfaced to the parent Machine's status.failureDomain. |
|
guestInstalled |
boolean | Whether the installed guest has announced itself, distinct from a live installer still overwriting the disk (ADR-0043). Read from guestinfo.banlieue.phase via config.extraConfig — the guest writes it with vmware-rpctool, the host reads it back here. None means nothing has looked yet (the whole life of an Immediate image, or a Deferred one before its first observation); sticky at Some(true) once observed, since the runtime value does not survive a power cycle but a stopped VM has not become uninstalled. Not part of the CAPI contract; mirrored onto the parent VirtualMachine as the GuestReady condition (common::condition_types::GUEST_READY), never as Ready. |
|
initialization |
object | CAPI contract field: replaces the deprecated v1beta1 status.ready. |
|
installMediaDetached |
boolean | Whether the provider has made sure no install medium is left on the VM (ADR-0044, vSphere amendment 2026-10-23). | |
instanceUuid |
string | VM instance UUID. Stable across vCenter restarts and the source for spec.providerID. Not part of the CAPI contract. |
|
observedGeneration |
integer | ||
observedPowerState |
string | The backend VM's actual power state, as last observed via VirtualMachine.runtime.powerState (ADR-0034) — the hypervisor's view, available immediately on power-on, not a guest-OS-boot signal. Absent until first observed. Not part of the CAPI contract; mirrored onto the parent VirtualMachine's own status.observedPowerState. Allowed: PoweredOn, PoweredOff, Suspended, null. |
|
sealedPartitions |
string[] | Partitions the guest has reported sealed, as LUKS containers, on a first-boot sealing machine (ADR-0088): from guestinfo.banlieue.sealed. Sticky: the report is re-asserted every boot but lives in volatile state, and a powered-off machine has not become unsealed. Empty until reported, and on every machine without spec.firstBootSealing. Guest-supplied, so it is only ever used to withhold GuestReady. |
|
tpmAttached |
boolean | Whether a vTPM device was successfully attached, when spec.tpmEnabled is set (ADR-0039). None when tpmEnabled is false (nothing was ever attempted) or the attach hasn't run yet. Not part of the CAPI contract; a failed attach surfaces through the Ready/InfrastructureReady conditions rather than a dedicated VirtualMachine-level mirror (ADR-0034's reasoning for observedPowerState applies equally here). |
|
tpmEndorsementCertificates |
string[] | PEM vTPM endorsement key certificate(s) issued by vCenter for this VM's vTPM (ADR-0045). | |
vmRef |
string | VMware managed-object reference (vm-NNNN). Useful for operator diagnostics. Not part of the CAPI contract. |
.status.addresses[]¶
CAPI contract field (optional): VM addresses. Surfaced to the parent
Machine's status.addresses once initialization is complete.
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | The address itself. |
type |
string | Yes | Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. |
.status.conditions[]¶
CAPI-compatible conditions (using metav1.Condition). The Ready
condition is mirrored as InfrastructureReady on the parent
(clusterv1.Machine or banlieue VirtualMachine) per contract.
| Field | Type | Required | Description |
|---|---|---|---|
lastTransitionTime |
string | Yes | lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
message |
string | Yes | message is a human readable message indicating details about the transition. This may be an empty string. |
observedGeneration |
integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | |
reason |
string | Yes | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. |
status |
string | Yes | status of the condition, one of True, False, Unknown. |
type |
string | Yes | type of condition in CamelCase or in foo.example.com/CamelCase. |
.status.initialization¶
CAPI contract field: replaces the deprecated v1beta1 status.ready.
| Field | Type | Required | Description |
|---|---|---|---|
provisioned |
boolean | True when the infrastructure provider reports that the resource's infrastructure is fully provisioned. |
VSphereMachineTemplate¶
API: infrastructure.banlieue.io/v1alpha1 · Kind: VSphereMachineTemplate · Scope: Namespaced · Short names: vsmt
VSphereMachineTemplate — a stamped-out VSphereMachine spec.
CAPI requires an InfraMachineTemplate so higher-level controllers (a
MachineSet / MachineDeployment) can mint many identical machines from one
template. It wraps a single template.spec that is the VSphereMachine spec
used for each generated machine. banlieue ships it for CAPI compatibility;
standalone VirtualMachine users do not need it.
.spec¶
| Field | Type | Required | Description |
|---|---|---|---|
template |
object | Yes | The VSphereMachine spec stamped into every machine created from this template. |
.spec.template¶
The VSphereMachine spec stamped into every machine created from this template.
| Field | Type | Required | Description |
|---|---|---|---|
spec |
object | Yes | The VSphereMachine spec for machines created from this template. |
.spec.template.spec¶
The VSphereMachine spec for machines created from this template.
| Field | Type | Required | Description |
|---|---|---|---|
cluster |
string | Yes | Compute cluster within the datacenter. |
createdBy |
string | The principal that created the parent VirtualMachine, copied from its banlieue.io/created-by annotation when present (ADR-0089). That annotation is stamped by an optional MutatingAdmissionPolicy (deploy/admission/virtualmachine-created-by.yaml) from request.userInfo.username at VirtualMachine CREATE — None on a cluster that doesn't apply it, or for a VirtualMachine that predates it. Surfaced as the vCenter CreatedBy custom attribute by the provider; never a stand-in value when absent. |
|
datacenter |
string | Yes | Datacenter name. |
datastore |
string | Yes | Datastore or datastore cluster name (resolved from the storage class). |
desiredPowerState |
string | Desired power state, resolved from the parent VirtualMachine's spec.desiredPowerState (ADR-0024). Defaults to PoweredOn, matching VirtualMachineSpec's own default. Allowed: PoweredOn, PoweredOff, Suspended. |
|
disks |
object[] | Yes | Disks. The first disk is the template's OS disk (grown if needed); subsequent disks are blank. |
failureDomain |
string | CAPI contract (optional): failure domain placement. The banlieue scheduler writes the chosen failure domain here; for CAPI users the parent Machine's spec.failureDomain is what populates this. |
|
firmware |
string | Yes | Firmware. EFI / EFI Secure require the template to be EFI-capable. Allowed: bios, efi, efi-secure. |
firstBootSealing |
object | First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged. |
|
folder |
string | Destination vCenter folder path for the clone (not the source template — see template_folder). Optional; defaults to the datacenter VM root, or (once set by banlieue-controller) the same per-zone folder the template lives in. |
|
memoryMiB |
integer | Yes | Memory in MiB. |
network |
object[] | Yes | Network interfaces. |
numCpus |
integer | Yes | Number of virtual CPUs. |
providerID |
string | CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: vsphere://<vm-instance-uuid>. Set by the provider controller after the VM is created. |
|
providerRef |
object | Yes | Reference to the banlieue Provider whose connection details describe the target vCenter. |
resourcePool |
string | Resource pool path within the cluster. Optional; defaults to the cluster's root resource pool. | |
template |
string | Yes | vCenter template's bare display name (resolved from VMImage). Never a decorated string (no [dc]/folder prefix) — see template_folder for the scoping the lookup needs. |
templateFolder |
string | The per-zone vCenter folder the template in template lives in (resolved from VMImage.status, e.g. templates/cluster-01, ADR-0020 Decision #5). Set for both Url and Template vSphere sources (ADR-0104); None only for a row written by a provider that predates it, whose lookup is datacenter-wide. |
|
tpmEnabled |
boolean | Attach a virtual TPM (vTPM) device to this VM, resolved from the VM's VMClass.spec.tpmEnabled (ADR-0039). Consumed by the provider controller between clone_vm (which always clones powered off) and the power-on step, so the device exists before first boot — a hard requirement for Kairos's kcrypt to seal LUKS keys to it during unattended install. |
|
userData |
string | Guest bootstrap payload content — already resolved from the parent VirtualMachine's spec.userData Secret or ConfigMap (ADR-0038) and placeholder-substituted (ADR-0024's ${VM_NAME}/${FQDN}/etc. set) by banlieue-controller (ADR-0025). The provider delivers this verbatim (base64 into guestinfo.userdata) — it never reads a Secret or ConfigMap itself. |
.spec.template.spec.disks[]¶
Disks. The first disk is the template's OS disk (grown if needed); subsequent disks are blank.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Stable disk name; echoed in status with resolved backend identifiers. |
provisioning |
string | Provisioning hint (thin / thick / eager-zeroed). Allowed: thin, thick, eagerZeroed. |
|
sizeGiB |
integer | Yes | Disk size in GiB. For the OS disk this is a floor — the template's disk is grown to at least this size. |
.spec.template.spec.firstBootSealing¶
First-boot sealing the guest must report before GuestReady
(ADR-0088), copied by banlieue-controller from the parent
VirtualMachine's VMImage.spec.firstBootSealing when the class is
tpmEnabled. None for every other machine, which keeps today's
GuestReady meaning unchanged.
| Field | Type | Required | Description |
|---|---|---|---|
partitions |
string[] | Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal. |
|
timeoutSeconds |
integer | Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed. |
.spec.template.spec.network[]¶
Network interfaces.
| Field | Type | Required | Description |
|---|---|---|---|
ipam |
object | Yes | IP address management for this interface. |
macAddress |
string | Optional MAC address (otherwise vCenter generates one). | |
name |
string | Yes | Stable NIC name; echoed in status. |
portGroup |
string | Yes | Resolved port group or distributed port group name. |
# .spec.template.spec.network[].ipam¶
IP address management for this interface.
| Field | Type | Required | Description |
|---|---|---|---|
pool |
object | Pool-based IPAM parameters. | |
static |
object | Static IPAM parameters (address, prefix, gateway, nameservers, domain). |
## .spec.template.spec.network[].ipam.pool¶
Pool-based IPAM parameters.
| Field | Type | Required | Description |
|---|---|---|---|
poolRef |
object | Yes | Typed reference (apiGroup + kind + name + optional namespace). |
### .spec.template.spec.network[].ipam.pool.poolRef¶
Typed reference (apiGroup + kind + name + optional namespace).
Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we
want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's
default) or future banlieue-native pool types.
| Field | Type | Required | Description |
|---|---|---|---|
apiGroup |
string | Yes | |
kind |
string | Yes | |
name |
string | Yes | |
namespace |
string |
## .spec.template.spec.network[].ipam.static¶
Static IPAM parameters (address, prefix, gateway, nameservers, domain).
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | |
domain |
string | DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>. |
|
gateway |
string | ||
nameservers |
string[] | ||
prefix |
integer | Yes |
.spec.template.spec.providerRef¶
Reference to the banlieue Provider whose connection details
describe the target vCenter.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes |