Skip to main content
Version: v4.12 Stable

Metal3

Enterprise
Available in these plansFreeDevProdScale
Metal3 Node Provider

Free, Dev, Prod, and Scale are vCluster Platform license plans. Open source does not need a license or a Platform connection. See Compare open source and free tiers.

The Metal3 provider allows you to provision bare metal servers as Machines using Metal3 and Ironic. When a Machine is requested, the platform claims an available BareMetalHost resource and configures it with the requested OS image and user data. Ironic then handles the PXE boot and OS installation on the physical server.

This enables you to offer different configurations of bare metal servers, all managed through BareMetalHost resources on a control plane clusterControl plane clusterThe Kubernetes cluster that hosts the virtualized control planes for tenant clusters. The control plane cluster is operated by the platform provider and is completely invisible to tenants. There are no shared control plane nodes, no in-cluster agent pods, and no lateral path between tenant environments. With shared nodes, this cluster also runs tenant workloads alongside the control plane pods — the same node pool is used for both.Related: Tenant cluster, Control plane cluster, Tenant cluster. Machines can be used as private nodes for tenant clusters or provisioned independently.

How the Metal3 provider provisions bare metalvCluster PlatformMachine requestMetal3 providerSelects an available host.Sets requested provisioning data.Deletion clears provisioning data and returns the host to available.Control plane clusterAvailableBareMetalHostMatched by node type.Bare MetalOperatorReconciles host.IronicPowers and boots.Installs the OS.Optional DHCP and Multus connect the provisioning network.Tenant clusterWorker nodeFor private nodes, user data registersthe provisioned server with the tenant cluster.Bare metal infrastructurePhysical serverBMC and boot NIC registered before provisioning.Ironic installs and initializes the operating system.
The platform writes the requested state to an available BareMetalHost. Metal3 and Ironic provision the external server, which joins a tenant cluster only when requested as a private node. Deleting the Machine returns the host to the available pool.

Overview​

The Metal3 provider works by selecting available BareMetalHost resources on a control plane cluster and provisioning them with an OS image and user data configuration. Node types let you organize bare metal servers based on type, location, or other criteria.

When the Machine is deleted, the platform powers the server off and clears its image, user data, and network data references. It restores pre-existing managed DHCP annotations and makes the BareMetalHost available for reuse.

How it works: Provisioning​

After the platform selects a BareMetalHost, it prepares the server for provisioning:

  1. The platform generates a user data configuration and stores it in a Kubernetes Secret on the control plane cluster.
  2. The provider sets the BareMetalHost's userData reference to this Secret and the image information from the configured OSImage or direct image properties.

Ironic then provisions the server through power management, PXE boot, and an in-memory installer that writes the OS to disk. The server boots into the provisioned OS with the user data configuration applied.

When a Machine is used as a private node for a tenant clusterTenant clusterA fully isolated Kubernetes environment provisioned for a single tenant. Each tenant cluster has its own API server, controller manager, and resource namespace, backed by a virtualized control plane hosted on a control plane cluster. From the tenant's perspective it behaves exactly like a standard Kubernetes cluster.Related: Control plane cluster, Tenant cluster, the user data includes registration scripts that automatically join the server to the tenant cluster.

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. You can also manage Metal3 and Ironic separately. When you enable the bundled DHCP server with external Ironic, configure proxy.ironicHttpUrl and either proxy.ironicApiUrl or proxy.apiAdvertiseUrl.

Bare metal provisioning and lifecycle management. Deploys the Bare Metal Operator, Ironic, an IPA image server, and MariaDB as separate workloads.

Install cert-manager on the control plane cluster before enabling this component. The Bare Metal Operator uses it for admission webhooks, and internal components use it for mutual TLS (mTLS). The Platform UI checks this prerequisite and warns when it is missing.

Upgrading from a Metal3 chart earlier than 0.6.0

