A workload cluster in Syself Autopilot is declared with a single Kubernetes `Cluster` object. The object defines which [Cluster Stack](/docs/hetzner/apalla/concepts/foundations/cluster-stacks) release the cluster runs, its Kubernetes version, control plane and worker capacity, infrastructure settings, and other cluster-level configuration. You apply the `Cluster` object to the Syself Autopilot management cluster. From there, Syself Autopilot creates and provisions the required servers, bootstraps Kubernetes, installs the platform components, and continuously reconciles the cluster to the state you declared. These steps create a standard Hetzner Cloud cluster. You can extend the same `Cluster` object with additional worker pools, bare-metal servers, OIDC, custom load balancer settings, and other supported configuration. ## Before you begin You need: - Access to your Syself management cluster with `kubectl`. - An organization namespace containing the `ClusterClass` for the Kubernetes version you want to use. - Enough Hetzner Cloud quota for the control plane and worker servers you want to create. Follow the steps in [Getting Started](/docs/hetzner/apalla/getting-started/overview) if you do not fulfill all the requirements. ## The Cluster object A Syself Autopilot cluster is configured through the `Cluster` resource. The important parts are: | Field | What it defines | | ---------------------------- | ---------------------------------------------------------------------- | | `metadata.name` | Name of the workload cluster | | `spec.topology.classRef` | Cluster Stack release and resulting `ClusterClass` used by the cluster | | `spec.topology.version` | Kubernetes version | | `spec.topology.controlPlane` | Control plane type and replica count | | `spec.topology.workers` | Worker pools and their replica counts | | `spec.topology.variables` | Cluster-level infrastructure and platform configuration | | `spec.clusterNetwork` | Pod and Service networks and the service domain | The Cluster Stack defines the supported platform and available configuration. The `Cluster` object defines the infrastructure you want and which supported settings should be used for this cluster. ## Step 1: Choose a Cluster Stack release Syself provides the Cluster Stack releases in your management cluster and keeps them available for you to use. List the ones you can run: ```console $ kubectl get clusterstackrelease NAME K8S VERSION READY AGE REASON MESSAGE hetzner-apalla-1-36-v1 v1.36.3 true 2d ``` Choose the release you want to run. You need two values from it: - `NAME`, used by `spec.topology.classRef.name`. - `K8S VERSION`, used by `spec.topology.version`. For the example above: ```yaml classRef: name: hetzner-apalla-1-36-v1 version: v1.36.3 ``` The release identifies the complete Syself platform version: Kubernetes, Syself Linux, Cluster API templates, networking, storage integrations, in-cluster components, lifecycle behavior, and the other components tested together by Syself. See [Cluster Stacks](/docs/hetzner/apalla/concepts/foundations/cluster-stacks) for how releases work. ## Step 2: Define the cluster Create a file named `cluster.yaml`: ```yaml title="cluster.yaml" 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: hcloud replicas: 3 workers: machineDeployments: - class: workeramd64hcloud name: general replicas: 3 failureDomain: nbg1 variables: overrides: - name: workerMachineTypeHcloud value: cpx41 variables: - name: region value: nbg1 - name: controlPlaneMachineTypeHcloud value: cpx41 ``` This object is enough to declare the cluster. Syself Autopilot derives the underlying control plane, MachineDeployments, Machines, infrastructure resources, bootstrap configuration, node images, and in-cluster components from the selected Cluster Stack. ## Cluster metadata The `Cluster` is a normal Kubernetes object, so you can add your own labels and annotations under `metadata`. For example: ```yaml metadata: name: mycluster labels: environment: production client: example-company ``` Labels are useful for organizing clusters and integrating them with your own automation. These labels describe the `Cluster` object in the management cluster. They do not automatically become labels on every node or workload inside the workload cluster. ## Control plane sizing The control plane is configured under: ```yaml controlPlane: class: hcloud replicas: 3 ``` `replicas` defines how many control plane servers Syself Autopilot maintains. A three-node control plane provides multiple API server and etcd members and allows the platform to replace control plane nodes one at a time while maintaining quorum. The server type is configured separately through the cluster-level variable: ```yaml - name: controlPlaneMachineTypeHcloud value: cpx41 ``` This separates **how many control plane servers you want** from **which type of server they should use**. ## Worker pools Workers are defined as MachineDeployments: ```yaml workers: machineDeployments: - class: workeramd64hcloud name: general replicas: 3 failureDomain: nbg1 ``` Each MachineDeployment is one independently managed worker pool. `replicas` determines how many workers Syself Autopilot maintains in that pool. The worker machine type can be configured for the pool through a variable override: ```yaml variables: overrides: - name: workerMachineTypeHcloud value: cpx41 ``` This becomes useful when a cluster has multiple worker pools. For example, you might have: - A general-purpose worker pool. - A larger compute worker pool. - A bare-metal database pool. - A GPU worker pool. Each pool can have its own replica count and supported infrastructure settings while remaining part of the same workload cluster. ## Region and machine types The cluster's Hetzner region is configured with: ```yaml variables: - name: region value: nbg1 ``` The example uses `nbg1`. The control plane server type is configured at cluster level: ```yaml - name: controlPlaneMachineTypeHcloud value: cpx41 ``` Worker machine types can be set independently for each worker pool: ```yaml variables: overrides: - name: workerMachineTypeHcloud value: cpx41 ``` This lets you size control plane and workload capacity separately. ## Pod and Service networks Every workload cluster needs dedicated IP ranges for pods and Kubernetes Services. `spec.clusterNetwork` is part of the cluster's required configuration, so every `Cluster` object carries it. The values below are the ones these guides use throughout; see [Configure pod and service subnets](/docs/hetzner/apalla/network/egress/configure-pod-and-service-subnets) for how to choose ranges: ```yaml spec: clusterNetwork: services: cidrBlocks: ["10.128.0.0/12"] pods: cidrBlocks: ["192.168.0.0/16"] serviceDomain: "cluster.local" ``` > [!WARNING] > Pod and Service networks are creation-time settings. > > The pod CIDRs, the Service CIDRs, and the service domain cannot be changed once the cluster exists. They are wired into every node, into Cilium, and into the API server, so a later change cannot take effect and is rejected on update. Adding a second range for dual-stack is rejected the same way. If you need something other than the defaults, set it before you create the cluster. If you do change the ranges, make sure they do not overlap with networks that the cluster must communicate with. ## Step 3: Apply the Cluster Apply the object to the management cluster: ```console $ kubectl apply -f cluster.yaml cluster.cluster.x-k8s.io/mycluster created ``` This creates the desired state for the workload cluster. From this point, Syself Autopilot handles the provisioning process. You do not create the individual control plane or worker servers yourself. ## Step 4: Watch the cluster come up You can watch the Cluster and its Machines from the management cluster: ```console $ kubectl get cluster,machines -n my-organization ``` During provisioning, Machines appear as Syself Autopilot creates the requested control plane and worker infrastructure. For the example cluster, you should eventually see three control plane Machines and three worker Machines: ```console $ kubectl get machines -n my-organization NAME CLUSTER NODE NAME FAILURE DOMAIN READY AVAILABLE UP-TO-DATE PHASE AGE VERSION mycluster-k9r2f-6g7dx mycluster mycluster-k9r2f-6g7dx nbg1 True True True Running 11m v1.36.3 mycluster-k9r2f-b7pkl mycluster mycluster-k9r2f-b7pkl nbg1 True True True Running 10m v1.36.3 mycluster-k9r2f-r8n4m mycluster mycluster-k9r2f-r8n4m nbg1 True True True Running 9m v1.36.3 mycluster-general-8jq2f-vd2kp-7bs4n mycluster mycluster-general-8jq2f-vd2kp-7bs4n nbg1 True True True Running 7m v1.36.3 mycluster-general-8jq2f-vd2kp-d9h2p mycluster mycluster-general-8jq2f-vd2kp-d9h2p nbg1 True True True Running 7m v1.36.3 mycluster-general-8jq2f-vd2kp-q6m8k mycluster mycluster-general-8jq2f-vd2kp-q6m8k nbg1 True True True Running 6m v1.36.3 ``` Each Machine represents one server being managed as part of the workload cluster. You can continuously watch provisioning with: ```console $ kubectl get machines -w ``` Provisioning includes more than creating the servers. Syself Autopilot installs Syself Linux, initializes the control plane, joins additional control plane and worker nodes, establishes networking and firewall rules, installs the required in-cluster components, and waits for the cluster to become operational. ## Step 5: Verify the cluster Once the Machines are running, retrieve the workload cluster kubeconfig: ```console $ kubectl get secret mycluster-kubeconfig \ -n my-organization \ -o jsonpath='{.data.value}' \ | base64 -d \ > mycluster-kubeconfig.yaml ``` Use it to check the new workload cluster: ```console $ KUBECONFIG=./mycluster-kubeconfig.yaml kubectl get nodes NAME STATUS ROLES AGE VERSION mycluster-k9r2f-6g7dx Ready control-plane 8m v1.36.3 mycluster-k9r2f-b7pkl Ready control-plane 7m v1.36.3 mycluster-k9r2f-r8n4m Ready control-plane 6m v1.36.3 mycluster-general-8jq2f-vd2kp-7bs4n Ready 5m v1.36.3 mycluster-general-8jq2f-vd2kp-d9h2p Ready 5m v1.36.3 mycluster-general-8jq2f-vd2kp-q6m8k Ready 4m v1.36.3 ``` All requested nodes should eventually report `Ready`. You can also check the platform pods: ```console $ KUBECONFIG=./mycluster-kubeconfig.yaml kubectl get pods -A ``` Some components may still be starting immediately after the nodes first register. The cluster is fully initialized once the requested nodes are `Ready` and the core platform components have become healthy. Your workload cluster is now running and continuously managed by Syself Autopilot. ## What happens after you apply the Cluster The `Cluster` object remains the desired state of the cluster after creation. Changing supported fields later can cause Syself Autopilot to reconcile the infrastructure accordingly. For example: - Increasing a worker pool's `replicas` creates more workers. - Decreasing `replicas` removes workers. - Changing a machine type rolls the affected Machines. - Moving to a new Cluster Stack release starts the supported platform upgrade process. - Adding another MachineDeployment creates another worker pool. You do not need to rerun a cluster creation procedure. You update the same declarative object. See [Declarative Cluster Management](/docs/hetzner/apalla/concepts/foundations/declarative-cluster-management) for the reconciliation model. ## Next steps Once the cluster is running, continue with the configuration that applies to your environment: - [Access a cluster through a domain](/docs/hetzner/apalla/clusters/configure/access-through-a-domain) - [Configure OIDC authentication](/docs/hetzner/apalla/clusters/configure/configure-oidc) - [Run a high-availability control plane](/docs/hetzner/apalla/clusters/configure/high-availability-control-plane) - [Run bare-metal control planes and clusters](/docs/hetzner/apalla/clusters/configure/fully-bare-metal-cluster) - [Add or resize worker pools](/docs/hetzner/apalla/servers-and-nodes/pools/scale-a-pool) - [Add bare-metal worker pools](/docs/hetzner/apalla/servers-and-nodes/provision/add-bare-metal-servers) - [Configure workload storage](/docs/hetzner/apalla/storage/overview) - [Configure network policies](/docs/hetzner/apalla/security/segment-with-network-policies) - [Configure GitOps](/docs/hetzner/apalla/clusters/gitops/overview) The `Cluster` object remains the central place for cluster-level and infrastructure-level configuration throughout the workload cluster's lifecycle.