kubeone

Bereitstellung von KubeOne-Clustern auf der Hetzner Cloud

Abubakar Siddiq Ango
Abubakar Siddiq Ango Senior Developer Advocate
18. März 2026 11 Min. Lesezeit Mittelstufe
Erste Schritte Automatisierung Multi-Cloud

Voraussetzungen

  • Hetzner-Cloud-Konto mit einem API-Token (console.hetzner.cloud)
  • KubeOne ist installiert – siehe „KubeOne installieren
  • Terraform 1.5+ ist installiert
  • SSH-Schlüsselpaar verfügbar unter ~/.ssh/id_rsa und ~/.ssh/id_rsa.pub
  • kubectl ist auf Ihrem lokalen Rechner installiert

Einführung

Hetzner Cloud ist eine beliebte Wahl für Kubernetes-Bereitstellungen in Europa. Die Preisgestaltung ist übersichtlich – Server mit gemeinsam genutzten vCPUs sind bereits ab wenigen Euro pro Monat erhältlich – und die Infrastruktur ist zuverlässig. Für Teams, die auf die Komplexität (oder die Kosten) von AWS, GCP oder Azure verzichten können, bietet Hetzner alles, was man für den Betrieb von Kubernetes-Clustern in der Produktion benötigt, und das zu einem Bruchteil des Preises.

KubeOne bietet erstklassige Unterstützung für die Hetzner Cloud. Die offiziellen Terraform-Beispiele übernehmen die gesamte Bereitstellung der Infrastruktur – Server, Netzwerke, Load Balancer, Firewalls und SSH-Schlüssel –, sodass Sie nichts davon manuell konfigurieren müssen. Sie geben lediglich einen Clusternamen und ein API-Token an, und KubeOne kümmert sich um den Rest.

In diesem Tutorial richten Sie mithilfe von KubeOne und Terraform einen hochverfügbaren Kubernetes-Cluster mit drei Knoten auf der Hetzner Cloud ein. Am Ende verfügen Sie über einen produktionsreifen Cluster mit einem externen Load Balancer, privatem Netzwerk, automatischer Bereitstellung von Worker-Knoten über den Machine-Controller und einem klaren Upgrade-Pfad für zukünftige Kubernetes-Versionen.

Was Sie lernen werden:

  • So konfigurieren Sie den Cloud-Anbieter Hetzner für KubeOne
  • So nutzen Sie die offiziellen Terraform-Beispiele zur Bereitstellung von Infrastruktur
  • So erstellen und wenden Sie ein KubeOneCluster-Manifest für Hetzner an
  • So überprüfen Sie Ihren Cluster und fügen Worker-Knoten hinzu
  • So schätzen und optimieren Sie Kosten

Schritt 1: Erstellen Sie ein Hetzner Cloud-API-Token

Sowohl KubeOne als auch Terraform benötigen ein API-Token, um mit der Hetzner Cloud zu kommunizieren. Melden Sie sich bei der Hetzner Cloud Console an, wählen Sie Ihr Projekt aus und navigieren Sie zu „Sicherheit > API-Token“.

Erstellen Sie ein neues Token mit Lese- und Schreibberechtigungen. Kopieren Sie das Token sofort – Hetzner zeigt es nur einmal an.

Exportieren Sie das Token als Umgebungsvariable. Sowohl Terraform als auch KubeOne lesen diese Variable automatisch aus:

Exportieren HCLOUD_TOKEN="Ihr-API-Token-hier"

Tipp: In Produktionsumgebungen sollten Sie das Token in einem Secrets-Manager oder einem .env Datei, die von der Versionskontrolle ausgeschlossen ist. Committe keine API-Token in dein Repository.

Überprüfen Sie, ob das Token funktioniert, indem Sie Ihre vorhandenen Server auflisten (die Liste ist leer, wenn es sich um ein neues Projekt handelt):

curl -s -H "Authorization: Bearer $HCLOUD_TOKEN" https://api.hetzner.cloud/v1/servers | jq '.servers | length'

Erwartetes Ergebnis:

0

Schritt 2: Einrichten der Terraform-Konfiguration

