Create a Cluster
A workload cluster in Syself Autopilot is declared with a single Kubernetes Cluster object.
The object defines which Cluster Stack 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
ClusterClassfor 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 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:
$ 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 byspec.topology.classRef.name.K8S VERSION, used byspec.topology.version.
For the example above:
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 for how releases work.
Step 2: Define the cluster#
Create a file named 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:
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:
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:
- 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:
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:
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:
variables:
- name: region
value: nbg1
The example uses nbg1.
The control plane server type is configured at cluster level:
- name: controlPlaneMachineTypeHcloud
value: cpx41
Worker machine types can be set independently for each worker pool:
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 for how to choose ranges:
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:
$ 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:
$ 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:
$ 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:
$ 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:
$ 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:
$ 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 <none> 5m v1.36.3
mycluster-general-8jq2f-vd2kp-d9h2p Ready <none> 5m v1.36.3
mycluster-general-8jq2f-vd2kp-q6m8k Ready <none> 4m v1.36.3
All requested nodes should eventually report Ready.
You can also check the platform pods:
$ 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
replicascreates more workers. - Decreasing
replicasremoves 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 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
- Configure OIDC authentication
- Run a high-availability control plane
- Run bare-metal control planes and clusters
- Add or resize worker pools
- Add bare-metal worker pools
- Configure workload storage
- Configure network policies
- Configure GitOps
The Cluster object remains the central place for cluster-level and infrastructure-level configuration throughout the workload cluster's lifecycle.
Run It Yourself, or With Help
Every service on Syself Autopilot is standard Kubernetes objects in your own cluster, so you can run it yourself, have Syself operate it, or move between the two per service without migrating anything.
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.