PerformanceBlog

by Anton Pütz | Dipl. Informatiker (Univ.) »

Ich habe einen self-hosted Kubernetes-Cluster von Grund auf gebaut – das steckt wirklich dahinter

Und dann habe ich einen Rust-Microservice darauf deployt, um mein Garagentor per iOS zu öffnen.

Wer über Kubernetes spricht, meint meistens EKS, GKE oder AKS. Managed Cluster, bei denen die Control Plane das Problem von jemand anderem ist. Das ist völlig okay – es ist pragmatisch. Aber es gibt eine andere Kategorie von Herausforderung, über die es sich zu reden lohnt: Das ganze Ding selbst bauen, auf Bare Metal, mit Networking auf Production-Niveau, weil man die volle Kontrolle über den Stack will.

Genau das habe ich getan. Und um zu beweisen, dass der Cluster auch wirklich zu etwas nütze ist, habe ich eine Rust-basierte MQTT-Bridge darauf deployt, mit der ich mein Garagentor über einen iOS-Shortcut öffnen kann.

Lass mich dich durch den Prozess führen, denn trivial ist das Ganze nicht.

Der Cluster

Der Cluster läuft in einem privaten Netzwerk, der API-Server ist unter 10.0.0.21:6443 erreichbar. Kein Cloud-Provider. Keine verwaltete Control Plane. Keine bequemen Wrapper.

Der Admin-Zugriff erfolgt über gegenseitiges TLS (mTLS) mit X.509-Client-Zertifikaten – den Standard-Credentials für kubernetes-admin, die von kubeadm generiert werden. Der Clustername lautet schlicht kubernetes, was schon zeigt: Hier wurde traditionell gearbeitet – mit kubeadm, direkt auf dem System, von Grund auf.

Digitale Souveränität: Warum die Hardware entscheidend ist

Bevor wir in die technischen Details des CNI eintauchen, müssen wir über das „Warum“ sprechen. In einer Welt, in der die „Cloud“ oft nur ein schickes Wort für „der Computer von jemand anderem“ ist, ist der Betrieb auf eigener Hardware der ultimative Schritt zu echter digitaler Souveränität.

  • Datensouveränität: Auf Bare Metal verlassen keine Daten das Haus, ohne dass ich es explizit erlaube. Es gibt keine Blackbox-Provider, keine unklaren Zugriffsberechtigungen durch Drittstaaten (Stichwort: Cloud Act) und kein Scannen von Workloads durch den Infrastruktur-Anbieter.

  • Technologische Freiheit: Wer proprietäre Cloud-Dienste nutzt, baut sich oft einen „Golden Cage“. Ein Wechsel wird durch Vendor Lock-in fast unmöglich. Mit diesem Cluster nutze ich ausschließlich Open-Source-Standards. Der gesamte Stack ist portabel.

  • Operative Autonomie: Ich entscheide über Update-Zyklen, Sicherheits-Patches und die genaue Konfiguration des Kernels. Ich bin kein bloßer Nutzer mehr – ich bin der Eigentümer.

Souveränität bedeutet jedoch auch Verantwortung: Man ist nicht nur der König seines Clusters, sondern auch sein Hausmeister.

Der schwierige Teil: Networking (CNI)

Hier scheitern die meisten Self-Hosting-Versuche. Das Container Network Interface (CNI) ist die Schicht, die die Pod-zu-Pod-Kommunikation über Nodes hinweg ermöglicht. Wenn hier etwas schiefgeht, können Pods nicht miteinander sprechen, Services brechen weg, DNS schlägt fehl und alles fühlt sich wie ein einziges Rätselraten an.

Ich habe mich für Calico entschieden, installiert über den Tigera Operator (v1.40.3).

Warum das eine bewusste Entscheidung war:

Flannel ist das CNI für Einsteiger – ein einfaches VXLAN-Overlay, das überall funktioniert und null Konfiguration erfordert. Aber es bringt Overhead mit sich: Jedes Paket zwischen Pods auf verschiedenen Nodes wird gekapselt, was Latenz verursacht und CPU-Zyklen frisst.

Calico ohne Kapselung ist anders. Es nutzt BGP, um Pod-CIDRs zwischen den Nodes auf der Routing-Ebene bekannt zu machen. Pakete reisen nativ – kein Tunneling, kein Overhead. Aber das setzt voraus, dass dein zugrunde liegendes Netzwerk diese Präfixe auch routen kann. Man muss also Layer-3-Networking verstehen, damit das funktioniert.

