KubeOne on Hetzner
Set up a production Kubernetes cluster using KubeOne as the provisioner.
Prerequisites
- lok8s CLI installed
- hcloud CLI installed and authenticated
- An SSH key pair added to your Hetzner project
- Hetzner Cloud API token exported as
HCLOUD_TOKEN
Cluster configuration
Create a cluster.lok8s.yaml with kind: KubeOne:
yaml
apiVersion: cluster.lok8s.dev/v1beta1
kind: KubeOne
metadata:
name: production
spec:
kubernetes:
version: "v1.35.5"
provider: hetzner
hcloud:
region: fsn1
sshPublicKeyFile: "~/.ssh/id_ed25519.pub"
network:
cidr: "10.0.0.0/16"
ssh:
user: root
publicKeyFile: "~/.ssh/id_ed25519.pub"
privateKeyFile: "~/.ssh/id_ed25519"
controlPlane:
replicas: 3
type: cx33
workers:
platform:
replicas: 2
type: cpx31Provision
bash
lo provisionThis will:
- Create Hetzner Cloud servers for control plane and workers
- Set up the private network
- Install Kubernetes via KubeOne
- Save the kubeconfig to
~/.kube/config
Verify
bash
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# cp-1 Ready control-plane 5m v1.35.5
# cp-2 Ready control-plane 5m v1.35.5
# cp-3 Ready control-plane 5m v1.35.5
# worker-1 Ready <none> 4m v1.35.5
# worker-2 Ready <none> 4m v1.35.5HA considerations
- Use
controlPlane.replicas: 3for production - Control plane nodes are spread across fault domains automatically
- The private network (
hcloud.network.cidr) isolates cluster traffic
Adding bootstrap addons
Cluster-infra addons (CNI, CCM, cert-manager, monitoring, …) are listed under spec.bootstrap and applied in order at provision time:
yaml
bootstrap:
- cilium
- ccm
- monitoringRun lo provision again to apply bootstrap changes incrementally.
Next steps
- Registration — register with the kubehz dashboard
- GitHub Actions — automate provisioning in CI
- CAPI — alternative provisioner using Cluster API
Doc status
| Aspect | Detail |
|---|---|
| State | active |
| Last reviewed | 2026-07-10 |