The default Metal3 chart version is 0.6.0. This version replaces the legacy single-pod deployment with separate workloads and a MariaDB backend. Review this architecture and database change before upgrading an existing Metal3 deployment.

To retain the legacy topology temporarily, pin spec.metal3.deploy.metal3.version to the version that is already deployed. The previous vClustervClusterAn open-source software product that creates and manages tenant clusters within Kubernetes infrastructure. vCluster provides tenant isolation capabilities while reducing infrastructure costs.Related: Tenant cluster, Control plane cluster Platform default was 0.4.1.

The components use the following runtime topology:

  • Ironic conductors run active/active. They shard host ownership over a consistent hash ring and coordinate through JSON-RPC.
  • The managed MariaDB is a single-replica StatefulSet. For high availability, run an external MariaDB and set mariadb.mode: external.
  • The IPA image server serves public static boot content outside the mTLS mesh.

Helm values:

ValueDescriptionDefault
ironic.replicasNumber of Ironic conductors. Values greater than 1 run them active/active.2
ironic.ipaAdvertiseIPIronic LoadBalancer VIP advertised to the in-memory agent (IPA). Set it to enable real provisioning against physical hosts; empty keeps the Ironic API in-cluster only (for scale-out testing without a real host cycle).""
ironic.serviceApplied as the Ironic Service spec, so any field can be set (for example type: LoadBalancer, loadBalancerClass, and a nested metadata map for annotations and labels). name, namespace, and selector are managed by the chart. Ports use chart defaults but can be replaced with a custom ports list. Empty leaves a default ClusterIP Service.{}
ironic.image.registryIronic container image registry.quay.io
ironic.image.repositoryIronic container image repository.metal3-io/ironic
ironic.image.tagIronic image tagrelease-35.0
ipaImages.replicasReplicas of the IPA image server that serves the IPA kernel and initramfs.2
mariadb.modeDatabase backend for Ironic: statefulset (single-replica managed MariaDB StatefulSet with its own PVC and cert-manager TLS) or external (connect to your own MariaDB).statefulset
mariadb.externalHostHost Ironic connects to in external mode. Ignored otherwise.""
mariadb.databaseDatabase name.ironic
mariadb.usernameDatabase username Ironic uses. An empty value resolves to ironic.""
mariadb.passwordDatabase password Ironic uses. In statefulset mode, an empty value generates a password on first install and preserves it across upgrades. In external mode, an empty value resolves to ironic.Mode-dependent
mariadb.caCertSecretName / mariadb.caCertSecretKeyexternal mode only. Secret and key holding the CA certificate used to verify the external MariaDB over TLS. When set, Ironic connects over TLS."" / ca.crt
mariadb.persistence.sizePVC size for the managed MariaDB in statefulset mode.10Gi
bareMetalOperator.image.registryBare Metal Operator image registry.quay.io
bareMetalOperator.image.repositoryBare Metal Operator image repository.metal3-io/baremetal-operator
bareMetalOperator.image.tagBare Metal Operator tagv0.13.1
ipaDownloader.image.registryIPA image downloader registry.ghcr.io
ipaDownloader.image.repositoryIPA image downloader repository.loft-sh/vcluster-platform-ipa-images
ipaDownloader.image.tagIPA image downloader tagv0.2.2

Set ironic.ipaAdvertiseIP to the VIP of the Ironic LoadBalancer Service so bare metal hosts can reach the Ironic agent endpoint during provisioning:

deploy:
metal3:
enabled: true
helmValues: |
ironic:
replicas: 2
ipaAdvertiseIP: 192.168.100.10
service:
type: LoadBalancer
# The assigned address must match ipaAdvertiseIP.
loadBalancerIP: 192.168.100.10

For highly available MariaDB, run your own database and point Ironic at it:

deploy:
metal3:
enabled: true
helmValues: |
mariadb:
mode: external
externalHost: mariadb.example.internal
database: ironic
username: ironic
password: <MARIADB-PASSWORD>