Meine Konfiguration:

# IP Pool
cidr: 10.245.0.0/16
blockSize: 26       # 64 IPs pro Node
encapsulation: None # Natives Routing — kein VXLAN, kein IPIP
natOutgoing: Enabled

# BGP
asNumber: 64513
nodeToNodeMeshEnabled: true

Die /26 Blockgröße bedeutet, dass jeder Node ein Subnetz mit 64 Adressen aus dem 10.245.0.0/16 Pool erhält. Ein BGP Full-Mesh sorgt dafür, dass jeder Node direkt mit jedem anderen Node peert und Routen austauscht.

Die Edge: HAProxy als Dual-Stack L4 Proxy

Bevor der Traffic überhaupt den Cluster erreicht, trifft er auf den HAProxy, der auf dem Host läuft. Hier ist die vollständige Konfig:

Code-Snippet

frontend ipv6_http
    bind [::]:80 v4v6
    default_backend envoy_http

frontend ipv6_https
    bind [::]:443 v4v6
    default_backend envoy_https

backend envoy_http
    server envoy1 10.100.234.70:80 send-proxy-v2

backend envoy_https
    server envoy1 10.100.234.70:443 send-proxy-v2

Ein paar Details dazu:

  • Dual-Stack von Anfang an: Clients beider Protokolle (IPv4/IPv6) erhalten denselben Pfad.

  • L4 Passthrough: HAProxy leitet rohe TCP-Streams weiter. TLS wird erst downstream bei Envoy terminiert. Das hält das Setup simpel und extrem performant.

  • PROXY protocol v2: Damit Envoy die echte IP-Adresse des Clients sieht und nicht nur die des HAProxy.

DNS & Gateway API

CoreDNS läuft automatisch in kube-system. Jeder Service ist sofort via DNS-Name erreichbar. Zusätzlich nutze ich die moderne Kubernetes Gateway API über den Tigera Operator. Sie ist der Nachfolger von „Ingress“ und bietet deutlich mehr Kontrolle über das Routing und eine sauberere Trennung der Verantwortlichkeiten.

Die Anwendung: Eine Rust MQTT Bridge

Die eigentliche Anwendung: Mein Garagentor per iOS-Shortcut steuern.

Die Architektur: iOS Shortcut → HTTPS → Envoy (API Key) → Rust Service → MQTT/TLS → Garagentor.

  • Warum Rust? Extrem sicher, minimale Ressourcen (32–128 MB RAM) und blitzschnell.

  • Sicherheit: API-Key an der Edge (Envoy), mTLS zum MQTT-Broker, Secrets-Management in Kubernetes. Der gesamte Round-Trip dauert weniger als 200 ms.

Fazit: Warum das für Production wichtig ist

Ein solches Setup ist kein Spielzeug. Es ist die Basis für Teams, die:

  1. On-Premise laufen müssen (Compliance/Latenz).

  2. Volle Kontrolle über den Netzwerk-Stack brauchen.

  3. Unabhängig von Cloud-Providern bleiben wollen.

Wenn du den Cluster selbst baust, verstehst du jede Schicht. Du weißt, warum BGP Full-Mesh funktioniert und wie man Netzwerkfehler auf Calico-Ebene debuggt.

Was ich anbiete

Ich unterstütze Produkt-Teams dabei, genau diese Art von Infrastruktur aufzubauen – stabil, sicher und wartbar, ohne dass man ein riesiges Platform-Team benötigt.

Lass uns über dein Projekt sprechen.

Optimierung der Finanzverwaltung: Wie ich mit Beancount und LLMs Amazon-Bestellungen effizient analysiere

Seit einigen Jahren nutze ich Beancount, um unsere Familienfinanzen im Blick zu behalten. Beancount ist ein doppelte Buchführungssystem, das auch ...

Sicherer WLAN Betrieb im Haus – Small Office

Mit dem verstärkten Einsatz von Homeoffice sind die IT-Sicherheits – Anforderungen an das eigene Netz größer als davor. Mich stört ...
office_setup

Mein Setup nach einem Jahr Homeoffice

In meinen letzten Artikel hatte ich mein damaliges Setup vorgestellt. Ich habe danach sehr viel ausprobiert und bin mittlerweile mit ...

Creating a Wireguard VPN Server on a Raspberry Pi 4

Update August 9th. 2021: The current Raspi OS versions include Wireguard as a package- so there is no need to ...