Configuration
vMetal is configured through a NodeProvider resource that defines the control plane cluster, infrastructure components, and node types. Node types categorize bare metal servers by hardware profile and control how they are provisioned.
NodeProvider
A Metal3 NodeProvider configuration consists of a cluster reference, optional infrastructure deployment settings, and a list of node types.
Cluster reference
The clusterRef specifies the control plane cluster where the platform installs Metal3 components and where the BareMetalHost resources live. This cluster must be connected to vCluster Platform.
| Field | Description | Required |
|---|---|---|
clusterRef.cluster | Name of the connected control plane cluster | Yes |
clusterRef.namespace | Namespace on the control plane cluster for Metal3 components and BareMetalHost resources | Yes |
Ironic must have network access to the BMC addresses of the bare metal servers. Ensure the control plane cluster where Ironic is deployed can reach the BMC network (Redfish/IPMI endpoints).
Example
apiVersion: management.loft.sh/v1
kind: NodeProvider
metadata:
name: metal3-provider
spec:
displayName: "Metal3 Bare Metal Provider"
metal3:
clusterRef:
cluster: bare-metal-cluster
namespace: metal3-system
deploy:
metal3:
enabled: true
dhcp:
enabled: true
helmValues: |
networkAttachmentDefinition:
vip: 192.168.100.2/24
multus:
enabled: true
helmValues: |
namespace: kube-system
nodeTypes:
- name: "compute-node"
displayName: "Compute Node"
resources:
cpu: "32"
memory: 128Gi
bareMetalHosts:
selector:
matchLabels:
role: compute
properties:
vcluster.com/os-image: ubuntu-noble
Infrastructure deployment
The Metal3 provider can deploy the required infrastructure components on the control plane cluster. Each component can be individually enabled and customized with Helm values. Metal3 and Ironic can also be managed independently. Disable the respective component and the provider uses whatever is already deployed.
- Metal3 & Ironic
- DHCP Server
- Multus
Bare metal provisioning and lifecycle management. Deploys the Bare Metal Operator and Ironic.
Helm values:
| Value | Description | Default |
|---|---|---|
ironic.image.repository | Ironic container image | quay.io/metal3-io/ironic |
ironic.image.tag | Ironic image tag | release-32.0 |
ipaDownloader.image.repository | IPA ramdisk downloader image | quay.io/metal3-io/ironic-ipa-downloader |
ipaDownloader.image.tag | IPA ramdisk downloader tag | latest |
bareMetalOperator.image.repository | Bare Metal Operator image | quay.io/metal3-io/baremetal-operator |
bareMetalOperator.image.tag | Bare Metal Operator tag | v0.12.0 |
deploy:
metal3:
enabled: true
helmValues: |
ironic:
image:
tag: release-32.0
Handles PXE and HTTP Boot by acting as a proxy between bare metal servers and Ironic, which may reside in a different network. When the provider also deploys Metal3, the Ironic endpoint URLs configure automatically.
Helm values:
| Value | Description | Default |
|---|---|---|
hostNetwork | Run the pod on the host network. When true, the pod runs as root and the Multus NetworkAttachmentDefinition is not attached. Use for flat networks where bare metal servers are on the same L2 as the control plane cluster nodes. | false |
networkAttachmentDefinition.vip | Virtual IP with prefix for the DHCP server. Ignored when hostNetwork: true. | 192.168.100.3/24 |
networkAttachmentDefinition.config | CNI configuration JSON for the NetworkAttachmentDefinition. Use bridge if control plane cluster nodes have a bridge on the provisioning network. Use macvlan if bare metal servers are on the same network as the nodes. | bridge br0 |
dhcp.listenAddr | DHCP listen address. When using hostNetwork: true, set to $(SERVER_IP):67 to avoid answering on shared bridges. | 0.0.0.0:67 |
extraArgs | Extra arguments appended to the server binary. Use to set IPA inspector and installer kernel parameters. | [] |
proxy.ironicHttpUrl | Ironic HTTP endpoint for image serving. | Auto-configured when Metal3 is enabled |
proxy.ironicApiUrl | Ironic API endpoint. | Auto-configured when Metal3 is enabled |
Example with a bridge:
deploy:
dhcp:
enabled: true
helmValues: |
networkAttachmentDefinition:
vip: 192.168.100.2/24
config: |
{
"cniVersion": "0.3.1",
"type": "bridge",
"bridge": "br0",
"isDefaultGateway": false
}
Example with macvlan (bare metal servers on the same network as the control plane cluster nodes):
deploy:
dhcp:
enabled: true
helmValues: |
networkAttachmentDefinition:
vip: 10.0.0.2/24
config: |
{
"cniVersion": "0.3.1",
"type": "macvlan",
"master": "eth0",
"mode": "bridge"
}
Example with hostNetwork for flat networks (no Multus required):
deploy:
dhcp:
enabled: true
helmValues: |
hostNetwork: true
dhcp:
listenAddr: "$(SERVER_IP):67"
CNI plugin that enables attaching the DHCP server to a separate provisioning network.
Helm values:
| Value | Description | Default |
|---|---|---|
namespace | Namespace to deploy Multus into | Provider namespace |
deploy:
multus:
enabled: true
helmValues: |
namespace: kube-system
Bare metal servers
Physical servers are added by creating BareMetalHost resources on the control plane cluster, either through the platform UI or by applying them directly with kubectl. Each BareMetalHost represents a physical server and requires BMC configuration for out-of-band management.
BMC configuration
Each BareMetalHost needs a BMC address and credentials. The address scheme determines which driver Metal3 uses to communicate with the server's BMC.
Common address formats:
- Redfish:
redfish://192.168.1.100 - IPMI:
ipmi://192.168.1.100:623
For the full list of supported BMC drivers and address formats, see the Metal3 Bare Metal Operator documentation.
BMC credentials are stored in a Kubernetes Secret:
apiVersion: v1
kind: Secret
metadata:
name: server-01-bmc
namespace: metal3-system
type: Opaque
stringData:
username: admin
password: <BMC-PASSWORD>
Add a single server
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
name: server-01
namespace: metal3-system
labels:
role: compute
spec:
bmc:
address: redfish://192.168.1.100
credentialsName: server-01-bmc
disableCertificateVerification: true
bootMACAddress: "aa:bb:cc:dd:ee:01"
Key fields:
| Field | Description |
|---|---|
spec.bmc.address | BMC endpoint URL. The scheme (redfish://, ipmi://, etc.) selects the driver. Immutable after the server leaves Registering state. |
spec.bmc.credentialsName | Name of the Secret containing username and password keys. Must be in the same namespace. |
spec.bmc.disableCertificateVerification | Set to true for BMCs with self-signed certificates. |
spec.bootMACAddress | MAC address of the NIC used for PXE boot. Immutable after creation. |
metadata.labels | Used by node type selectors to match servers to node types. |
Bulk registration
Add multiple servers at once by applying BareMetalHost and Secret resources together:
---
apiVersion: v1
kind: Secret
metadata:
name: server-01-bmc
namespace: metal3-system
type: Opaque
stringData:
username: admin
password: <BMC-PASSWORD>
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
name: server-01
namespace: metal3-system
labels:
role: compute
rack: rack-a
spec:
bmc:
address: redfish://192.168.1.100
credentialsName: server-01-bmc
bootMACAddress: "aa:bb:cc:dd:ee:01"
---
apiVersion: v1
kind: Secret
metadata:
name: server-02-bmc
namespace: metal3-system
type: Opaque
stringData:
username: admin
password: <BMC-PASSWORD>
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
name: server-02
namespace: metal3-system
labels:
role: compute
rack: rack-b
spec:
bmc:
address: ipmi://192.168.1.101:623
credentialsName: server-02-bmc
bootMACAddress: "aa:bb:cc:dd:ee:02"
kubectl apply -f servers.yaml
Node types
Each node type specifies which BareMetalHosts it can claim and what properties to apply during provisioning.
Select BareMetalHosts by label
Use bareMetalHosts.selector to match BareMetalHosts by labels. Only hosts matching the selector and having sufficient resources are eligible.
nodeTypes:
- name: "gpu-server"
displayName: "GPU Server"
resources:
cpu: "64"
memory: 256Gi
nvidia.com/gpu: "4"
bareMetalHosts:
selector:
matchLabels:
role: gpu
datacenter: us-east
- name: "general-compute"
displayName: "General Compute"
resources:
cpu: "32"
memory: 128Gi
bareMetalHosts:
selector:
matchLabels:
role: compute
Capacity
Capacity for Metal3 node types is determined by the number of available BareMetalHosts matching the node type's label selector. The platform tracks how many servers are provisioned and marks the node type as unavailable when all matching hosts are in use.
Cost
Each node type has an associated cost, either manually specified via the spec.cost field or calculated from resources. Default cost per resource unit:
- Each CPU:
10 - Each GB of memory:
2 - Each other resource (e.g., GPU):
10000
The platform uses cost to select the cheapest node type when multiple types match a request.
Configuration properties
Properties are key-value pairs on node types or Machines that control provisioning behavior.
Image configuration
vcluster.com/os-image
Type: string
References an OSImage resource by name. The OSImage's properties configure the image URL, checksum, and checksum type. This is the recommended way to configure OS images.
metal3.vcluster.com/image-url
Type: string
Required: Yes (if not using vcluster.com/os-image)
Direct URL to the OS image. Example: https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
metal3.vcluster.com/image-checksum
Type: string
Required: Yes (if not using vcluster.com/os-image)
Checksum of the OS image for verification.
metal3.vcluster.com/image-checksum-type
Type: string
Checksum algorithm. Supported values: md5, sha256, and sha512. If omitted, the type is auto-detected.
Network configuration
metal3.vcluster.com/network-cidr
Type: string (format: <gateway-ip>/<prefix-length>)
Specifies the gateway IP in CIDR notation. The platform derives the network address from the prefix length and allocates IPs from that range using its built-in IPAM. The gateway IP must be a valid host address within the network (not the network or broadcast address).
Example: 192.168.100.1/24 — gateway is 192.168.100.1, allocates from 192.168.100.0/24
metal3.vcluster.com/network-ip-range
Type: string (comma-separated IP ranges)
Specifies explicit IP ranges for allocation instead of CIDR-based allocation. Format: IP1-IP2,IP3-IP4
Example: 10.0.0.20-10.0.0.30,10.0.0.40-10.0.0.50
metal3.vcluster.com/dns-servers
Type: string (comma-separated)
DNS servers to configure on the provisioned server. Example: 8.8.8.8,8.8.4.4
metal3.vcluster.com/network-data
Type: string
Complete custom network-data configuration. When set, this overrides automatic network configuration from CIDR or IP range properties.
vcluster.com/network-data-template
Type: string
A Go template string that renders into a cloud-init network-config document. Evaluated when metal3.vcluster.com/network-data is not set. The template receives the same Values object as vcluster.com/user-data-template.
vcluster.com/network-data-template-secret
Type: string (format: <namespace>/<name>)
References a Secret containing a Go template for network data. Evaluated when both metal3.vcluster.com/network-data and vcluster.com/network-data-template are unset. The Secret must carry the vcluster.com/user-data-template-type label.
Node environment
vcluster.com/network-environment
Type: string
Names a NodeEnvironment resource whose properties are merged into the NodeClaim's effective property set. The platform resolves this from the merged properties of NodeProvider, NodeType, and NodeClaim. When set, this takes precedence over the typed NodeClaim.spec.environmentRef field.
Server pinning
metal3.vcluster.com/server-name
Type: string
Pins a Machine to a specific BareMetalHost by name. Set this property on the Machine, not on the node type. Useful when you want to target a particular physical server.
SSH and user data
vcluster.com/ssh-keys
Type: string (comma-separated)
References SSHKey resources by name. The public keys are included in the user data during provisioning.
vcluster.com/user-data
Type: string
A complete cloud-config YAML document used as the base for user data generation. The platform appends the vCluster join command and SSH keys from vcluster.com/ssh-keys into this document — it does not replace them. Takes precedence over vcluster.com/user-data-template and vcluster.com/user-data-template-secret.
vcluster.com/user-data-template
Type: string
A Go template that renders into a cloud-config YAML document. Evaluated when vcluster.com/user-data is not set. The template receives a Values object:
| Field | Description |
|---|---|
.Values.NodeClaim | The NodeClaim being provisioned. |
.Values.Project | The project the node belongs to. |
.Values.Properties | Merged properties from the NodeProvider, NodeType, and NodeClaim. |
.Values.SSHKeys | SSH public keys to inject. |
.Values.BareMetalHost | The selected BareMetalHost resource (unstructured). |
.Values.AllocatedIP | IP allocated for the Machine, if IPAM is in use. |
.Values.Gateway | Default gateway for the allocated network. |
vcluster.com/user-data-template-secret
Type: string
The name of a Secret containing a Go template for user data. Evaluated when both vcluster.com/user-data and vcluster.com/user-data-template are unset. The Secret must have the label vcluster.com/user-data-template-type set.
Precedence order: vcluster.com/user-data → vcluster.com/user-data-template → vcluster.com/user-data-template-secret. In all cases, the platform appends the vCluster join command and SSH keys to the resolved cloud-config.
Deleting a user data template Secret does not affect servers already provisioned with its content. The platform embeds the rendered template in the BareMetalHost at provision time.