Self Hosted Kubernetes ohne DevOps Team (Vortrag Rack&Stack)

Sebastian Kurfürst22.04.2026

Dieser Artikel basiert auf meinem Vortrag bei der Rack&Stack Nürnberg im April 2026. Den hier beschriebenen Kubernetes Blueprint gibt es als Open-Source-Projekt auf GitHub.

Die Prämisse: Langweilig ist gut

Bevor wir in die Technik einsteigen, ein Wort zur Philosophie. Monzo, die britische Neobank, hat vor einigen Jahren stolz ihre Microservices-Architektur präsentiert - inklusive eines Netzwerkdiagramms mit 1.500 Services:

SCR 20260422 Qppz

Die Farben zeigten die verantwortlichen Teams. Der Aufschrei war groß: Wie kann man so Software betreiben und dabei noch ruhig schlafen?

Das Problem bei solchen Architekturen: Die Komplexität liegt nicht in den einzelnen Komponenten, sondern in den Lücken dazwischen - in der Netzwerkkommunikation, in der Orchestrierung, in den Abhängigkeiten. Und genau das ist meistens noch viel schwieriger zu debuggen als größere einzelne Dienste.

Mein Ziel im Betrieb von Software is daher:

Langweilig ist gut. Damit wird es vorhersehbar und günstig im Betrieb.

20260412 RackAndStack Kubernetes Selfhosted.009

Warum Kubernetes? Und warum selbst gehostet?

Docker-Container packen eine Anwendung mit allen Abhängigkeiten in eine wiederverwendbare Einheit. Dasselbe Image läuft in der lokalen Entwicklung, in der Testumgebung und in Produktion. Das schafft Dev-Prod-Parity und hilft, viele Fehler früh zu erkennen.

Up-Scaling vs. Down-Scaling

Wenn man nach "Container in Produktion" sucht, findet man fast ausschließlich Informationen zu Up-Scaling: Wie verteile ich meine Anwendung auf 5, 50 oder 500 Server? Das ist das Szenario, das Google, Amazon und Co. durch die Gegend treiben, weil sie es selbst brauchen.

Für uns im Mittelstand ist aber ein anderer Aspekt mindestens genauso relevant: Down-Scaling -- also eine hohe Packungsdichte auf wenigen Servern. Wir betreiben auf unserem Kubernetes-Cluster mit drei physischen Servern rund 200 Container. Das sind interne Anwendungen, Single Sign-On, Logging, Monitoring und auch diverse Produktivinstanzen unserer Kunden:

20260412 RackAndStack Kubernetes Selfhosted.011

Kubernetes als Quasi-Standard

Kubernetes ist de facto der Standard für Container-Orchestrierung. Es ist Open Source, wurde initial von Google gestartet und wird heute von tausenden Contributors in vielen Teilprojekten weiterentwickelt.

Die Power von Kubernetes kommt von seiner Erweiterbarkeit: eigene Module ("Operators") oben drauf bauen, das System erweitern. Der Zoo an Modulen in der CNCF Landscape ist mittlerweile unübersichtlich.

20260412 RackAndStack Kubernetes Selfhosted.014

"Für Kubernetes braucht man ein Operations-Team" -- Nope.

Diesen Mythos möchte ich entkräften. Wir sind 35 Leute, wir haben Kubernetes seit sieben Jahren im Einsatz und die aktuelle Plattform seit fünf Jahren. Niemand bei uns ist ausschließlich für Kubernetes zuständig. Etwa 4-5 Personen im Team kennen sich gut damit aus und maintainen es nebenbei.

Natürlich: Man darf und muss sich Inhouse-Expertise aufbauen. Es ist nicht kostenlos. Aber man sollte keine Angst davor haben.

Unsere Ziele und Trade-Offs

Wenn man Kubernetes im KMU-Kontext einsetzt, ist es hilfteich, manche Dinge anders zu denken als im klassischen, elastischen Cloud-Setup:

  • Langfristige Skalierbarkeit -- ohne extreme Elastizität. Wir wollen einen vierten oder fünften Server dazustellen können, aber nicht automatisiert um 3 Uhr nachts.
  • Stabilität und Updatefähigkeit. 9 von 10 Updates schaffen wir ohne jede Downtime unserer Workloads, und ohne Workload-Migration auf andere Server.
  • Flexibilität für viele verschiedene Workloads. Fast alle sprechen HTTP(S) in irgendeiner Form.
  • Komplexitätsreduktion. Es ist nicht unser Hauptjob, Kubernetes zu betreiben -- daher muss es so einfach wie möglich sein.
  • Geringe Wartungskosten. Durch Automatisierung und Dokumentation.
  • Einfache Nutzung (Self-Service). Der Rest des Teams soll nicht Kubernetes-Experte werden müssen, um eine Anwendung zu deployen.

