Run bare-metal control planes and clusters
Syself Autopilot can run the Kubernetes control plane, worker nodes, or the entire workload cluster on Hetzner Robot dedicated servers.
Bare metal gives the cluster dedicated physical hardware, large amounts of CPU and memory, fast local storage, and predictable performance without sharing a virtualization host with other customers. It is particularly well suited to steady base loads, databases and data-heavy workloads, security requirements around single-tenant hardware, and environments where predictable infrastructure cost matters.
Running the control plane on bare metal also removes one dependency on cloud capacity. During an upgrade or recovery, Syself Autopilot reprovisions servers already assigned to the cluster instead of requesting another VM from the Hetzner Cloud capacity pool.
The trade-off is that bare metal is fixed capacity. The physical servers must already be available before Syself Autopilot can use them.
A cluster does not have to choose only one model. You can keep a dedicated bare-metal base and add Hetzner Cloud workers for elastic capacity.
When bare metal fits#
Bare metal works particularly well when capacity runs continuously, data should remain close to local storage, or workloads benefit from dedicated CPUs, memory, GPUs, NUMA topology, KVM, or high-throughput networking.
It can also be attractive financially for steady workloads because you pay for dedicated capacity rather than maintaining equivalent long-running cloud VMs. From a security perspective, each workload node is a dedicated physical machine rather than a guest sharing a virtualization host with other customers.
For the control plane, the fixed-inventory model has another advantage: the machines needed for upgrades and recovery already belong to you. The operation is not blocked waiting for a new HCloud VM type to become available in the region.
Bare metal is less suitable when capacity must frequently appear and disappear with demand. For those environments, combine bare-metal workers with an HCloud worker pool.
Before you begin#
Bare-metal servers must first be registered with Syself Autopilot as HetznerBareMetalHost resources.
Each resource represents one physical server in your Hetzner Robot account. Before using it in a cluster, register the server, configure the operating-system target disk, verify that it can reliably enter the Hetzner Rescue System, and label it according to the pool that should use it.
See Add bare-metal servers .
Organize bare-metal inventory with labels#
Selectors pick hosts by label, so each HetznerBareMetalHost carries labels that say which pool it belongs to. A minimal set is a role and a cluster:
metadata:
labels:
role: controlplane # or: worker
cluster: mycluster
You can add hardware-oriented labels (for example storage: nvme or workload: database) when an inventory holds several server classes. Registering and labeling the hosts themselves is covered in Add bare-metal servers ; this page uses those labels to select hosts for the cluster.
We recommend using selectors for production pools. Explicit labels make it clear which physical capacity belongs to which cluster and prevent unrelated pools from competing for the same hosts. This is especially important when you want to use the bare-metal servers' local storage
Run the control plane on bare metal#
Set controlPlane.class to hetznerbaremetal and select the hosts through controlPlaneHostSelectorBareMetal:
spec:
topology:
controlPlane:
class: hetznerbaremetal
replicas: 3
variables:
overrides:
- name: controlPlaneHostSelectorBareMetal
value:
matchLabels:
role: controlplane
cluster: mycluster
Syself Autopilot claims matching hosts, installs Syself Linux, initializes the first control plane, and joins the remaining members.
For production clusters, use at least three control plane replicas. See High-availability control plane .
Select hosts with matchLabels#
matchLabels requires every configured label to match:
variables:
overrides:
- name: controlPlaneHostSelectorBareMetal
value:
matchLabels:
role: controlplane
cluster: mycluster
This is the simplest approach when a set of servers belongs to one clearly defined pool.
Select hosts with matchExpressions#
Use matchExpressions when several groups of hosts are eligible:
variables:
overrides:
- name: controlPlaneHostSelectorBareMetal
value:
matchExpressions:
- key: role
operator: In
values:
- controlplane-group-1
- controlplane-group-2
This allows Syself Autopilot to claim any available server matching the expression instead of requiring one exact label value.
Understand the bare-metal rollout window#
Bare-metal control planes cannot create temporary surge capacity in the way HCloud control planes can.
An HCloud control plane normally uses maxSurge: 1, allowing the replacement VM to start before the old one is removed. Bare metal uses maxSurge: 0: the physical server must first leave the existing Machine, be reprovisioned, and then rejoin using the new Cluster Stack.
For a three-node control plane, the lifecycle looks like this:
flowchart LR
A["3 control-plane nodes healthy"] --> B["Drain and remove one member"]
B --> C["2 etcd members remain<br/>quorum still available"]
C --> D["Reprovision physical host"]
D --> E["Node rejoins etcd"]
E --> F["3 control-plane nodes healthy"]During the reprovisioning window, etcd still has two of three members and remains operational, but there is temporarily no additional control-plane failure tolerance. A second member becoming unavailable can remove quorum.
Start bare-metal control plane maintenance only when every member is healthy, and allow each replacement to fully rejoin before the rollout proceeds.
High availability on physical servers#
Each control plane replica runs on its own physical HetznerBareMetalHost. Unlike HCloud VMs, Robot servers do not require a placement group to keep several control plane replicas off the same hypervisor.
flowchart TB
A["Physical server A<br/>control-plane-1"]
B["Physical server B<br/>control-plane-2"]
C["Physical server C<br/>control-plane-3"]
Q["etcd quorum"]
A --> Q
B --> Q
C --> QWith three members, losing one physical server still leaves the two members required for etcd quorum.
This protects against a single server failure, not against failure of the entire Hetzner location or other shared infrastructure. Regional disaster recovery requires a separate recovery strategy.
Add bare-metal worker pools#
Bare-metal workers use the workeramd64baremetal MachineDeployment class.
spec:
topology:
workers:
machineDeployments:
- class: workeramd64baremetal
name: baremetal-workers
replicas: 3
variables:
overrides:
- name: workerHostSelectorBareMetal
value:
matchLabels:
role: worker
cluster: mycluster
workerHostSelectorBareMetal works like the control plane selector and supports both matchLabels and matchExpressions.
Syself Autopilot claims matching registered hosts until the requested replica count is satisfied.
Run an entirely bare-metal cluster#
Use bare metal for both control plane and workers when the cluster does not need elastic cloud capacity:
apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
name: mycluster
namespace: my-organization
spec:
clusterNetwork:
services:
cidrBlocks: ["10.128.0.0/12"]
pods:
cidrBlocks: ["192.168.0.0/16"]
serviceDomain: "cluster.local"
topology:
classRef:
name: hetzner-apalla-1-36-v1
version: v1.36.3
controlPlane:
class: hetznerbaremetal
replicas: 3
variables:
overrides:
- name: controlPlaneHostSelectorBareMetal
value:
matchLabels:
role: controlplane
cluster: mycluster
workers:
machineDeployments:
- class: workeramd64baremetal
name: baremetal-workers
replicas: 3
variables:
overrides:
- name: workerHostSelectorBareMetal
value:
matchLabels:
role: worker
cluster: mycluster
variables:
- name: region
value: nbg1
The management cluster remains operated separately by Syself. Only the workload cluster's infrastructure is placed on your dedicated servers.
Plan capacity ahead of time#
Bare-metal capacity is inventory rather than an API request.
If a worker pool requests five replicas, Syself Autopilot needs five matching physical hosts. When only four are available, the fifth Machine waits until compatible inventory becomes available.
Plan enough capacity for the normal workload while accounting for upgrades, hardware maintenance, failed servers, and future growth.
This is the main operational difference from HCloud: Syself Autopilot can request a new cloud VM, but it cannot manufacture another physical server when the bare-metal pool is full.
Bare-metal worker rollouts#
Workers are also reprovisioned one at a time without surge capacity.
flowchart LR
A["Worker healthy"] --> B["Cordon"]
B --> C["Drain workloads"]
C --> D["Release host"]
D --> E["Provision new Syself Linux"]
E --> F["Worker rejoins"]
F --> G["Continue with next worker"]The pool temporarily has one fewer usable worker, so the remaining nodes must have enough CPU and memory to accept displaced pods.
Critical workloads should use multiple replicas, graceful shutdown, topology spread, and suitable PodDisruptionBudgets. See Plan maintenance and prechecks .
Networking on bare metal#
Bare-metal and cloud nodes use the same Cilium networking model, including pod networking, Service load balancing, network policy, host firewall enforcement, and Hubble observability.
Depending on the selected dedicated hardware and network option, bare-metal servers can provide connectivity of up to 10 Gbit/s. This makes them particularly useful for databases, analytics systems, storage-heavy workloads, and other applications that move large amounts of data between nodes.
The cluster does not depend on bare-metal and cloud nodes sharing a trusted private network. The Cluster Stack establishes the required authenticated control-plane and node connectivity during provisioning.
Storage is local#
Bare-metal workers can expose local NVMe, SSD, and HDD devices through TopoLVM, using StorageClasses such as local-nvme, local-ssd, and local-hdd. TopoLVM is not installed by default: it is a one-time setup per cluster.
Local storage removes the network hop of cloud block storage and provides low, predictable latency. It is a strong fit for databases and other I/O-sensitive workloads.
Hetzner Cloud volumes cannot attach to Robot bare-metal servers. A bare-metal workload therefore needs local storage, an external storage service, or an application-level replicated storage architecture.
Local volumes remain tied to the physical server. Reprovisioning the operating system can preserve separately configured data disks, but the volume does not automatically move to another host when a pod is rescheduled.
See Use local storage on bare metal .
Bare metal or a mixed cluster#
You do not need to place every workload on the same infrastructure type.
A common architecture keeps predictable workloads on bare metal and uses HCloud for elastic capacity:
flowchart TB
C["Workload cluster"]
C --> BM["Bare-metal workers"]
C --> HC["HCloud workers"]
BM --> BM1["Steady base load"]
BM --> BM2["Databases and local storage"]
BM --> BM3["GPU and dedicated compute"]
HC --> HC1["Burst capacity"]
HC --> HC2["Autoscaled services"]
HC --> HC3["Temporary workloads"]This keeps the continuously used part of the cluster on dedicated infrastructure while retaining the ability to create additional workers when demand increases.
Add cloud workers later#
You can add an HCloud MachineDeployment to an existing bare-metal cluster:
spec:
topology:
workers:
machineDeployments:
- class: workeramd64baremetal
name: baremetal-workers
replicas: 3
variables:
overrides:
- name: workerHostSelectorBareMetal
value:
matchLabels:
role: worker
cluster: mycluster
- class: workeramd64hcloud
name: cloud-workers
replicas: 2
failureDomain: nbg1
variables:
overrides:
- name: workerMachineTypeHcloud
value: cpx41
Both pools join the same Kubernetes cluster. Use node selectors, affinity, and dedicated pools when workloads must run on one specific infrastructure class.
The HCloud pool can also be managed by the Cluster Autoscaler, giving the cluster dedicated baseline capacity with elastic cloud bursting.
See Autoscale a cluster .
Switch the control plane between cloud and bare metal#
controlPlane.class determines the infrastructure used by control plane Machines:
| Value | Control plane |
|---|---|
hcloud | Hetzner Cloud VMs |
hetznerbaremetal | Hetzner Robot dedicated servers |
Changing the class replaces the existing control plane Machines through a rolling migration. The existing VMs are not converted into physical nodes, and physical nodes are not converted into VMs.
Before switching to bare metal, register enough destination hosts and verify that the control plane is completely healthy. Avoid combining the migration with a Kubernetes version upgrade, and monitor each replacement until it has fully joined etcd.
Warning
Changing controlPlane.class replaces every control plane Machine.
With a three-member control plane, one member is unavailable while its replacement is being provisioned. Do not start the migration while another control plane member is already unhealthy.
When moving back to HCloud, make sure the destination region has enough capacity for the requested control plane server type before starting the rollout.
Move workers between backends safely#
For worker pools, create the destination capacity before removing the source.
Add the new worker pool and wait for its nodes to become Ready. Move workloads using placement rules where required, verify that application replicas are healthy, and migrate any stateful data separately before scaling down the old pool.
Warning
Local bare-metal PersistentVolumes do not migrate to HCloud workers.
Replicate or move the application data before removing a bare-metal worker that owns local persistent storage.
Understand the trade-offs#
| Bare metal | Hetzner Cloud | |
|---|---|---|
| Hardware | Dedicated physical server | Virtual machine |
| Capacity | Pre-ordered inventory | Created through API |
| Scale up | Claim a free host | Create a VM |
| Scale down | Release the host | Delete the VM |
| Upgrade | Reprovision existing host | Replacement can be created first |
| Surge capacity | No | Yes |
| Storage | Local disks | Hetzner Cloud volumes |
| Specialized hardware | GPUs, NUMA, KVM, large local disks | Depends on available VM types |
| Elastic bursting | Limited by inventory | Yes |
| Physical tenancy | Single tenant | Shared virtualization host possible |
The important distinction is capacity ownership. With bare metal, you already own the capacity and Syself Autopilot manages its lifecycle. With HCloud, Syself Autopilot requests capacity as the desired state changes.
Common architectures#
A bare-metal control plane with HCloud workers keeps Kubernetes itself independent from HCloud capacity shortages while retaining elastic workload capacity.
A fully bare-metal cluster fits steady workloads, databases, dedicated compute, and environments that prefer single-tenant physical infrastructure.
A bare-metal base with HCloud bursting keeps predictable minimum demand on dedicated servers and lets an autoscaled cloud pool handle temporary peaks.
flowchart LR
A["Bare-metal base capacity"] --> C["Workload cluster"]
B["Elastic HCloud capacity"] --> C
C --> D["Steady workloads"]
C --> E["Burst workloads"]Related#
High-availability control plane
Run a highly available Kubernetes control plane with three or more nodes, understand etcd quorum, size control-plane servers correctly, and spread Hetzner Cloud nodes across physical hosts.
Run a worker-less cluster
Run a control-plane-only cluster for platform components, and know what stops working without workers.