The DHCP server reads its lease data from BareMetalHost annotations. When network properties enable platform IPAM, the provider writes the allocated address and related network settings to those annotations.

Configuration​

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.

FieldDescriptionRequired
clusterRef.clusterName of the connected control plane clusterYes
clusterRef.namespaceNamespace on the control plane cluster for Metal3 components and BareMetalHost resourcesYes

The cluster and namespace references are immutable after you create the provider. A connected control plane cluster can be referenced by only one Metal3 NodeProvider.

Ironic network access

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​

This configuration deploys Metal3, Ironic, the DHCP server, and Multus, and defines a single node type that selects BareMetalHosts with the label role: compute.

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
helmValues: |
ironic:
# Expose the IPA API on a provisioning-network LoadBalancer VIP.
ipaAdvertiseIP: 192.168.100.10
service:
type: LoadBalancer
loadBalancerIP: 192.168.100.10
dhcp:
enabled: true
helmValues: |
networkAttachmentDefinition:
# Attach the DHCP server to the provisioning network.
vip: 192.168.100.2/24
proxy:
# Send IPA directly to the bundled non-mTLS agent endpoint.
apiAdvertiseUrl: https://192.168.100.10:6388
multus:
enabled: true
nodeTypes:
- name: "compute-node"
displayName: "Compute Node"
resources:
cpu: "32"
memory: 128Gi
bareMetalHosts:
selector:
matchLabels:
role: compute
properties:
vcluster.com/os-image: ubuntu-noble

Get started​

This walkthrough covers the essential steps to go from a connected control plane cluster to a provisioned bare metal server.

Before you begin:

  • Install cert-manager on the control plane cluster.
  • Connect each control plane cluster node to the provisioning network through a br0 bridge, or replace the DHCP NetworkAttachmentDefinition configuration.
  • Configure a load balancer implementation that can assign 192.168.100.10 to the Ironic Service. Replace all example network addresses with addresses from your provisioning network.
  • Create an OSImage named ubuntu-noble, or change the node type to reference an existing Metal3-compatible OSImage.
  1. Apply the NodeProvider.

    Create a NodeProvider that references your control plane cluster and defines at least one node type. The node type's label selector determines which BareMetalHosts it can claim.

    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
    helmValues: |
    ironic:
    # Expose the IPA API on a provisioning-network LoadBalancer VIP.
    ipaAdvertiseIP: 192.168.100.10
    service:
    type: LoadBalancer
    loadBalancerIP: 192.168.100.10
    dhcp:
    enabled: true
    helmValues: |
    networkAttachmentDefinition:
    # Attach the DHCP server to the provisioning network.
    vip: 192.168.100.2/24
    proxy:
    # Send IPA directly to the bundled non-mTLS agent endpoint.
    apiAdvertiseUrl: https://192.168.100.10:6388
    multus:
    enabled: true
    nodeTypes:
    - name: "compute-node"
    displayName: "Compute Node"
    resources:
    cpu: "32"
    memory: 128Gi
    bareMetalHosts:
    selector:
    matchLabels:
    role: compute
    properties:
    vcluster.com/os-image: ubuntu-noble
    kubectl apply -f metal3-provider.yaml

    Wait for Metal3 and Ironic to be running on the control plane cluster before creating BareMetalHost resources. The Metal3 webhook must be ready to validate them.

  2. Create BMC credentials.

    Create a Secret with the BMC username and password for your server. This Secret is referenced by the BareMetalHost resource.

    apiVersion: v1
    kind: Secret
    metadata:
    name: server-01-bmc
    namespace: metal3-system
    type: Opaque
    stringData:
    username: admin
    password: <BMC-PASSWORD>
    kubectl apply -f server-01-bmc-secret.yaml
  3. Create a BareMetalHost.

    Register the physical server by creating a BareMetalHost resource. The bmc.address scheme determines which driver Metal3 uses, such as Redfish or IPMI. The bootMACAddress identifies the NIC used for PXE boot.

    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"
    kubectl apply -f server-01-bmh.yaml

    The server moves through registering and inspecting states as Metal3 verifies BMC access and collects hardware inventory.

  4. Verify the server reaches available state.

    Once the BareMetalHost passes inspection, it transitions to available. This means the server is registered, its hardware inventory is collected, and it is ready for provisioning.

    kubectl get baremetalhost -n metal3-system
    NAME STATE CONSUMER ONLINE ERROR AGE
    server-01 available false 5m
  5. Create a tenant cluster that claims the server.

    Create a tenant cluster with private nodes configured to use the Metal3 provider. The platform provisions a Machine, which claims the BareMetalHost and installs the OS through Ironic.

    privateNodes:
    enabled: true
    autoNodes:
    - provider: metal3-provider
    static:
    - name: compute-nodes
    quantity: 1
    nodeTypeSelector:
    - property: vcluster.com/node-type
    value: compute-node

    After provisioning completes, the server boots into the configured OS and joins the tenant cluster as a worker node.