Ein bewusster Trade-Off: Wir pinnen unsere Workloads auf bestimmte Server. Wir wissen damit, welche Anwendung auf welchem Server läuft und wo die Daten liegen. Das reduziert die Elastizität, bringt aber ein massiv einfaches Betriebsmodell.

Der Sandstorm Kubernetes Blueprint

Alles folgende ist als Open-Source-Projekt veröffentlicht:

github.com/sandstorm/KubernetesBlueprint

Ihr könnt das komplett auf eigenen Servern ausprobieren, Teile herausnehmen oder als Diskussionsgrundlage nutzen.

20260412 RackAndStack Kubernetes Selfhosted.020

Schritt 1: K3S als Basis

K3S ist eine Kubernetes-Distribution von Rancher (jetzt Teil von SUSE), die sich als Lösung für IoT und Edge-Computing vermarktet. Wir haben festgestellt: K3S läuft hervorragend im Datacenter. Nur weil etwas auch auf einem Raspberry Pi läuft, heißt das nicht, dass es nicht auch auf einem großen Server mit 200 GB RAM exzellent funktioniert.

Das Schöne an K3S:

  • Kubernetes in einer einzigen Binary. Runterladen, starten, fertig.
  • Update = Binary austauschen und neustarten. Einfaches Betriebsprinzip.
  • Updates im laufenden Betrieb ohne Downtime der Container möglich.
  • Die einzige echte Downtime (ca. 5 Minuten) haben wir bei Kernel-Updates, weil der Server dann wirklich neu booten muss.

K3S bringt bereits Standardmodule mit:

  • Traefik als Reverse Proxy (Ingress/Gateway)
  • Local Path Provisioner für persistente Daten - ein bestimmter Ordner auf dem Server enthält alle persistenten Daten. Einfach zu verstehen, einfach zu sichern.

Schritt 2: Server-Setup mit Ansible

Unser Basis-Setup besteht aus:

  1. Load Balancer (idealerweise von unserem Hoster)
  2. Internes Netzwerk
  3. ein oder mehrere Server

Wir demonstrieren den Setup basierend auf Hetzner Cloud, aber es funktioniert genauso auf eigenem Blech, in Proxmox oder bei jedem anderen Provider.

Das interne Netzwerk hinter dem Load Balancer ist wichtig - auch bei nur einer Instanz. Ohne Load Balancer macht man DNS-basiertes Failover, und das hat bekannte Probleme mit Propagierungszeiten. Der Load Balancer gibt Flexibilität im Incident-Fall.

Die Server-Provisionierung machen wir mit Ansible. Wir installieren K3S, ein paar Admin-Tools -- und zusätzlich MariaDB und PostgreSQL direkt auf dem Server (nicht in Kubernetes). Das ist wieder unsere Philosophie: Wir wollen wissen, wo die Daten liegen.

Das Schöne an Ansible und Kubernetes: Ich definiere den Zielzustand, nicht die Schritte. Das System konvergiert immer zu diesem Zielzustand -- auch wenn zwischendurch mal etwas schiefgeht.

Nach der Ausführung ist der Cluster leer und bereit:

20260412 RackAndStack Kubernetes Selfhosted.024

Schritt 3: Cilium als Netzwerkschicht

Vom K3S-Standard weichen wir bei der Netzwerkschicht ab und nutzen Cilium, welches Routing und Netzwerk auf eBPF-Basis bereitstellt. Das Hauptfeature für uns: Cilium Hubble - ein "Röntgenblick" in die Netzwerkverbindungen im Cluster.

Dies hilft für folgende Szenarien:

  • Visualisierung von Traffic-Flüssen im Cluster
  • sofort sehen, wenn eine Firewall-Regel Traffic blockt (rot markiert in der UI)
  • Debugging von Ost-West-Traffic zwischen Diensten

Ohne Cilium sehe ich oft nur "meine Verbindung geht nicht" - ohne zu wissen, ob es am Routing, an der Firewall oder an etwas anderem liegt. Cilium lässt sich übrigens auch im laufenden Betrieb updaten, ohne die Konnektivität im Cluster zu beeinträchtigen.

Die Hausbau-Analogie

An diesem Punkt haben wir:

  1. Grundstück gekauft = Server bereitgestellt
  2. Rohbau = Kubernetes (K3S) installiert
  3. Haus steht = Cilium + Netzwerk konfiguriert

