Das Prinzip
OKD (OpenShift Kubernetes Distribution) 4 ist der Upstream von OpenShift Container Platform – gleiche Operatoren, Web-Console, Routes, BuildConfigs, ImageStreams. Es laeuft auf Fedora CoreOS. Fuer eine hochverfuegbare Control-Plane braucht es 3 Nodes mit etcd. „Kompakt“ heisst: diese 3 Nodes sind schedulebar und tragen auch deine Workloads – separate Worker sind optional. Ein Load Balancer buendelt API (6443), Machine-Config (22623) und Ingress (80/443).
steuert nur
+ Bootstrap (nur bei Install)
+ Bastion (nur bei Install)
ssh)
01 Realitaets-Check – bevor du anfaengst
etcd & Festplatten-Latenz: Die OpenShift-Control-Plane reagiert extrem
empfindlich auf fsync-Latenz. Auf Hetzners shared cx-Servern
scheitert die Installation regelmaessig an etcd-Timeouts. Nimm ccx-Server
(dedizierte vCPU) – oder besser Hetzner Robot / Dedicated (AX).
Groesse: kompakt = 3 Nodes, je min. 4 vCPU / 16 GB
(offiziell fuer schedulebare Control-Plane eher 8 vCPU / 32 GB). Empfehlung:
3× CCX33. Lab-Minimum: 3× CCX23 – wird eng.
Dazu voruebergehend 1 Bootstrap-Node und 1 kleine Bastion.
Kosten: 3× CCX33 ≈ 415 €/Monat
+ LoadBalancer ~6 € + Traffic. Das ist kein Spar-Setup. Wenn du nur
oc ueben willst → nimm die OKD-Single-Node-Anleitung (1 Node CPX42, ~0,10 €/h).
Zeit: ~45 Minuten am Stueck, nicht sinnvoll unterbrechbar.
Kein Red-Hat-Pull-Secret noetig – OKD nimmt ein Fake-Secret.
Wenn das alles ok ist: Hetzner-Konto anlegen, ein Projekt erstellen, unter Security → API Tokens einen Token mit Read & Write erzeugen und sofort kopieren.
02 Voraussetzung: Server-Basis
Konto, API-Token, hcloud CLI, SSH-Key – einmalig, in einer eigenen Anleitung.
Server-Basis
durcharbeiten. Zusätzlich fuer OKD: winget install RedHat.OpenShift-Client
(oc). Den eigentlichen Installer (openshift-install, nur Linux) laedst
du in Schritt 6 auf die Bastion.
03 SSH-Key: der .pub-Inhalt
Der SSH-Key liegt schon bei Hetzner (Server-Basis). OKD braucht zusätzlich den
Inhalt des öffentlichen Schlüssels – er kommt in die
install-config (fuer den core-User auf FCOS).
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub # Inhalt merken (fuer Schritt 6)
04 Privates Netz & Load Balancer
Die Nodes reden ueber ein privates Netz miteinander (etcd, API). Ein Hetzner Load Balancer ist der einzige oeffentliche Einstieg und verteilt auf die Control-Plane-Nodes.
hcloud network create --name okd-net --ip-range 10.128.0.0/16
hcloud network add-subnet okd-net --network-zone eu-central --type cloud --ip-range 10.128.0.0/24
hcloud load-balancer create --name okd-lb --type lb11 --location nbg1 --network-zone eu-central
hcloud load-balancer attach-to-network okd-lb --network okd-net
# Dienste: API, Machine-Config, Ingress
hcloud load-balancer add-service okd-lb --protocol tcp --listen-port 6443 --destination-port 6443
hcloud load-balancer add-service okd-lb --protocol tcp --listen-port 22623 --destination-port 22623
hcloud load-balancer add-service okd-lb --protocol tcp --listen-port 80 --destination-port 80
hcloud load-balancer add-service okd-lb --protocol tcp --listen-port 443 --destination-port 443
hcloud load-balancer describe okd-lb -o 'format={{.PublicNet.IPv4.IP}}' # -> oben ins Feld "LoadBalancer-IP"
Vier hcloud-Objekte in einem Block – Netz, Subnetz, Load Balancer, Dienste:
| Schalter | gehoert zu | bewirkt |
|---|---|---|
hcloud network create --name okd-net |
zuerst | Ein privates Netz ist ein eigenstaendiges Objekt, das mehrere Server verbindet, ohne dass ihr Verkehr das oeffentliche Internet beruehrt. Server darin erreichen einander ueber Adressen wie 10.128.0.5. Das kostet bei Hetzner nichts extra und ist der Grund, warum die Nodes spaeter ohne oeffentliche IP auskommen. |
hcloud load-balancer create --name okd-lb |
danach | Der Load Balancer verteilt eingehende Verbindungen auf mehrere Server und ist hier der einzige oeffentliche Einstieg in den Cluster. Er wird angelegt, ans Netz gehaengt, bekommt Dienste (Port-Weiterleitungen) – und erst in Schritt 8 die eigentlichen Ziele, weil die Nodes jetzt noch nicht existieren. |
--ip-range 10.128.0.0/16 |
network create | Der Adressraum des gesamten privaten Netzes. Er muss gross genug fuer alle spaeteren Subnetze sein und darf sich nicht mit den Cluster-internen Bereichen von OpenShift ueberschneiden – sonst laufen Pod- und Node-Adressen ineinander und der SDN-Verkehr bricht auf schwer auffindbare Weise ab. |
--ip-range 10.128.0.0/24 |
network add-subnet | Der Ausschnitt, aus dem die Nodes ihre privaten Adressen bekommen – ein /24 reicht fuer 254 Server. Das Netz allein traegt keine Adressen; ohne Subnetz bekommt kein Server eine private IP (Internet Protocol). |
--network-zone eu-central |
Subnetz, LB | Die Netzwerkzone, nicht der Standort. Sie umfasst mehrere Rechenzentren (nbg1, fsn1, hel1 …). Load Balancer und Subnetz muessen in derselben Zone liegen wie die Server – sonst schlaegt attach-to-network fehl. |
--type lb11 |
load-balancer create | Die kleinste Bauform: 5 Dienste, 25 Targets, 20 TB Traffic. Genau die vier Dienste unten passen hinein – ein fuenfter waere das Limit. Traffic ist bei Hetzner-LBs inklusive. |
attach-to-network okd-lb --network okd-net |
load-balancer | Stellt den LB mit einem Bein ins private Netz. Erst danach kann er die Nodes ueber ihre privaten Adressen erreichen; ohne das muesste jeder Node eine oeffentliche IP behalten. |
--protocol tcp |
add-service | Reines Durchreichen auf Schicht 4. Wichtig fuer 6443 und 22623, weil dort TLS bis zum Cluster durchlaufen muss – ein HTTP-Modus wuerde die Verbindung aufbrechen und das Zertifikat passt dann nicht mehr. Auch 80 und 443 bleiben deshalb bewusst TCP; die Terminierung macht der OpenShift-Router. |
--listen-port 22623 |
add-service | Der Machine-Config-Server. Nur die Nodes selbst brauchen ihn, und nur waehrend der Installation – aber ohne ihn bootet kein Node fertig. Er liefert unauthentifiziert Ignition-Konfiguration aus und gehoert deshalb hinter die Firewall, nicht ins offene Netz. |
-o 'format={{.PublicNet.IPv4.IP}}' |
describe | Gibt statt der ganzen Beschreibung nur ein Feld aus – Go-Template-Syntax, dieselbe wie bei docker inspect. Praktisch, weil die IP gleich in ein Skript oder in das Platzhalter-Feld oben wandert. Die einfachen Anfuehrungszeichen sind Pflicht, sonst frisst PowerShell die geschweiften Klammern. |
Die LB-Targets (die Nodes) haengen wir in Schritt 8 an, sobald sie existieren.
lb11 reicht fuer ein Lab. Traffic ist bei Hetzner-LBs inklusive.
05 DNS ohne eigenen Server: nip.io
OpenShift verlangt, dass api.<cluster>.<domain> und
*.apps.<cluster>.<domain> aufloesen. nip.io loest
jede Subdomain von <ip>.nip.io auf genau diese IP (Internet Protocol) auf –
also zeigt automatisch alles auf den Load Balancer.
base-domain = <lb-ip>.nip.io
API-URL = https://api.lab.<lb-ip>.nip.io:6443
Apps = *.apps.lab.<lb-ip>.nip.io
Zeigt die API-URL und die App-Hosts auf nip.io, ist der Cluster bei
einem nip.io-Ausfall komplett nicht erreichbar. Fuer alles ausser einem kurzen Lab besser
sslip.io (gleiche Wildcard-Idee, andere Betreiber – die anderen Guides hier
nutzen es) oder gleich die echte Wildcard bei Cloudflare (nächster Absatz).
Fuer echten Betrieb spaeter eine richtige Domain nehmen – z. B.
seb4u.com, das schon als Full-Zone bei Cloudflare liegt (siehe
Domain zu Cloudflare umziehen). Dort in der bestehenden Zone
api.okd als A-Record + *.apps.okd als Wildcard-A-Record auf die
LB-IP setzen. Beide Records „DNS only“ (grau) – ein
proxied Wildcard braucht Cloudflare Enterprise, und der OKD-Router macht TLS (Transport Layer Security) selbst.
06 Bastion + install-config.yaml
Eine kleine Wegwerf-VM erzeugt die Ignition-Dateien und stellt sie den Nodes bereit.
hcloud server create --name okd-bastion --type cpx22 --image ubuntu-24.04 `
--ssh-key laptop --network okd-net
$bastion = (hcloud server ip okd-bastion).Trim()
ssh root@$bastion
OKD=$(curl -s https://api.github.com/repos/okd-project/okd/releases/latest | grep -oP '"tag_name": "\K[^"]+')
cd /root
curl -L "https://github.com/okd-project/okd/releases/download/$OKD/openshift-install-linux-$OKD.tar.gz" | tar xz
curl -L "https://github.com/okd-project/okd/releases/download/$OKD/openshift-client-linux-$OKD.tar.gz" | tar xz
mv oc kubectl openshift-install /usr/local/bin/
mkdir -p /root/okd && cd /root/okd
apiVersion: v1
baseDomain: <lb-ip>.nip.io
metadata:
name: lab
controlPlane:
name: master
replicas: 3
compute:
- name: worker
replicas: 0
networking:
networkType: OVNKubernetes
machineNetwork:
- cidr: 10.128.0.0/24
clusterNetwork:
- cidr: 10.132.0.0/14
hostPrefix: 23
serviceNetwork:
- 172.30.0.0/16
platform:
none: {}
pullSecret: '{"auths":{"fake":{"auth":"aWQ6cGFzcwo="}}}'
sshKey: 'ssh-ed25519 AAAA... (Inhalt deiner id_ed25519.pub)'
07 Manifeste & Ignition erzeugen
Aus der install-config werden die Boot-Konfigurationen. Vorher sichern –
openshift-install verbraucht die Datei.
cd /root/okd
cp install-config.yaml install-config.yaml.bak
# Control-Plane schedulebar machen (kompakter Cluster):
openshift-install create manifests
sed -i 's/mastersSchedulable: false/mastersSchedulable: true/' manifests/cluster-scheduler-02-config.yml
openshift-install create ignition-configs
python3 -m http.server 8080 & # serviert bootstrap.ign / master.ign
# FCOS-Image-URL passend zum Installer:
openshift-install coreos print-stream-json | grep -oP 'https://[^"]+qemu[^"]+x86_64[^"]+\.xz' | head -1
bootstrap.ign, master.ign, worker.ign und
auth/kubeconfig + auth/kubeadmin-password liegen in
/root/okd/. Der HTTP-Server auf :8080 laeuft.
08 Nodes erstellen & FCOS schreiben
1 Bootstrap + 3 Master. Jede VM (virtuelle Maschine) startet im Rescue-Modus,
coreos-installer schreibt Fedora CoreOS mit der passenden Ignition auf die
Platte, dann Neustart ins fertige System.
# Beispiel: bootstrap (dann master-0/1/2 mit --type ccx33 und passender .ign)
hcloud server create --name okd-bootstrap --type cpx42 --image ubuntu-24.04 `
--ssh-key laptop --network okd-net --start-after-create=false
hcloud server enable-rescue okd-bootstrap --ssh-key laptop
hcloud server poweron okd-bootstrap
$n = (hcloud server ip okd-bootstrap).Trim()
ssh root@<node>)FCOS_URL="https://.../fedora-coreos-...-metal.x86_64.raw.xz" # aus Schritt 7
BASTION_PRIV=10.128.0.2 # private IP der Bastion
podman run --privileged --rm --pull=always -v /dev:/dev -v /run/udev:/run/udev \
quay.io/coreos/coreos-installer:release install /dev/sda \
--image-url "$FCOS_URL" --insecure \
--ignition-url "http://$BASTION_PRIV:8080/bootstrap.ign" --insecure-ignition
reboot
hcloud load-balancer add-target okd-lb --server okd-bootstrap --use-private-ip
# spaeter fuer master-0/1/2 dasselbe; Bootstrap nach Schritt 9 wieder entfernen
Gleiche Schritte mit --type ccx33 und
--ignition-url http://$BASTION_PRIV:8080/master.ign. Alle drei an den LB haengen.
09 Bootstrap abwarten
cd /root/okd
openshift-install wait-for bootstrap-complete --log-level=info
# ~15-25 Min. Wenn "It is now safe to remove the bootstrap resources":
hcloud load-balancer remove-target okd-lb --server okd-bootstrap
hcloud server delete okd-bootstrap
10 Installation abschliessen & oc login
openshift-install wait-for install-complete
# druckt am Ende Console-URL und das kubeadmin-Passwort
cat /root/okd/auth/kubeadmin-password
scp root@$bastion:/root/okd/auth/kubeconfig $env:USERPROFILE\.kube\okd-hetzner.yaml
$env:KUBECONFIG = "$env:USERPROFILE\.kube\okd-hetzner.yaml"
oc get nodes
oc get clusteroperators # alles "Available=True"?
# Bastion wird nicht mehr gebraucht:
hcloud server delete okd-bastion
https://console-openshift-console.apps.lab.<lb-ip>.nip.io
– Login kubeadmin + das Passwort von oben. Port 443 am LB ist schon offen.
11 Projekt, Route, Storage
oc new-project demo
oc new-app --image=docker.io/library/nginx --name=web
oc expose deployment/web --port=80
oc expose service/web # Route auf web-demo.apps.lab.<lb-ip>.nip.io
oc get route
Ein frischer platform: none-Cluster hat keine Default-StorageClass.
Fuer echte PVs (PersistentVolumes) den LVM (Logical Volume Manager) Storage Operator (LVMS) aus dem OperatorHub
installieren (nutzt freien Platz auf den Node-Platten) – oder fuers Erste mit
emptyDir arbeiten. ODF/Ceph ist fuer 3 Nodes zu schwer.
+ Worker hinzufuegen
Mehr Kapazitaet, ohne die Control-Plane zu belasten.
# neue VM, Rescue, coreos-installer mit worker.ign (von der Bastion – oder .ign vorher sichern!)
hcloud server create --name okd-worker-1 --type ccx33 --image ubuntu-24.04 `
--ssh-key laptop --network okd-net --start-after-create=false
# ... Rescue + coreos-installer --ignition-url .../worker.ign + reboot
oc get csr -o name | ForEach-Object { oc adm certificate approve ($_ -replace 'certificatesigningrequest.certificates.k8s.io/','') }
oc get nodes # der neue Worker erscheint nach 1-2 Min als Ready
Die worker.ign zeigt auf den Machine-Config-Server (:22623 ueber den LB) –
die muss also erreichbar bleiben. worker.ign aus Schritt 7 vorher wegsichern,
da die Bastion geloescht wurde.
+ Kosten: abreissen & neu aufbauen
Preise sind Richtwerte. Hetzner hat 2026 zweimal erhöht (zuletzt 15. Juni: CX/CAX +30–40 %, CPX/CCX über 100 %). Aktuelle Server-Preise, alle Nebenposten, ein Rechner und Beispielrechnungen stehen zentral in Kosten & Budget.
Einen laufenden Cluster kann man nicht „pausieren“ – die 3 Server kosten durchgehend. Realistischer Spar-Weg: komplett loeschen, bei Bedarf in ~45 Min neu installieren (Schritte 6–10). Das Skript raeumt alles ab.
| Posten | €/Std | €/Tag | €/Monat (Dauerbetrieb) |
|---|---|---|---|
3× Control-Plane CCX33 (dediziert, 32 GB) | ~0,57 | ~13,7 | ~415 |
Bootstrap CPX42 – nur waehrend Installation (~45 Min) | ~0,095 | einmalig ~0,07 | – |
Bastion CPX22 – nur waehrend Installation | ~0,027 | einmalig ~0,03 | – |
Load Balancer lb11 | ~0,010 | ~0,25 | ~7,5 |
| Primary-IPs (3× IPv4) | ~0,0021 | ~0,05 | ~1,50 |
| Privates Netzwerk | gratis | gratis | 0 |
| Cluster im Dauerbetrieb | ~0,58 | ~14 | ~425 |
Richtwerte 2026 (CCX33 grob, aktuell: hcloud server-type describe CCX33).
.\scripts\cluster.ps1 down loescht Server, LB und Netz – alle Uhren stoppen sofort.
Ein vergessenes Wochenende (Fr–Mo) sind ~40 €. Deshalb ist das naechtliche
Auto-Teardown hier der wichtigste Schutz.
.\scripts\cluster.ps1 status # was laeuft, ~Kosten
.\scripts\cluster.ps1 down # alle okd-* Server + LB + Netz loeschen
#Requires -Version 5.1
param([ValidateSet('down','status')][string]$Action = 'status')
# Kein globales 'Stop': hcloud und ssh schreiben Hinweise ("Server not found",
# Fortschritt) nach stderr - PowerShell 5.1 wertet das unter 'Stop' als Abbruch.
$ErrorActionPreference = 'Continue'
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$Prefix = 'okd-'
# Stundensaetze (EUR): aus scripts/rates.psd1 - eine Quelle wie cloud.ps1 / snapshot.ps1.
$RatesFile = Join-Path $PSScriptRoot 'rates.psd1'
$Rate = if (Test-Path $RatesFile) { Import-PowerShellDataFile $RatesFile }
else { @{ cpx22 = 0.0267; cpx42 = 0.0952; cpx52 = 0.1377 # Fallback (Stand nach 15.06.2026)
ccx13 = 0.0589; ccx23 = 0.1178; ccx33 = 0.1897 } }
function Cluster-Servers {
hcloud server list -o json | ConvertFrom-Json | Where-Object { $_.name -like "$Prefix*" }
}
function Show-Status {
$srv = Cluster-Servers
if (-not $srv) { Write-Host 'AUS - keine okd-* Server.' -ForegroundColor Green; return }
$sum = 0.0
foreach ($s in $srv) {
$age = (Get-Date).ToUniversalTime() - ([datetime]$s.created).ToUniversalTime()
$r = $Rate[$s.server_type.name]; if ($r) { $sum += $age.TotalHours * $r }
Write-Host (" {0,-16} {1,-8} seit {2:0.0} h" -f $s.name, $s.server_type.name, $age.TotalHours)
}
$lb = hcloud load-balancer list -o json | ConvertFrom-Json | Where-Object { $_.name -like "$Prefix*" }
Write-Host ("`n{0} Server + {1} LB ~{2:N2} EUR bisher (nur Server)" -f $srv.Count, $lb.Count, $sum) -ForegroundColor Yellow
}
function Invoke-Down {
Cluster-Servers | ForEach-Object { Write-Host "delete $($_.name)"; hcloud server delete $_.name | Out-Null }
hcloud load-balancer list -o json | ConvertFrom-Json | Where-Object { $_.name -like "$Prefix*" } |
ForEach-Object { hcloud load-balancer delete $_.name | Out-Null }
hcloud network list -o json | ConvertFrom-Json | Where-Object { $_.name -like "$Prefix*" } |
ForEach-Object { hcloud network delete $_.name | Out-Null }
[Environment]::SetEnvironmentVariable('KUBECONFIG', $null, 'User')
Write-Host "`nAlles abgerissen. Kosten gestoppt." -ForegroundColor Green
}
switch ($Action) { 'down' { Invoke-Down } 'status' { Show-Status } }
Ein Abriss-Skript ist die gefährlichste Sorte Werkzeug. Diese Stellen entscheiden darueber, ob es nur den Cluster erwischt:
| Konstrukt | Stelle | bewirkt |
|---|---|---|
#Requires -Version 5.1 |
Zeile 1 | Keine Kommentarzeile, sondern eine Zusicherung an PowerShell: das Skript weigert sich zu starten, wenn eine aeltere Fassung laeuft. 5.1 ist die, die bei Windows 10 und 11 dabei ist – das Skript kommt also ohne Nachinstallation aus, muss dafuer aber auf die Bequemlichkeiten von PowerShell 7 verzichten (kein ??, kein &&, kein Ternaeroperator). |
switch ($Action) { 'down' {…} 'status' {…} } |
letzte Zeile | Die einzige Zeile, die etwas ausloest – alles darueber sind nur Definitionen. PowerShell laeuft die Datei von oben nach unten durch und legt dabei die Funktionen an; aufgerufen wird erst hier. Deshalb darf Invoke-Down weiter oben stehen als der Aufruf. |
$Prefix = 'okd-'Where-Object { $_.name -like "$Prefix*" } |
überall | Die einzige Sicherung des Skripts. Es löscht nichts, was nicht mit okd- beginnt – andere Server im selben Hetzner-Projekt bleiben unangetastet. -like ist der Vergleich mit Platzhaltern (*), nicht mit regulären Ausdrücken; dafür hiesse der Operator -match und ein Punkt träfe jedes Zeichen. Wer den Cluster anders benennt, muss diese Zeile mitändern – sonst findet down nichts und meldet trotzdem Erfolg. |
[ValidateSet('down','status')]$Action = 'status' |
param | Zwei bewusste Entscheidungen: ValidateSet lässt PowerShell die Eingabe prüfen, bevor eine Zeile läuft, und der Vorgabewert ist der harmlose. Ein Aufruf ohne Argument zeigt an, statt zu löschen. |
$ErrorActionPreference = 'Continue' |
Kopf | Bewusst nicht 'Stop': hcloud und ssh schreiben auch harmlose Hinweise nach stderr, und PowerShell 5.1 wertet das unter Stop als abbrechenden Fehler – das Skript bräche dann mitten im Abriss ab und liesse die Hälfte stehen. |
Import-PowerShellDataFile |
Tarife | Liest eine .psd1 als reine Daten ein – im Gegensatz zu Invoke-Expression oder einem gesourcten Skript wird darin kein Code ausgeführt. Das if (Test-Path …) … else … hält das Skript einzeln lauffähig, auch wenn die Datei fehlt. |
hcloud … -o json | ConvertFrom-Json |
Abfragen | Macht aus der Textausgabe echte Objekte, sodass $_.name und $_.server_type.name funktionieren. Der zuverlässige Weg – die Tabellenausgabe von hcloud zu zerlegen bricht, sobald sich eine Spaltenbreite ändert. |
([datetime]$s.created).ToUniversalTime() |
Laufzeit | Hetzner liefert den Zeitstempel als Text; die eckigen Klammern sind eine Typumwandlung. Beide Seiten der Subtraktion werden auf UTC gebracht – ohne das ist die berechnete Laufzeit im Sommer um zwei Stunden daneben, und die Kostenschätzung mit ihr. |
("{0,-16} {1,-8} seit {2:0.0} h" -f …) |
Ausgabe | Der Format-Operator. {0,-16} heisst „Argument 0, 16 Zeichen breit, linksbündig“ (positiv wäre rechtsbündig), {2:0.0} rundet auf eine Nachkommastelle. So stehen die Spalten untereinander, ohne von Hand Leerzeichen zu zählen. |
Server → Load Balancer → Netz |
Invoke-Down | Keine Stilfrage, sondern Pflicht: Hetzner verweigert das Löschen eines Netzes, solange noch etwas darin hängt. In umgekehrter Reihenfolge scheitert der letzte Schritt still – und ein Netz kostet zwar nichts, blockiert aber beim nächsten Aufbau seinen eigenen Namen. |
| Out-Null |
Invoke-Down | Verwirft die Bestätigungen von hcloud, damit die eigenen Write-Host-Zeilen die Ausgabe bestimmen. Sichtbar bleibt so, was gelöscht wird – bei einem Abriss-Skript der wichtigere Teil. |
SetEnvironmentVariable('KUBECONFIG', $null, 'User') |
Invoke-Down | Entfernt die dauerhaft gespeicherte Variable aus der Benutzerumgebung – $null löscht sie, eine leere Zeichenkette liesse sie mit leerem Wert stehen. Ohne das zeigt kubectl in der nächsten Sitzung auf einen Cluster, den es nicht mehr gibt, und hängt in Zeitüberschreitungen. Gilt erst in einer neu geöffneten Konsole, nicht in der laufenden. |
Diese Datei liegt als scripts/cluster.ps1 bei (im Repo zusaetzlich mit
Ausfuehrungszeit-Ausgabe wie die anderen Skripte) – nicht aus dem Browser abtippen.
Wie bei den anderen Anleitungen: Windows-Aufgabenplanung ruft scripts\cluster.ps1 down
taeglich um 03:00. Bei einem 150-€-Cluster ist das der wichtigste Schutz – ein
vergessenes Wochenende = ~15 €.
.\scripts\install-autodown.ps1 -For cluster # legt die Aufgabe "OKD Auto-Teardown" an
+ Absicherung
- Nodes ohne oeffentlichen Zugang: nach der Installation die Public-IPs der
Master entfernen (
hcloud server …) – Egress dann ueber ein NAT-Gateway oder Hetzners--without-ipv4+ IPv6 (Internet Protocol Version 6). Zugang nur noch ueber den LB und die Bastion. - LB-Firewall: 6443 und die Console (443) auf deine IP beschraenken, solange nichts oeffentlich sein muss (Hetzner-LB unterstuetzt keine Source-IP-Filter – dafuer eine Cloud-Firewall vor die Nodes, oder haproxy statt LB).
- kubeadmin abschaffen: nach dem ersten echten OAuth-IdP (htpasswd, GitHub,
…) den
kubeadmin-Secret loeschen. - Updates:
oc adm upgrade– OKD zieht neue Releases aus dem eigenen Update-Graphen. - etcd-Backup:
oc debug node/…→/usr/local/bin/cluster-backup.shregelmaessig laufen lassen.
Grundausstattung-Checkliste – 2FA aufs Hetzner-Konto, Tailscale fuer den Admin-Zugang, etcd-Backup ausser Haus, Monitoring, und der Kostenblick (bei ~425 €/Monat).
+ Kill-Switch
Anders als bei den Ein-Node-Anleitungen gibt es kein Snapshot-und-zurueck: ein Cluster mit geaenderten Node-IPs ist kaputt. Der Kill-Switch hier ist deshalb komplett abreissen (Skript in Schritt 13) plus naechtliches Auto-Teardown. Neu aufbauen = Schritte 6–10, ~45 Minuten.
3× CCX33 ≈ 0,57 €/Stunde zusammen ≈
14 €/Tag. Ein Cluster, den du an 6 Abenden im Monat je 3 h nutzt, kostet
≈ 10 € – wenn das Auto-Teardown zuverlaessig laeuft. Vergisst du ihn
einen Monat: ~425 €.
Ein Self-Destruct-Timer wie in den anderen Anleitungen ist hier heikel (er wuerde einzelne
Nodes killen und den Cluster zerlegen, ohne den LB/das Netz aufzuraeumen). Besser: das
Auto-Teardown auf dem Laptop und zusaetzlich ein Cron auf einem separaten
Mini-Server (anderes Hetzner-Projekt), der einmal am Tag hcloud … delete
fuer alle okd-* Ressourcen ausfuehrt.
+ Andere Wege zu echtem OpenShift
| Weg | Art | Bemerkung |
|---|---|---|
| Hetzner Robot / Dedicated (AX41–AX102) | self-host | Der richtige Hetzner-Weg fuer OKD: echte NVMe, ISO-Mount, KVM-Konsole. etcd-Latenz kein Problem. ~40–120 €/Monat je Node + Setup. |
| Assisted Installer (OKD) | self-host | Web-UI erzeugt eine Discovery-ISO, Nodes booten davon, UI (User Interface) installiert. Braucht ISO-Boot (Robot) oder coreos-installer wie hier. |
| Single Node OpenShift (SNO) | self-host | 1 Node, voller Funktionsumfang, ab ~16 GB RAM (Random Access Memory) – aber keine HA (Hochverfügbarkeit). Fuer „echter Betrieb“ nur bedingt. |
| bare-metal auf anderen Clouds | self-host | Vultr Bare Metal, OVH, Latitude.sh, Equinix – ueberall wo du FCOS (Fedora CoreOS) booten und einen TCP-LB stellen kannst. |
Managed OpenShift – jemand betreibt die Control-Plane
| Dienst | Wo | ab ca. | Bemerkung |
|---|---|---|---|
| ROSA (Red Hat OpenShift Service on AWS) | AWS (Amazon Web Services) | ~0,03 $/h + Worker | Red Hat OpenShift on AWS. Voll gemanagt, Konsole, Operatoren, Support. |
| ARO (Azure Red Hat OpenShift) | Azure | ~0,17 $/h + Worker | Azure Red Hat OpenShift. Aehnlich ROSA. |
| OpenShift Dedicated | AWS / GCP (Google Cloud Platform) | ~1000 $/Mon | Von Red Hat auf deren Konten gehostet. |
| Developer Sandbox | Red Hat | gratis | Geteiltes Projekt, ~30 Tage erneuerbar. Perfekt zum oc-Ueben ohne Cluster – eigene Anleitung. |
Reihenfolge der Anleitungen nach Aufwand: Podman/Docker → k3s → OKD Single-Node → dieser OKD-Cluster. Fang klein an.