Define 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. The provider checks requested CPU and memory against the inspected BareMetalHost inventory. Other resource keys don't affect BareMetalHost selection, so use labels to select hardware such as GPUs.

nodeTypes:
- name: "gpu-server"
displayName: "GPU Server"
resources:
cpu: "64"
memory: 256Gi
bareMetalHosts:
selector:
matchLabels:
role: gpu
datacenter: us-east

- name: "general-compute"
displayName: "General Compute"
resources:
cpu: "32"
memory: 128Gi
bareMetalHosts:
selector:
matchLabels:
role: compute

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 are used to 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 are md5, sha256, sha512, and auto. If omitted, Ironic defaults to md5. Set it to auto to have Ironic detect the algorithm from the checksum.

Network configuration​

metal3.vcluster.com/network-cidr​

Type: string (standard CIDR notation)

Specifies the gateway IP and subnet for IP allocation. Use standard CIDR notation where the host portion is the gateway address. The platform allocates IPs from the resulting subnet using its built-in IPAM.

Example: 10.0.0.1/24

metal3.vcluster.com/network-ip-range​

Type: string (comma-separated IP ranges)

Restricts allocation to explicit IP ranges. The metal3.vcluster.com/network-cidr property remains required because it supplies the gateway and prefix. Keep every range within that subnet. 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 for the installed operating system. When set, it replaces the network-data document that the provider would generate. CIDR and IP range properties still control address allocation and provisioning DHCP.

vcluster.com/network-data-template-config​

Type: string

References a MachineConfigTemplate by name. The provider renders the template's networkDataTemplate into a cloud-init network-config document when metal3.vcluster.com/network-data isn't set. See Machine Config Templates for the template syntax and available variables.

Network environment​

vcluster.com/network-environment​

Type: string

Names the network environment, 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 property 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. This is useful when creating a Machine directly and you want to target a particular server. Set this property on the Machine, not on the node type.

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

Custom cloud-init configuration merged with the generated user data. Accepts any valid cloud-config directives, including packages, write_files, and runcmd. The platform's provisioning commands are appended after any user-supplied runcmd entries.

Takes precedence over vcluster.com/user-data-template-config.

vcluster.com/user-data-template-config​

Type: string

References a MachineConfigTemplate by name. The provider renders the template's cloudInitTemplate into a cloud-config document when vcluster.com/user-data isn't set. See Machine Config Templates for the template syntax and available variables.

The platform always merges resolved SSH keys into the cloud-config. For a tenant cluster worker, it also appends the join command. For a tenant cluster control plane machine, it appends the control plane installation commands. Independently provisioned Machines receive no tenant cluster registration command.

Try it yourself​

The community and experimental vCluster Bare Metal with KubeVirt guide runs the Metal3 provisioning flow locally with KubeVirt VMs as fake bare metal servers. It sets up a vind (vCluster in Docker) cluster, a Metal3 NodeProvider, and simulated BareMetalHosts with Redfish BMC endpoints. No physical hardware is required.