Das entspricht ungefähr dem, was man bei einem Cloud-Provider als Managed Kubernetes bekommt sofern man hier keine Elastizität benötigt (EKS, GKE, AKS) -- allerdings für einen Bruchteil der Kosten (Faktor 5-10 günstiger).

Schritt 4: Innenausbau - SSL-Zertifikate & Co.

Den "Innenausbau" muss man bei jedem Kubernetes machen, auch bei Managed-Angeboten. Dazu gehören z.B. automatische SSL-Zertifikate via cert-manager und Let's Encrypt:

apiVersion: v1 kind: Namespace metadata: name: cert-manager --- apiVersion: helm.cattle.io/v1 kind: HelmChart metadata: name: cert-manager namespace: cert-manager spec: repo: https://charts.jetstack.io chart: cert-manager version: '1.19.2' set: "crds.enabled": "true" "crds.keep": "true"

Operators: Die eigene Platform as a Service

Kubernetes direkt zu nutzen bedeutet, für jede Anwendung viele Einzelteile zu konfigurieren: Ingress, Zertifikate, Services, Deployments, Persistent Volumes, Datenbanken... Unsere Entwickler sollen das nicht alles wissen müssen.

Unsere Standard-Anwendungen sind Web-Anwendungen mit einem HTTP-Port, auf dem diese Traffic entgegennehmen. Mehr nicht. Also haben wir das abstrahiert: Ein eigener Kubernetes Operator namens OneContainerOnePort, der aus einer minimalen Konfiguration automatisch alles Nötige erzeugt:

  • Ingress
  • TLS-Zertifikat (via Let's Encrypt)
  • Deployment
  • Persistent Volume (wenn nötig)
  • Redis (wenn nötig)

Was ist ein Operator?

Kubernetes funktioniert deklarativ: Ich beschreibe meinen Zielzustand in YAML, und ein Controller (der "Operator") sorgt permanent dafür, dass dieser Zustand hergestellt wird. Wenn etwas gelöscht wird, legt der Operator es automatisch neu an. Das ist die Basis für die hohe Resilienz von Kubernetes.

Mit dem Operator SDK kann man eigene Operators bauen. Dafür gibt es drei Wege:

20260412 RackAndStack Kubernetes Selfhosted.043

Der Ansible-Operator: Externe Systeme fernsteuern

Unser Database-Operator ist Ansible-basiert. Ein kurzes YAML reicht, um eine Datenbank für eine Anwendung bereitzustellen:

apiVersion: k8s.sandstorm.de/v1alpha1 kind: Database metadata: name: neos-db spec: databaseServer: postgres1

Was passiert im Hintergrund?

  1. Der Operator würfelt neue Zugangs-Credentials aus
  2. Er legt sie als Kubernetes Secret ab
  3. Er verbindet sich per Ansible zur externen Datenbank
  4. Er legt dort die Datenbank an

Das Mächtige daran: Ich kann über Kubernetes externe Systeme steuern - Datenbanken, DNS-Provider, Cloud-Ressourcen, Keycloak-Tenants - alles, wofür es ein Ansible-Modul gibt. Und ich bekomme zentrale Sichtbarkeit: Ein kubectl get databases --all-namespaces zeigt mir alle Datenbanken im gesamten System.

Dieses Pattern ist aus meiner Sicht ein absoluter Game Changer für Kubernetes in Brownfield-Umgebungen, weil es die Integration mit der externen Welt ermöglicht. Erstaunlicherweise wird wenig darüber gesprochen.

Der Helm-Operator: Standardisierung über Projekte hinweg

Der OneContainerOnePort-Operator ist Helm-basiert. Damit kann ich z.B. Excalidraw (ein webbasiertes Diagramm-Tool) folgendermaßen deployen:

apiVersion: k8s.sandstorm.de/v1alpha1 kind: OneContainerOnePort metadata: name: excalidraw spec: image: excalidraw/excalidraw:latest port: 80 hostNames: excalidraw.${BASE_DOMAIN}: [] ssl: true stagingCertificates: false

Der große Vorteil gegenüber losen Helm-Charts: Wenn wir am Operator etwas ändern und deployen, werden alle Systeme automatisch auf den neuesten Stand gebracht. Probleme fallen sofort auf - nicht erst ein halbes Jahr später, wenn ein Kunde sein Projekt wieder anfasst.

Praxisbeispiel: Neos CMS deployen

Ein etwas fortgeschritteneres Beispiel mit Datenbank, Redis und persistentem Storage:

apiVersion: k8s.sandstorm.de/v1alpha1 kind: OneContainerOnePort metadata: name: neos spec: # ... envFromConfigMaps: - neos-db envFromSecrets: - neos-db - neos-admin redis: transient volumes: - name: persistent mountPath: /app/Data/Persistent storage: 1Gi

Ein kubectl apply später läuft eine vollständige Neos-CMS-Instanz - mit SSL, Datenbank, Cache und persistentem Storage. Und wenn jemand versehentlich ein Gateway oder einen Service löscht? Der Operator stellt es automatisch wieder her. Solange niemand die OneContainerOnePort-Ressource selbst löscht, heilt sich alles von allein.

Das ist ein extrem schönes Modell, weil auch Teammitglieder mit wenig Kubernetes-Erfahrung sehr selbstständig arbeiten können, ohne Angst haben zu müssen, etwas kaputt zu machen.

Bonus: Permissions und Access Management mit Rancher

Wir betreiben nicht nur einen, sondern mehrere Kubernetes-Cluster. Innerhalb eines Clusters gibt es zwar gute Workload-Separierung, aber keine vollständige Garantie, dass eine "noisy" Workload andere nicht beeinträchtigt. Für verschiedene Abteilungen oder Vertrauenszonen können separate Cluster sinnvoll sein.

Für das zentrale Management nutzen wir den Open-Source Rancher Manager:

  • Zentraler Einstiegspunkt für alle Cluster
  • SSO-Anbindung via OpenID Connect (Keycloak, Entra ID, ...)
  • Zentrale Permissions und Audit-Logging -- wer darf was, und wer hat was gemacht?
  • Projekt-Konzept: Gruppen von Namespaces, auf die ich Rechte vergeben kann
  • Download der lokalen kubectl-Konfiguration über die Web-UI
20260412 RackAndStack Kubernetes Selfhosted.058

Zusammenfassung

K3S als leichtgewichtige, stabile Kubernetes-Distribution -- auch im Datacenter hervorragend

  • Cilium für Netzwerk-Transparenz und Debugging
  • Eigene Operators (Ansible- und Helm-basiert) für eine interne Platform as a Service
  • Bewusste Trade-Offs: Weniger Elastizität, mehr Stabilität und Einfachheit
  • Alles Open Source: github.com/sandstorm/KubernetesBlueprint

Der wichtigste Punkt: Kubernetes muss nicht kompliziert sein und es muss nicht immer elastisch sein. Für viele KMU-Workloads ist das "langweilige" Setup - vorhersehbar, günstig, stabil - genau das Richtige. Und wenn man später doch Elastizität braucht, kann man sie gezielt hinzufügen.

FAQs

"Wenn ich Daten auf eine Node pinne, mache ich den Kubernetes-Vorteil kaputt?" Das ist (für uns) ein gezielter Trade-Off zugunsten von Komplexitätsreduktion. Wir haben Backups und können manuell eine neue Instanz auf einem anderen Host erzeugen. Für unsere Workloads brauchen wir diese Elastizität fast nie.

"Warum K3S und nicht Talos oder RKE2?" Historisch gewachsen - als wir starteten, gab es RKE2 noch nicht und Talos auch nicht. Außerdem kennen wir Ubuntu-Server sehr gut, und das ermöglicht uns, Datenbanken co-located neben Kubernetes zu betreiben. Heute würde ich Talos durchaus in Betracht ziehen.

"Warum eigene Operators und nicht Kustomize mit Argo oder Flux?" Argo/Flux arbeiten Push-basiert (Git als Source of Truth wird in den Cluster gepusht). Wir arbeiten Pull-basiert: Unsere Projekte haben ein minimales YAML, das per kubectl apply in den Cluster geschoben wird. Der Operator im Cluster sorgt dann für den Zielzustand. Beides führt zum Ziel - wir bevorzugen aktuell den deklarativen, Pull-basierten Ansatz.

"Was ist mit Black Friday und horizontaler Skalierung?" Für große Konzerne unterstützen wir bei Planung und Betrieb von großen, elastischen Kubernetes-Cluster. Aber: Der Default sollte "nicht elastisch" sein. Elastizität bringt Dynamik und Komplexität, die man nicht will, wenn man stabilen Betrieb höher wichtet. Lieber mit dem einfachen Setup starten und bei Bedarf Elastizität gezielt dazuschalten.

Dieser Artikel basiert auf dem Vortrag "Self Hosted Kubernetes ohne DevOps Team" bei der Rack&Stack Nürnberg am 22. April 2026.

Bei Fragen oder Interesse an Workshops und Beratung: academy.sandstorm.de oder sk@sandstorm.de.