KubeOne enthält offizielle, in der Produktion erprobte Terraform-Beispiele für jeden unterstützten Cloud-Anbieter. Anstatt Terraform-Code von Grund auf neu zu schreiben, nutzen Sie das Hetzner-Beispiel als Ausgangspunkt.

Laden Sie die KubeOne-Version herunter und entpacken Sie die Terraform-Beispiele:

# Die neueste Version von KubeOne herunterladen
curl -sfL https://get.kubeone.io | sh

# Die Beispiele sind im Release enthalten
# Kopiere das Hetzner-Beispiel in dein Projektverzeichnis
mkdir kubeone-hetzner && cd kubeone-hetzner
cp -r /usr/local/share/kubeone/examples/terraform/hetzner/* .

Falls sich die Beispiele nicht unter diesem Pfad befinden, klone sie bitte von GitHub:

mkdir kubeone-hetzner && cd kubeone-hetzner
git clone --depth 1 https://github.com/kubermatic/kubeone.git /tmp/kubeone-repo
cp -r /tmp/kubeone-repo/examples/terraform/hetzner/* .
rm -rf /tmp/kubeone-repo

Ihr Verzeichnis sollte nun Folgendes enthalten:

kubeone-hetzner/
├── main.tf
├── output.tf
├── variables.tf
└── versions.tf

Diese Dateien definieren die gesamte Infrastruktur: Control-Plane-Server, privates Netzwerk, Subnetz, Load Balancer, Firewall-Regeln, SSH-Schlüssel und Platzierungsgruppen für die Serververteilung.

Schritt 3: Terraform-Variablen konfigurieren

Erstellen Sie eine terraform.tfvars Datei mit Ihren Cluster-Einstellungen:

cluster_name = "production"

# Servertypen – siehe https://www.hetzner.com/cloud für aktuelle Preise
control_plane_type = "cpx21"    # 3 vCPU, 4 GB RAM, 80 GB SSD
worker_type        = "cpx31"    # 4 vCPU, 8 GB RAM, 160 GB SSD

# Standort des Rechenzentrums
Rechenzentrum = „nbg1“             # Nürnberg. Alternativen: fsn1 (Falkenstein), hel1 (Helsinki)

# Von machine-controller verwaltete Worker-Knoten
initial_machinedeployment_replicas = 2

# SSH-Schlüssel für den Knotenzugriff
ssh_public_key_file = "~/.ssh/id_rsa.pub"

Auswahl der Servertypen

Hetzner Cloud bietet Server mit gemeinsam genutzten vCPUs (CX/CPX-Serie) und dedizierten vCPUs (CCX-Serie) an. Für Kubernetes:

RolleEmpfohlener TypTechnische DatenUngefähre monatliche Kosten
Steuerungsebenecpx213 vCPU, 4 GB RAM, 80 GB~5 EUR
Arbeitnehmer (allgemein)cpx314 vCPU, 8 GB RAM, 160 GB~10 EUR
Arbeiter (Informatik)cpx418 vCPU, 16 GB RAM, 240 GB~19 EUR
Arbeitnehmer (engagiert)ccx132 vCPU, 8 GB RAM, 80 GB~14 EUR
Lastenausgleichlb1125 Ziele, 5 Dienstleistungen~6 EUR

Hinweis: Hetzner aktualisiert regelmäßig seine Servertypen und Preise. Informieren Sie sich vor der Bereitstellung auf der Hetzner Cloud-Preisseite über die aktuellen Preise.

Verfügbare Terraform-Variablen

Das Hetzner-Terraform-Beispiel unterstützt folgende Variablen:

VariableStandardBeschreibung
Clustername(erforderlich)Bezeichnung für alle Ressourcen
Anzahl der Control-Plane-VMs3Anzahl der Knoten der Steuerungsebene
Steuerungsebene-Typcx23Hetzner-Servertyp für die Steuerungsebene
Arbeitnehmertypcx23Hetzner-Servertyp für Worker
lb_typelb11Hetzner-Load-Balancer-Typ
Rechenzentrumnbg1Hetzner-Rechenzentrum
osUbuntuBetriebssystem (Ubuntu oder flatcar)
ssh_public_key_file~/.ssh/id_rsa.pubPfad zum öffentlichen SSH-Schlüssel
ssh_port22SSH-Port
Anzahl der Replikate bei der ersten Maschinenbereitstellung2Anzahl der Worker-Knoten
disable_kubeapi_loadbalancerfalschAuf „true“ setzen, um die Erstellung von LB zu überspringen

Schritt 4: Bereitstellung der Infrastruktur

Terraform initialisieren, den Plan überprüfen und anwenden:

terraform init
terraform plan

Überprüfen Sie die Planausgabe. Es sollten Ressourcen für folgende Bereiche erstellt worden sein:

  • 3 Control-Plane-Server (hcloud_server.control_plane)
  • 1 privates Netzwerk mit einem Subnetz (hcloud_network.net, hcloud_network_subnet.kubeone)
  • 1 Load Balancer für den API-Server (hcloud_load_balancer.load_balancer)
  • 1 Firewall mit den für Kubernetes erforderlichen Ports (hcloud_firewall.cluster)
  • 1 SSH-Schlüssel (hcloud_ssh_key.kubeone)
  • 1 Zuordnungsgruppe zur Verteilung der Server auf die Hosts

Wenn alles korrekt aussieht, klicke auf:

terraform apply

Typ ja wenn Sie dazu aufgefordert werden. Terraform erstellt alle Ressourcen in etwa 1–2 Minuten.

Exportiere die Infrastrukturdaten für KubeOne:

terraform output -json > tf.json

Überprüfen Sie, ob die Ausgabe Ihre Infrastruktur enthält:

cat tf.json | jq '.kubeone_api.value.endpoint'

Erwartetes Ergebnis:

{
  "host": "203.0.113.100",
  "port": 6443
}

Der Host ist die öffentliche IP-Adresse des Hetzner-Load-Balancers, der vor Ihren API-Servern steht.

Schritt 5: Erstellen Sie das KubeOneCluster-Manifest

Erstellen kubeone.yaml mit der Hetzner-spezifischen Konfiguration:

apiVersion: kubeone.k8c.io/v1beta2
kind: KubeOneCluster
name: production

versions:
  kubernetes: "v1.30.2"

cloudProvider:
  hetzner: {}
  external: true

containerRuntime:
  containerd: {}

clusterNetwork:
  cni:
    canal: {}

features:
  nodeLocalDNS:
    deploy: true

Die wichtigen Hetzner-spezifischen Einstellungen:

cloudProvider.hetzner: {} weist KubeOne an, die Hetzner Cloud-Integrationen zu konfigurieren. Dazu gehört der Hetzner Cloud Controller Manager (CCM), der Ereignisse im Lebenszyklus der Knoten verwaltet und Kubernetes Metadaten über die zugrunde liegende Infrastruktur bereitstellt.

cloudProvider.external: true stellt den Cloud Controller Manager als externe Komponente (out-of-tree) bereit. Dies ist der empfohlene Ansatz für alle Cloud-Anbieter in modernen Kubernetes-Umgebungen. Der externe CCM läuft als Deployment im Cluster und ist nicht in das Kubelet integriert.

clusterNetwork.cni.canal: {} nutzt Canal (Calico + Flannel) als CNI-Plugin. Dies ist die Standardeinstellung von KubeOne und funktioniert bei Hetzner einwandfrei. Canal stellt ein VXLAN-Overlay-Netzwerk für die Kommunikation zwischen Pods bereit, während Calico für die Durchsetzung der Netzwerkrichtlinien zuständig ist.

features.nodeLocalDNS setzt auf jedem Knoten einen DNS-Cache ein, um die Latenz und die Auslastung von CoreDNS zu verringern.

Tipp: Sie können auch Cilium anstelle von Canal als CNI verwenden. Ersetzen Sie das cni Abschnitt mit cilium: {}. Cilium bietet erweiterte Netzwerkfunktionen wie eBPF-basierten Lastausgleich und Netzwerküberwachung, setzt jedoch den Linux-Kernel 5.10 oder höher auf Ihren Knoten voraus (was die Ubuntu-Images von Hetzner bieten).

Schritt 6: Bereitstellung des Kubernetes-Clusters

Sobald Ihre Infrastruktur läuft und das Manifest bereit ist, richten Sie Kubernetes ein:

kubeone apply --manifest kubeone.yaml --tfjson tf.json

KubeOne zeigt Ihnen eine Übersicht über die geplanten Schritte an. Überprüfen Sie die geplanten Aktionen – folgende Punkte sollten aufgeführt sein:

  • 3 Control-Plane-Hosts mit ihren Hetzner-IP-Adressen
  • Kubernetes-Version v1.30.2
  • Kanal CNI
  • Hetzner – externer Cloud-Anbieter

Bestätigen Sie, um fortzufahren. KubeOne führt dann Folgendes aus:

  1. Stellt über SSH eine Verbindung zu jedem Knoten der Steuerungsebene her
  2. Installiert die Pakete „containerd“ und „Kubernetes“
  3. Den ersten Knoten der Steuerungsebene mit kubeadm initialisieren
  4. Verbindet den zweiten und dritten Knoten zu einem HA-Cluster
  5. Konfiguriert etcd auf allen drei Knoten
  6. Stellt den Hetzner Cloud Controller Manager bereit
  7. Stellt Canal CNI, den Metrics-Server und das lokale DNS bereit
  8. Stellt eine Maschinensteuerung für die Verwaltung der Worker-Knoten bereit
  9. Erstellt MachineDeployments für Worker-Knoten (basierend auf Anzahl der Replikate bei der ersten Maschinenbereitstellung)

Der Vorgang dauert 5 bis 8 Minuten. Bitte unterbrechen Sie ihn nicht.

Erwartete Ausgabe (letzte Zeilen):

INFO[00:05:32] Kubeconfig wird heruntergeladen...
INFO[00:05:32] MachineDeployments sicherstellen...
INFO[00:05:33] Fertig!

Schritt 7: Auf den Cluster zugreifen und ihn überprüfen

KubeOne erstellt eine kubeconfig-Datei in Ihrem aktuellen Verzeichnis:

export KUBECONFIG=$(pwd)/production-kubeconfig

Überprüfen Sie, ob alle Knoten der Steuerungsebene bereit sind:

kubectl get nodes

Erwartetes Ergebnis:

NAME                   STATUS   ROLLEN           ALTER   VERSION
production-cp-1        Bereit    Steuerungsebene   6m    v1.30.2
production-cp-2        Bereit    Steuerungsebene   5m    v1.30.2
production-cp-3        Bereit    Steuerungsebene   5m    v1.30.2

Worker-Knoten werden vom Machine-Controller asynchron bereitgestellt. Sie sind innerhalb von 2–3 Minuten verfügbar:

kubectl get nodes --watch

Sobald die Arbeiter erscheinen:

NAME                   STATUS   ROLES           AGE   VERSION
production-cp-1        Ready    control-plane   8m    v1.30.2
production-cp-2        Ready    control-plane   7m    v1.30.2
production-cp-3        Ready    control-plane   7m    v1.30.2
production-worker-1    Ready    <none>          2m    v1.30.2
production-worker-2    Ready    <none>          2m    v1.30.2

Überprüfen Sie, ob alle System-Pods ausgeführt werden:

kubectl get pods -A

Du solltest Pods für den API-Server, den Controller-Manager, den Scheduler, etcd, CoreDNS, Canal, das lokale DNS des Knotens, den Machine-Controller und den Hetzner-Cloud-Controller-Manager sehen – alle in Laufen Zustand.

Überprüfen Sie den Hetzner Cloud Controller Manager

Das CCM verwaltet Knoten-Metadaten und Lebenszyklusereignisse. Überprüfen Sie, ob es läuft:

kubectl get pods -n kube-system -l app=hcloud-cloud-controller-manager

Erwartetes Ergebnis:

NAME                                              BEREIT   STATUS    NEUSTARTE   ALTER
hcloud-cloud-controller-manager-xxxxxxxxxx-xxxxx  1/1     Läuft   0          6m

Überprüfen Sie, ob die Knoten Hetzner-spezifische Bezeichnungen haben:

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.node\.kubernetes\.io/instance-type}{"\n"}{end}'

Hier sollte der Hetzner-Servertyp angezeigt werden (z. B. cpx21) für jeden Knoten, um sicherzustellen, dass das CCM die Metadaten der Knoten korrekt meldet.

Schritt 8: Eine Test-Workload bereitstellen

Überprüfen Sie, ob der Cluster voll funktionsfähig ist, indem Sie Nginx bereitstellen:

kubectl create deployment nginx--image=nginx:latest--replicas=4
kubectl get pods -o wide

Die Pods sollten auf Ihre Worker-Knoten verteilt werden. Überprüfen Sie die Netzwerkverbindung zwischen den Pods:

kubectl exec -it $(kubectl get pods -l app=nginx -o jsonpath='{.items[0].metadata.name}') -- curl -s -o /dev/null -w "%{http_code}" http://$(kubectl get pods -l app=nginx -o jsonpath='{.items[1].status.podIP}')

A 200 Die Antwort bestätigt, dass das Overlay-Netzwerk zwischen den Knoten ordnungsgemäß funktioniert.

Die Testumgebung bereinigen:

kubectl delete deployment nginx

Schritt 9: Skalierung der Worker-Knoten

Einer der Vorteile von KubeOne bei Hetzner besteht darin, dass die Skalierung der Worker-Knoten über den Machine-Controller vollständig automatisiert ist. Sie müssen keine Server manuell bereitstellen.

Bestehende Mitarbeiter skalieren

Um die Anzahl der Worker zu erhöhen, bearbeiten Sie die Datei „MachineDeployment“:

kubectl -n kube-system get machinedeployments
kubectl -n kube-system scale machinedeployment production-worker--replicas=4

Die Maschinensteuerung richtet neue Hetzner-Server automatisch ein, installiert Kubernetes und fügt sie dem Cluster hinzu. Neue Knoten sind innerhalb von 2–3 Minuten verfügbar.

Einen weiteren Mitarbeiterpool hinzufügen

Um Worker mit unterschiedlichen Servertypen hinzuzufügen (z. B. für rechenintensive Workloads), erstellen Sie ein neues „MachineDeployment“. Sehen Sie sich zunächst das vorhandene an, um es als Vorlage zu verwenden:

kubectl -n kube-system get machinedeployment production-worker -o yaml > worker-pool.yaml

Bearbeiten worker-pool.yaml: Ändern Sie den Namen und passen Sie den Servertyp an cloudProviderSpecund aktualisieren Sie die Replikanzahl. Wenden Sie das neue MachineDeployment an:

kubectl apply -f worker-pool.yaml

Schritt 10: Die Kostenaufschlüsselung verstehen

Bei der Standardkonfiguration (3x cpx21-Steuerungsebene, 2x cpx31-Worker, 1x lb11-Lastverteiler) belaufen sich Ihre geschätzten monatlichen Kosten auf:

RessourceTypAnzahlUngefähre StückkostenInsgesamt
Steuerungsebenecpx213~5 EUR~15 EUR
Arbeitnehmercpx312~10 EUR~20 EUR
Lastenausgleichlb111~6 EUR~6 EUR
Privates Netzwerk1Kostenlos0 EUR
Insgesamtca. 41 EUR/Monat

Hinweis: Die Preise sind Richtwerte und variieren je nach Rechenzentrum. Die aktuellen Preise finden Sie in der Hetzner Cloud-Preisliste. Der Datenverkehr innerhalb des privaten Netzwerks ist kostenlos. Der ausgehende öffentliche Datenverkehr ist bei den meisten Servertypen bis zu 20 TB/Monat inbegriffen.

Tipps zur Kostenoptimierung

  • Verwenden Sie für Control-Plane-Knoten die CX-Serie anstelle der CPX-Serie, wenn Sie keine AMD EPYC-Prozessoren benötigen. Die CX-Serie (Intel) ist etwas günstiger.
  • Beginnen Sie mit zwei Arbeitern und erweitern Sie die Kapazität nach Bedarf. Dank der Maschinensteuerung ist die Skalierung mit einem einzigen Befehl erledigt.
  • Verwenden Sie Hetzner-Volumes für storage dauerhaften storage größere Servertypen für Speicherplatz bereitzustellen.
  • Richten Sie die automatische Skalierung mit dem Kubernetes Cluster Autoscaler und dem Cloud-Anbieter Hetzner ein, um die Anzahl der Worker je nach Bedarf anzupassen.

Fehlerbehebung

Terraform schlägt mit der Fehlermeldung „Unauthorized“ fehl

Das API-Token fehlt oder ist ungültig. Überprüfen Sie, ob es festgelegt ist:

echo $HCLOUD_TOKEN

Wenn die Variable leer ist, exportiere sie erneut. Wenn sie gesetzt ist, Terraform aber dennoch fehlschlägt, generiere ein neues Token in der Hetzner Cloud Console – das alte wurde möglicherweise widerrufen.

Worker-Knoten werden nicht angezeigt

Wenn die Knoten der Steuerungsebene bereit sind, aber nach 5 Minuten noch keine Worker-Knoten erscheinen:

  1. Status der Maschinenbereitstellung prüfen:
kubectl -n kube-system get-machinedeployments
kubectl -n kube-system get machines
  1. Überprüfen Sie die Protokolle der Maschinensteuerung:
kubectl -n kube-system logs -l app=machine-controller-f

Häufige Ursachen: die HCLOUD_TOKEN Das Secret fehlt im Cluster, das Token verfügt nicht über Schreibrechte oder das Hetzner-API-Ratenlimit wurde erreicht.

  1. Überprüfen Sie, ob das Cloud-init-Geheimnis vorhanden ist:
kubectl -n kube-system get secrets | grep cloud-init

Knoten, die im Status „NotReady“ hängen geblieben sind

Wenn Knoten erscheinen, aber in Nicht bereit Zustand:

  1. Überprüfen Sie die Kubelet-Protokolle auf dem betroffenen Knoten:
ssh root@<node-ip> journalctl -u kubelet -f
  1. Überprüfen Sie, ob die Canal-Pods auf allen Knoten laufen:
kubectl get pods -n kube-system -l k8s-app=canal-o wide

Falls Canal-Pods vorhanden sind CrashLoopBackOffMöglicherweise ist das private Netzwerk nicht korrekt konfiguriert. Überprüfen Sie in der Hetzner Cloud Console, ob das private Netzwerk von Hetzner vorhanden ist und alle Server damit verbunden sind.

API-Server nicht erreichbar

Falls kubectl nach der Bereitstellung keine Verbindung herstellen kann:

  1. Überprüfen Sie in der Hetzner Cloud Console, ob der Load Balancer ordnungsgemäß funktioniert. Alle drei Control-Plane-Ziele sollten den Status „healthy“ anzeigen.
  2. Stellen Sie sicher, dass Port 6443 nicht durch eine lokale Firewall oder das Unternehmensnetzwerk blockiert wird.
  3. Überprüfen Sie, ob die kubeconfig auf die richtige IP-Adresse des Load Balancers verweist:
grep server production-kubeconfig

Nächste Schritte

Ihr Hetzner Cloud-Cluster ist nun in Betrieb und bereit für Workloads. Hier sind einige Möglichkeiten, wie Sie nun vorgehen können:

Zusammenfassung

Sie haben mithilfe von KubeOne und Terraform einen hochverfügbaren Kubernetes-Cluster auf der Hetzner Cloud bereitgestellt. Der Cluster umfasst drei Control-Plane-Knoten mit verteiltem etcd, zwei von machine-controller verwaltete Worker-Knoten sowie einen Hetzner-Load-Balancer, der den API-Server frontendet. Der Hetzner Cloud Controller Manager stellt Kubernetes Funktionen zur Verwaltung des Knotenlebenszyklus sowie Infrastruktur-Metadaten bereit. Die gesamte Konfiguration kostet etwa 41 EUR pro Monat und kann mit einem einzigen Befehl aktualisiert, skaliert oder repariert werden. kubeone apply Befehl.