A worker-less cluster runs only control-plane nodes, with no worker pool. It fits a cluster that exists to host platform components rather than tenant workloads, a small management or tooling cluster, for example. It is a deliberate, narrow choice: know what still works and what stops before you run one. ## Declare it by omitting the workers Leave the `workers` section out of the `Cluster` object entirely. The control plane comes up and the cluster is Ready with no worker Machines: ```yaml title="cluster.yaml" apiVersion: cluster.x-k8s.io/v1beta2 kind: Cluster metadata: name: tooling 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: hcloud replicas: 3 variables: - name: region value: nbg1 - name: controlPlaneMachineTypeHcloud value: cpx32 ``` ## What runs, and what does not Control-plane nodes carry a `NoSchedule` taint that keeps ordinary pods off them. The in-cluster components that must run somewhere tolerate that taint, so they fall back onto the control-plane nodes when there is no worker to take them. Your own workloads, and anything that does not tolerate the control-plane taint, do not schedule at all. Two consequences to plan for: - **No block storage.** The CSI components that back Hetzner Cloud volumes cannot run on control-plane nodes, so a worker-less cluster has no dynamically provisioned block storage. The `csi-controller` Deployment stays `Pending` in `kube-system` for as long as the cluster has no workers. This is expected, not a fault. Do not run stateful workloads that need a PersistentVolume here. - **No tenant workloads.** Your applications do not tolerate the control-plane taint and will sit `Pending`. A worker-less cluster is for the control plane and platform components, not for running your apps. > [!NOTE] > The Hetzner CCM and the Cilium operator run on the control plane in this setup. Confirm the exact set of in-cluster components that do and do not fall back for your workload before relying on a worker-less cluster in production. ## One or three control planes The control-plane count is the same decision as any cluster: - **One** control-plane node for a disposable or non-production tooling cluster where control-plane downtime is acceptable. - **Three** for anything that must stay available, so the in-cluster components running there keep a quorum and survive a node replacement. See [High-availability control plane](/docs/hetzner/apalla/clusters/configure/high-availability-control-plane). With everything running on the control plane, size those nodes with headroom for the in-cluster components, not just for etcd and the API server. On three control planes, the platform spreads these in-cluster components across the nodes where it can, so losing one node does not necessarily take a component down. Single-replica in-cluster components simply restart on another control-plane node. ## Add workers later A worker-less cluster is not a dead end. Add a `machineDeployments` entry when you need to run real workloads, and the in-cluster components move back onto the new workers. See [Add cloud servers](/docs/hetzner/apalla/servers-and-nodes/provision/add-cloud-servers). For the full variable list, see [Cluster variables](/docs/hetzner/apalla/reference/cluster-variables). ## Related - [Autoscale a cluster](/docs/hetzner/apalla/clusters/configure/autoscale-a-cluster), add and remove workers automatically once you add a pool - [High-availability control plane](/docs/hetzner/apalla/clusters/configure/high-availability-control-plane), sizing and quorum for the control plane