Erster Cluster
Eine detaillierte Erläuterung der Konfigurationsdatei cluster.lok8s.yaml.
Voraussetzungen
- lok8s CLI installiert
- Ein Hetzner Cloud-Konto mit einem API-Token
- Ein SSH-Schlüsselpaar (Ed25519 empfohlen)
- Eine Domain, die dir gehört: API-Endpunkt und Zertifikatsnamen leiten sich daraus ab (als
spec.cluster.domain;example.comunten ist ein Platzhalter)
Vollständige Konfigurationsreferenz
Vollständige cluster.lok8s.yaml anzeigen
# clusters/example.com/cluster.lok8s.yaml
apiVersion: cluster.lok8s.dev/v1beta1
kind: KubeOne
metadata:
name: my-cluster
spec:
kubernetes:
version: "v1.35.5"
cluster:
# PFLICHT: eine Domain, die dir gehört; für Ingress und Zertifikate
domain: example.com
# Standard-Namespace für Workloads
namespace: default
provider:
name: hetzner
# Die Maschinen, in Hetzners eigenen Begriffen. Jeder `server`-Eintrag wird
# zu einem `hcloud server create`; seine Schlüssel sind hcloud-Flags. Lege
# denselben Inhalt in eine eigene Datei und zeige mit `configRef: hetzner.json`
# darauf, wenn du eine kürzere Spec bevorzugst.
config:
cluster_name: my-cluster
sshUser: root
sshPrivateKey: ~/.ssh/id_ed25519
sshPublicKey: ~/.ssh/id_ed25519.pub
ssh-key:
- name: my-cluster
public-key-from-file: ~/.ssh/id_ed25519.pub
network:
- name: my-cluster
# Bereich des privaten Netzwerks
ip-range: 10.0.0.0/16
"#subnets":
- network-zone: eu-central
type: cloud
ip-range: 10.0.0.0/24
server:
# 3 Control Planes für HA; 1 reicht für Dev
- name: cp-1
type: cx33
image: ubuntu-24.04
# fsn1, nbg1 oder hel1
location: fsn1
ssh-key: [0]
network: 0
label: lok8s.dev/cluster=my-cluster,lok8s.dev/role=control-plane
- name: cp-2
type: cx33
image: ubuntu-24.04
location: fsn1
ssh-key: [0]
network: 0
label: lok8s.dev/cluster=my-cluster,lok8s.dev/role=control-plane
- name: cp-3
type: cx33
image: ubuntu-24.04
location: fsn1
ssh-key: [0]
network: 0
label: lok8s.dev/cluster=my-cluster,lok8s.dev/role=control-plane
- name: worker-1
type: cpx31
image: ubuntu-24.04
location: fsn1
ssh-key: [0]
network: 0
label: lok8s.dev/cluster=my-cluster,lok8s.dev/role=worker
- name: worker-2
type: cpx31
image: ubuntu-24.04
location: fsn1
ssh-key: [0]
network: 0
label: lok8s.dev/cluster=my-cluster,lok8s.dev/role=worker
# Cluster-Infra-Addons, in Reihenfolge angewendet
bootstrap:
# CNI (Standard, wenn weggelassen)
- cilium
# Hetzner cloud-controller-manager
- ccm
- cert-manager
- monitoring
kubehz:
# self (du betreibst alles) | hosted (kubehz betreibt die Control Plane)
# | shared (ein Space auf einer geteilten Control Plane, kind: Kubehz)
hosting: self
# none | registered | managed (Supporter+)
access: registered
# cronjob (schreibgeschützter Heartbeat) | operator (Managed-Stufe, Live-Ansicht)
agent: cronjob
apiUrl: https://api.kubehz.cloudWichtige Abschnitte
spec.kubernetes
Legt die Kubernetes-Version fest. kubehz bietet eine kuratierte Liste an, jede Version auf einen Patch-Release gepinnt: heute v1.34.8 und v1.35.5 (die Voreinstellung). Eine Version wird zurückgezogen, sobald Upstream ihre Minor-Version nicht mehr patcht.
spec.provider
Wer die Maschinen stellt. name: hetzner wählt Hetzner Cloud, den einzigen implementierten Provider. config (oder configRef, ein Pfad zu einer JSON- oder YAML-Datei neben der Spec) ist der Provider-Deskriptor: der SSH-Zugang, den lok8s nutzt (sshUser, sshPrivateKey, sshPublicKey), und je eine Liste pro Hetzner-Ressource (ssh-key, network, server sowie optional volume und load-balancer). Jeder Eintrag wird zu einem hcloud <resource> create, und seine Schlüssel sind die Flags dieses Befehls. ssh-key: [0] und network: 0 an einem Server verweisen per Index auf Einträge dieser Listen.
Das Label lok8s.dev/role entscheidet, was ein Server wird: control-plane oder worker. Drei Control Planes geben dir HA; eine reicht für die Entwicklung. type ist ein Hetzner-Servertyp, location das Rechenzentrum.
Bare Metal. Ein Hetzner Dedicated Server kommt als #cloud.root-Eintrag in denselben Deskriptor (ein Robot-Server, den lok8s neu installiert und aufnimmt). Die Form steht in der lok8s-Provider-Referenz.
Veraltete Form. Ältere Specs trugen spec.ssh, spec.controlPlane und spec.workers. lok8s liest sie weiterhin als Fallback, in neuen Specs sollten sie aber nicht mehr vorkommen: SSH-Zugang und Node-Topologie gehören dem Provider-Deskriptor.
spec.bootstrap
Eine geordnete Liste von Cluster-Infra-Addons (CNI, CCM, cert-manager, Monitoring, …), die beim Provisionieren angewendet werden, bevor Workloads landen. Jeder Eintrag wird angewendet und abgewartet, bevor der nächste folgt. Blanke Namen lösen zu lok8s-Framework-Addons auf; ./pfad-Einträge zeigen auf deine eigenen Kustomize-Verzeichnisse. Wenn weggelassen, ist der Standard cilium: Jeder Cluster braucht ein CNI. Die vollständige Liste steht im lok8s-Addons-Guide.
spec.kubehz
Optionale Integration der kubehz-Plattform. hosting sagt, wer die Control Plane betreibt: self (du, auf deinem eigenen Konto), hosted (kubehz, siehe Gehostet) oder shared (ein Space auf einer Control Plane, die kubehz zwischen Kunden teilt; dieser Wert braucht kind: Kubehz). access sagt, was kubehz sieht: none, registered (schreibgeschützter Zustand) oder managed (ergänzt die Verwaltungsfunktionen: Healing-Richtlinien, Kapazitäts-Überwachung, Verwaltung des gewünschten Zustands; erfordert ein Supporter-Abo oder höher). Das Ausführen ist Pull-basiert: Der clusterinterne Agent holt den gewünschten Zustand von der Plattform ab und wendet ihn mit den eigenen Zugangsdaten deines Clusters an; kubehz hält niemals eingehenden Zugriff.
Die übrigen Schlüssel sind optional:
| Schlüssel | Bedeutung |
|---|---|
agent | Welcher clusterinterne Agent den Heartbeat besitzt: cronjob (der schreibgeschützte Standard) oder operator (die Live-Ansicht der Managed-Stufe). |
apiUrl | Die kubehz-API, nur HTTPS. Pflicht, sobald access nicht none ist, sowie für hosted und shared. |
connectHcloudToken | true übergibt der Plattform bei der Registrierung deinen HCLOUD_TOKEN, ausschließlich über HTTPS, damit ein gehosteter Cluster Worker-Pools bereitstellen kann. Standardmäßig aus. |
upgrades | channel: none / patch / minor (wie weit die Plattform ungefragt aktualisieren darf, Standard patch) und defer: window / immediate. |
maintenanceWindow | Wann plattformgesteuerte Arbeiten laufen dürfen: daysOfWeek, startTime, durationMinutes, timezone und exclusions (Daten oder Zeiträume, die alles einfrieren). |
space | Nur bei hosting: shared: der slug des Space, sein Anzeige-name und die nodes, für die beim Provisionieren Join-Tickets ausgestellt werden. |
Siehe Wie es funktioniert für das vollständige Modell und die Vertrauensgrenze sowie Registrierung, um die Sichtbarkeit zu aktivieren.
Datei speichern
lo hält unter clusters/ einen Ordner pro Cluster, benannt nach der Domain, und liest cluster.lok8s.yaml von dort. Lege den Ordner an, speichere die Datei und markiere die Domain dann als aktiv:
mkdir -p clusters/example.com
# füge die obige Referenz in clusters/example.com/cluster.lok8s.yaml ein
lo use example.comlo use schreibt die aktive Domain nach clusters/.active; --domain <domain> oder DOMAIN_NAME überschreiben sie für einen einzelnen Befehl.
Bearbeite dies vor dem Provisionieren. Die Referenz liefert Platzhalter, keine Standardwerte:
| Feld | Platzhalter | Was es sein muss |
|---|---|---|
metadata.name | my-cluster | der Name deines Clusters |
spec.cluster.domain und der Ordner | example.com | eine Domain, die dir gehört (wird für den API-Endpunkt verwendet) |
die SSH-Pfade in provider.config | ~/.ssh/id_ed25519[.pub] | der echte Pfad deines Schlüssels, nur falls er nicht den Ed25519-Standardnamen trägt |
lok8s deinen Hetzner-Token geben
lo provision erzeugt echte, kostenpflichtige Infrastruktur in deinem Hetzner-Konto und authentifiziert sich mit dem API-Token aus den Voraussetzungen. Exportiere ihn in derselben Shell, aus der du gleich provisionierst. Er wird aus der Umgebung gelesen, nie aus der Konfigurationsdatei, und landet so nie in git:
export HCLOUD_TOKEN="<dein-token>"Cluster bereitstellen
Führe dies aus deinem Projektverzeichnis aus, mit aktiver Domain:
lo provisionDie Bereitstellung dauert typischerweise 10–15 Minuten. Die kubeconfig wird als .kubeconfig/my-cluster.yaml im Projekt abgelegt, benannt nach metadata.name. Deine ~/.kube/config wird nicht angefasst.
Die Referenzkonfiguration oben fordert bei Hetzner fünf Server an (3 für die Control Plane und 2 Worker), die stündlich zu Hetzners veröffentlichten Preisen für diese Servertypen abgerechnet werden. Nichts davon ist endgültig: lo destroy entfernt jederzeit jeden Server, den lok8s angelegt hat.
Überprüfen
kubectl zeigt weiterhin auf den zuvor genutzten Kontext; wähle den neuen Cluster also explizit aus, sonst antwortet get nodes für deinen vorherigen:
export KUBECONFIG=.kubeconfig/my-cluster.yaml
kubectl get nodes
# (AGE trimmed — STATUS is what to check)
# NAME STATUS ROLES VERSION
# cp-1 Ready control-plane v1.35.5
# cp-2 Ready control-plane v1.35.5
# cp-3 Ready control-plane v1.35.5
# worker-1 Ready <none> v1.35.5
# worker-2 Ready <none> v1.35.5
kubectl get pods -A
# Listet NUR Pods, die noch nicht bereit sind. Auf einem gesunden Cluster: nichts.
kubectl get pods -A --field-selector=status.phase!=Running,status.phase!=Succeeded
# No resources foundJeder Node sollte Ready melden, und die Spalte VERSION sollte zur oben konfigurierten Kubernetes-Version passen.
kubectl get pods -A listet alle System-Pods, viel zum Durchsehen. Der zweite Befehl dreht das um: Er zeigt nur, was nicht Running oder Completed erreicht hat. No resources found ist die gewünschte Antwort. Gib CNI und Cloud-Controller direkt nach dem Provisionieren eine Minute, bevor du dort Gelistetes als Fehler wertest.
Nächste Schritte
- Dashboard-Einrichtung: deinen Cluster überwachen
- Registrierung: mit dem kubehz-Dashboard verbinden
- KubeOne-Leitfaden: fortgeschrittene KubeOne-Konfiguration
Doku-Status
| Aspekt | Detail |
|---|---|
| Zustand | aktiv |
| Zuletzt geprüft | 2026-09-05 |