Cluster variables
Every value you can set under spec.topology.variables on a Cluster is here, with its type, default, and what it changes. Syself reads these variables and turns them into settings on the Hetzner infrastructure and on the nodes. For how a variable becomes a node file or an API server flag, see Declarative cluster management .
The cluster template that ships with your cluster stack release declares the variables.
How to read this#
- Required variables must be set on every cluster. The rest have a default or are optional.
…Hcloudvariables apply to HCloud (cloud VM) machines.…BareMetalvariables apply to Hetzner Robot bare-metal machines. A cluster uses one backend per machine pool.- Today a cluster supports amd64 CPUs only and a single Hetzner region. The
controlPlaneMachineArchHcloudvariable enforces the architecture: its only allowed value isamd64. - A few variables are kept in the schema but not offered as features, so a new cluster should not set them:
hcloudNetwork(private networks) andworkerRaidEnabledBareMetal/workerRaidLevelBareMetal(bare-metal RAID). The schema accepts only their disabled value, and the keys remain so existing manifests keep validating.
Control-plane endpoint and load balancer#
| Variable | Type | Required | Default | What it sets |
|---|---|---|---|---|
clusterEndpointHost | string | no | "" | The hostname or IP clients use to reach the API server. |
clusterEndpointPort | integer | no | 443 | The port clients use to reach the API server. |
clusterLoadBalancerType | string | no | lb11 | The Hetzner load balancer product for the control plane (lb11, lb21, lb31). |
clusterLoadBalancerName | string | no | none | A custom name for the control-plane load balancer. |
region | string | yes | fsn1 | The Hetzner region for all cluster infrastructure. One region per cluster. |
Machine type, architecture, and placement#
| Variable | Type | Required | Default | What it sets |
|---|---|---|---|---|
controlPlaneMachineTypeHcloud | string | yes | cpx32 | The HCloud server type for control-plane machines. |
workerMachineTypeHcloud | string | yes | cpx32 | The HCloud server type for worker machines. |
controlPlaneMachineArchHcloud | string | yes | amd64 | Architecture of HCloud control planes. Only amd64 is supported; ARM is not available. |
controlPlanePlacementGroupNameHcloud | string | no | none | HCloud placement group for control-plane machines. |
workerMachinePlacementGroupNameHcloud | string | no | none | HCloud placement group for worker machines. |
hcloudPlacementGroups | array of objects | no | none | Cluster-level HCloud placement groups (name, type). |
HCloud SSH#
SSH access to HCloud nodes is not configured with a topology variable. The SSH key attached to HCloud nodes is the one named in the hcloud-ssh-key-name field of the hetzner Secret the cluster references. See Prepare your Hetzner account for how that Secret is created.
Bare-metal host selection and RAID#
| Variable | Type | Required | Default | What it sets |
|---|---|---|---|---|
controlPlaneHostSelectorBareMetal | object | no | none | hostSelector that binds control-plane machines to a HetznerBareMetalHost. Subfields: matchLabels, matchExpressions (key, operator, values). |
workerHostSelectorBareMetal | object | no | none | Same, for worker machines. |
workerRaidEnabledBareMetal | boolean | no | false | Bare-metal RAID is not offered. The schema accepts only false, so a Cluster that sets it true is rejected at admission. The variable key is kept so existing manifests that set it false keep validating. Do not add it to new clusters. |
workerRaidLevelBareMetal | integer | no | 1 | Has no effect, because RAID is not offered. The key is kept in the schema for compatibility; do not add it to new clusters. |
API server policy#
| Variable | Type | Required | Default | What it sets |
|---|---|---|---|---|
oidcIssuerUrl | string | no | none | The issuer URL of your OIDC identity provider. OIDC (OpenID Connect) is a standard for identity federation. Takes effect only when set. |
oidcClientID | string | no | none | The client ID registered with your identity provider. |
oidcUsernameClaim | string | no | sub | The token claim used as the Kubernetes username. |
oidcGroupsClaim | string | no | groups | The token claim used for the user's groups. |
etcdEncryptionSecretRef | object | no | none | etcd encryption at rest. Subfields: enabled (default false), name (default etcd-encryption), key (default config). When enabled, writes /etc/kubernetes/encryption-provider.yaml from the named Secret and adds the API server encryption-provider-config flags. |
kubeGatePolicySecretRef | object | no | none | Loads a source-IP allow policy for the API server load-balancer path. KubeGate is the per-node gateway in front of the API server. Subfields: enabled (default false), name (default kubegate-policy), key (default policy.yaml). When enabled, it drops load-balancer connections whose source IP is not in the named Secret's sourceCIDRs list. See Restrict API server access . |
DNS#
| Variable | Type | Required | Default | What it sets |
|---|---|---|---|---|
dnsServers | array of strings | no | [] | Per-cluster DNS servers. Renders into /run/syself/node-config.json (dns.servers), which the provisioner reads to configure the host resolver and the kubelet resolvConf. When unset, the node image's default DNS applies. |
dnsServers sets the DNS resolvers (the servers that answer name lookups) the nodes use. You only set it to point nodes at your own resolvers. When you leave it unset, nodes use the image defaults, 1.1.1.1 and 8.8.8.8.
Pass IPv4 addresses as a list of strings under spec.topology.variables:
spec:
topology:
variables:
- name: dnsServers
value:
- "10.0.0.53"
- "1.1.1.1"
The scope is the node. The kubelet's resolv.conf (at /etc/kubernetes/resolv.conf) is also where the in-cluster CoreDNS forwards external queries. A pod on the default ClusterFirst DNS policy asks CoreDNS first, not these resolvers directly: CoreDNS answers cluster-internal names itself and forwards the rest to the resolvers you set here. So dnsServers changes the node resolvers and, through CoreDNS, the upstream for external pod queries. It does not change that a ClusterFirst pod's first hop is CoreDNS.
Set dnsServers when the resolvers baked into the node image do not fit, for example when nodes must resolve names against an internal or private resolver. Leave it unset to keep the image defaults.
IP families#
There is no ipFamilies topology variable today. A cluster's IP family is fixed at IPv4. IPv6 and dual-stack support are planned but not available yet.
Private networks#
| Variable | Type | Required | Default | What it controls |
|---|---|---|---|---|
hcloudNetwork | object | no | enabled: false | Private networks are not offered. The schema accepts only enabled: false, so a Cluster that sets it true is rejected at admission. The variable key is kept so existing manifests that set it false keep validating. |
Infrastructure backends and rollout behavior#
The cluster template supports two infrastructure backends: HCloud (cloud VMs) and Hetzner Robot (bare metal). Each backend handles control-plane nodes and worker nodes separately.
| Backend | Rollout strategy |
|---|---|
| HCloud control plane | maxSurge=1: a new node starts before the old one is removed |
| Bare-metal control plane | maxSurge=0: the physical host must be released before it is reprovisioned |
| HCloud workers | maxSurge=1, maxUnavailable=0: new nodes come up before old ones are removed |
| Bare-metal workers | maxSurge=0, maxUnavailable=1, with a constant hostname across reprovisioning |
Both control-plane backends share the same API server, etcd, scheduler, and controller-manager settings. They differ in rollout strategy and in what triggers automatic remediation: a bare-metal control plane is remediated only on Ready=False, while the health daemon's own conditions alert a human there instead.
When variables take effect#
Most variables take effect on every cluster, always. Some are conditional.
| Variable | Condition for taking effect |
|---|---|
controlPlaneMachineArchHcloud | Only amd64 is applied (the only supported architecture today) |
dnsServers | Applied only when the variable is set |
oidcIssuerUrl | The OIDC API server flags are added only when this is set |
etcdEncryptionSecretRef.enabled | The encryption config and API server flags are added only when enabled: true |
kubeGatePolicySecretRef.enabled | The KubeGate policy is written to the control planes only when enabled: true |
clusterLoadBalancerName | A custom load balancer name is set only when this is set |
hcloudPlacementGroups | Cluster-level placement groups are added only when this is set |
controlPlanePlacementGroupNameHcloud / workerMachinePlacementGroupNameHcloud | Placement group name is set per node type only when set |
controlPlaneHostSelectorBareMetal / workerHostSelectorBareMetal | Host selector is applied only when set |
All other variables in this reference are applied to every cluster.
Fixed network settings#
The pod and service CIDRs are fixed at cluster creation. You don't set them as topology variables; they come from the cluster's network definition.
- Pod CIDR: default
100.64.0.0/11. Written to every node at join time. - Service CIDR: default
100.96.0.0/16. Written to every node at join time.
These pair with maxPods: 220 and a per-node subnet that leaves room for that many pod IPs. Both are set once at cluster creation and cannot be changed on a running cluster.
Related#
- Declarative cluster management : how variables become cluster configuration.
- Configure OIDC : step-by-step guide for the OIDC variables.
- Encrypt etcd : step-by-step guide for
etcdEncryptionSecretRef. - Bare-metal control planes : using
controlPlaneHostSelectorBareMetal. - Node labels and annotations : labels Syself sets at node provisioning time.
Runtime threat detection
Deploy Falco or an equivalent to catch what the preventive controls miss, then wire it into a detect-and-respond loop for a compromised workload.
Node labels and annotations
All labels and annotations on a Syself Autopilot node, who sets each one, and what reads it. Covers role, topology, hardware, bootstrap, and health annotation.