Zum Hauptinhalt springen

Private Cloud: Der Unterbau — Infrastrukturkomponenten im Detail

Im dritten Teil ging es um die handfeste Seite: Hardware, Stromkosten, die ehrlichen Grenzen. Heute schauen wir unter die Haube und unter die Applikationen — auf den Unterbau, der all das zusammenhält.


Warum zwei Posts statt einem? #

Wer eine private Cloud aufbaut, denkt zuerst an die Apps: Nextcloud für Dateien, Immich für Fotos, Vaultwarden für Passwörter. Das ist verständlich — am Ende des Tages sind es die Anwendungen, die man täglich benutzt. Aber bevor auch nur ein einziger Container läuft, muss ein stabiles Fundament stehen. Netzwerk, Storage, Zertifikate, Monitoring, GitOps-Workflows — all das ist unsichtbar, wenn es funktioniert, und sehr sichtbar, wenn es das nicht tut.

Deshalb teile ich den technischen Deep-Dive in zwei Teile auf: Dieser erste Teil widmet sich ausschließlich den Infrastrukturkomponenten, die den Cluster am Laufen halten. Der zweite Teil folgt dann mit den eigentlichen Applikationen und den Entscheidungen dahinter. So bleibt beides lesbar — und man kann gezielt nachschlagen, ohne sich durch das jeweils andere zu kämpfen.

Überblick des gesamten Infrastruktur-Stacks von Proxmox über Kubernetes bis zu den einzelnen Diensten
Überblick des gesamten Infrastruktur-Stacks von Proxmox über Kubernetes bis zu den einzelnen Diensten


Calico im eBPF-Datapath #

Kubernetes braucht ein sogenanntes CNI-Plugin (Container Network Interface), das die Kommunikation zwischen Pods regelt. Meine Wahl fiel auf Calico im eBPF-Datapath — nicht weil es das einfachste wäre, sondern weil es stabil, weit verbreitet und gut dokumentiert ist, und weil eBPF die Netzwerkebene auf ein Niveau hebt, das mit klassischem iptables-Routing nicht erreichbar ist.

Konkret heißt das: kube-proxy ist komplett ersetzt (kubeProxyReplacement: Strict), Service-Routing passiert direkt im Kernel über eBPF-Programme, und die alten iptables-Regeln werden aktiv aufgeräumt. Der Vorteil zeigt sich vor allem bei vielen Services und Pods — niedrigere Latenz, bessere Performance, und deutlich tiefere Observability, weil eBPF Einblick in den Netzwerk-Stack erlaubt, ohne den Datenpfad auszubremsen.

Die Trade-offs sind real: eBPF setzt einen aktuellen Kernel voraus, das Debugging ist anspruchsvoller als bei iptables-Regeln, die man notfalls mit iptables -L lesen kann, und nicht jedes Tooling im Kubernetes-Ökosystem geht sauber mit einem fehlenden kube-proxy um. Wer die Lernkurve nicht gehen will, ist mit dem Standard-Datapath besser bedient.

Beim Pod-Netzwerk fahre ich in Phase 1 bewusst mit VXLAN-Encapsulation, nicht mit BGP. Auf einem einzelnen Proxmox-Host mit vier VMs gibt es schlicht kein Routing-Problem, das BGP lösen müsste — alle Nodes hängen am gleichen virtuellen Switch. VXLAN funktioniert ohne Konfiguration der darunterliegenden Netzwerk-Infrastruktur und kostet bei dieser Größenordnung praktisch keine Performance. Sobald ein zweiter Proxmox-Host dazukommt und Pod-Traffic über physische Netzwerkgrenzen läuft, wird auf BGP umgestellt — dann zahlt sich echtes Layer-3-Routing aus, weil der Encapsulation-Overhead wegfällt.

Für ein Single-Host-Setup ist das alles technisch gesehen Overkill. Aber es ist die Architektur, die sich am besten skalieren lässt — und genau darum geht es in dieser Serie: Entscheidungen treffen, die heute sinnvoll sind und morgen nicht bereuen lassen.


Traefik als Ingress-Controller #

Traefik übernimmt die Rolle des Ingress-Controllers: Es sitzt vor dem Cluster, nimmt eingehende HTTP/HTTPS-Anfragen entgegen und leitet sie an den richtigen Service weiter. Im Gegensatz zu klassischen Reverse-Proxies wie nginx wird Traefik nicht über statische Konfigurationsdateien gefüttert, sondern liest seine Routing-Regeln direkt aus Kubernetes-Ressourcen — entweder über das Standard-Ingress-Objekt oder über die Traefik-eigene IngressRoute-CRD, die mehr Funktionen mitbringt.

Was mich überzeugt hat: das Middleware-Konzept für Authentifizierung, Rate-Limiting und Header-Manipulation, die übersichtliche Web-UI für einen schnellen Überblick über aktive Routen, und das saubere Zusammenspiel mit cert-manager. Wichtig dabei: cert-manager ist eine eigenständige Komponente — er beantragt und erneuert TLS-Zertifikate über Let’s Encrypt und legt sie als Kubernetes-Secrets ab. Traefik nutzt diese Secrets dann beim Terminieren von TLS. Welche Zertifikate ich beziehe, entscheide ich pro Ingress über den ClusterIssuer: letsencrypt-staging für Tests (höhere Rate-Limits, aber ungültige Zertifikate), letsencrypt-prod für den Produktivbetrieb. Das ist deklarativ, aber bewusst manuell — und genau das macht den Setup vorhersehbar.

Traefik ist hier nicht nur ein HTTP-Router, sondern der zentrale Eingangspunkt für den gesamten Cluster — und damit eine Komponente, bei der Stabilität über Experimentierfreude geht.


cert-manager — TLS ohne Handarbeit #

Zertifikate manuell verwalten war gestern. cert-manager integriert sich direkt in Kubernetes und stellt über Let’s Encrypt automatisch TLS-Zertifikate aus — und erneuert sie rechtzeitig, bevor sie ablaufen. Die Konfiguration läuft über ClusterIssuer- und Certificate-Ressourcen, die sich sauber in den GitOps-Workflow einbinden lassen.

Ein kleines Detail mit großer Wirkung: cert-manager läuft komplett im Hintergrund und macht sich nur dann bemerkbar, wenn etwas schiefläuft. Genau so soll eine Infrastrukturkomponente funktionieren.


Storage: Longhorn und csi-driver-nfs — zwei Tools, eine Aufgabe? #

Storage ist der Punkt, an dem viele Heimlabore ins Stocken geraten. Kubernetes unterscheidet zwischen ReadWriteOnce (RWO) und ReadWriteMany (RWX) Volumes — und nicht jede Lösung beherrscht beides.

Longhorn übernimmt bei mir die RWO-Volumes: persistente Datenspeicher, die von genau einem Pod gleichzeitig beschrieben werden — Datenbanken, Anwendungsdaten, Zustände. Longhorn repliziert diese Volumes über mehrere Nodes, was eine gewisse Ausfallsicherheit auch auf einem einzelnen physischen Host mit mehreren Worker-Nodes ermöglicht. Der integrierte Backup-Mechanismus nach S3 ist ein weiteres Plus, auf das ich in einem späteren Post noch genau eingehe.

Daneben läuft csi-driver-nfs, und das aus einem ganz konkreten Grund: Manche Workloads brauchen ein Volume, das von mehreren Pods gleichzeitig beschrieben werden kann — RWX. Longhorn unterstützt das nicht nativ, also kommt eine dedizierte NFS-VM ins Spiel, die über csi-driver-nfs als StorageClass eingebunden wird. Das Ergebnis: saubere Trennung der Zuständigkeiten, kein Workaround, keine Hacks.

Die Faustregel: RWO → Longhorn, RWX → NFS. Wer das einmal verstanden hat, kämpft nicht mehr mit “can only be used with access mode ReadWriteOnce”-Fehlern.


Flux CD und Ansible — GitOps als Prinzip #

Von allen Infrastrukturkomponenten in diesem Post ist Flux diejenige, die den Charakter des gesamten Clusters am stärksten prägt. Nicht weil Flux besonders viel Rechenleistung verbraucht oder im Alltag sichtbar wäre — sondern weil Flux bestimmt, wie Änderungen am Cluster überhaupt passieren dürfen. Das verdient einen eigenen, etwas ausführlicheren Abschnitt.

Was GitOps eigentlich bedeutet #

GitOps ist keine bestimmte Technologie, sondern ein Prinzip: Der gewünschte Zustand des Systems liegt als Code in einem Git-Repository, und eine Automatisierung sorgt dafür, dass der tatsächliche Zustand diesem Wunschzustand entspricht. Das Repository ist die einzige Quelle der Wahrheit — nicht das, was jemand mal eben mit kubectl apply eingespielt hat, nicht ein Klick in einer Web-UI, nicht ein Skript auf einem Laptop. Was nicht im Repo steht, existiert nicht.

Das klingt nach einer kleinen Umstellung, ist aber in der Praxis eine große. Jede Änderung am Cluster wird zu einem Commit. Jeder Commit ist nachvollziehbar, reviewbar, revertierbar. Wer hat wann was geändert? git log. Warum wurde eine bestimmte Einstellung gewählt? Commit-Message. Wie sah der Cluster vor drei Monaten aus? git checkout.

Der Reconciliation-Loop #

Das Herzstück von Flux ist der sogenannte Reconciliation-Loop. Flux läuft als eine Handvoll Controller im Cluster und macht in regelmäßigen Abständen genau eine Sache: vergleichen. Flux liest den gewünschten Zustand aus dem Git-Repository, liest den tatsächlichen Zustand aus der Kubernetes-API — und wenn es Abweichungen gibt, korrigiert Flux sie. Standardmäßig passiert das alle paar Minuten, und zwar in beide Richtungen: Neues im Repo wird eingespielt, manuelle Änderungen am Cluster werden wieder überschrieben.

Dieser letzte Punkt ist wichtig: Wer per Hand ein Deployment ändert, das von Flux verwaltet wird, hat das Problem nicht gelöst — nur verzögert. Beim nächsten Reconcile ist die Änderung weg. Das ist kein Bug, das ist das Feature. Der Cluster gehört dem Repo, nicht dem Admin.

Sources und Kustomizations #

Flux arbeitet mit zwei Kernkonzepten, die man verstanden haben sollte, bevor man eigene Manifeste schreibt:

Eine Source ist die Quelle, aus der Flux seine Konfiguration zieht. Im einfachsten Fall ein GitRepository, das auf ein Git-Repo mit einem bestimmten Branch zeigt. Es gibt auch HelmRepository für Helm-Charts und OCIRepository für Container-Registries. Flux zieht von diesen Sources regelmäßig den aktuellen Stand und stellt ihn intern zur Verfügung.

Eine Kustomization (Achtung: nicht zu verwechseln mit klassischem Kustomize, auch wenn es darauf aufbaut) ist eine Anweisung an Flux, aus einer Source einen bestimmten Pfad zu nehmen, ihn auf den Cluster anzuwenden und dort zu halten. Kustomizations haben Abhängigkeiten untereinander — dependsOn sorgt dafür, dass zum Beispiel erst cert-manager deployed wird, bevor ein ClusterIssuer erstellt wird, der ihn voraussetzt. So entsteht eine definierte Reihenfolge beim Bootstrap.

Für Helm-Charts gibt es zusätzlich den HelmRelease — im Prinzip das Flux-Äquivalent zu einem helm install, nur dass der Release deklarativ im Repo beschrieben steht und von Flux gepflegt wird.

Warum Flux und nicht Argo CD? #

Die ehrliche Antwort: beides funktioniert. Argo CD ist populärer und hat eine schönere Web-UI, Flux ist schlanker und Kubernetes-nativer aufgebaut. Für mich hat der Ausschlag gegeben, dass Flux ohne eigene zentrale UI auskommt — der Zustand des Systems ist das Repo, nicht ein Dashboard. Das passt besser zu meiner Philosophie: keine zusätzlichen Komponenten, wenn der vorhandene Weg (Git + kubectl/flux CLI) reicht.

Ansible — dort wo Kubernetes aufhört #

Flux kann vieles, aber nicht alles. Bevor der Cluster überhaupt existiert, muss jemand die VMs provisionieren, Proxmox konfigurieren, SSH einrichten, Kernel-Parameter setzen, kubeadm ausführen. Das ist klassische Konfigurationsverwaltung auf OS-Ebene — und genau dafür ist Ansible gemacht.

Die Trennung ist sauber: Ansible baut das Fundament bis einschließlich eines leeren, funktionsfähigen Kubernetes-Clusters mit Flux darauf. Ab dort übernimmt Flux. Alles, was innerhalb des Clusters passiert, ist GitOps — alles darunter ist Ansible. Zwei Werkzeuge, zwei klar getrennte Zuständigkeiten, kein Overlap.


SOPS — Secrets in Git, aber richtig #

Sobald GitOps konsequent gedacht wird, stellt sich eine unangenehme Frage: Was passiert mit Passwörtern, API-Tokens und Zertifikaten? Die gehören logisch zum Cluster-Zustand — also ins Repo. Aber ein Datenbankpasswort im Klartext auf GitHub oder auch nur in einem privaten Git-Server? Keine gute Idee.

Die Lösung heißt SOPS (Secrets OPerationS), ein Tool von Mozilla, das genau dieses Problem adressiert: Secrets werden verschlüsselt im Repo abgelegt, und erst auf dem Cluster wieder entschlüsselt. In Kombination mit age als Verschlüsselungs-Backend entsteht ein Setup, das überraschend schlank ist: ein Keypair, eine .sops.yaml-Konfigurationsdatei, fertig.

Der Weg eines Secrets: vom lokalen age-Keypair über die Verschlüsselung ins Git-Repository bis zur Entschlüsselung durch Flux im Cluster
Der Weg eines Secrets: vom lokalen age-Keypair über die Verschlüsselung ins Git-Repository bis zur Entschlüsselung durch Flux im Cluster

Warum SOPS zum Start vollkommen ausreicht #

Für eine private Cloud — und ehrlich gesagt auch für viele kleine bis mittlere Produktivumgebungen — ist SOPS die richtige Wahl. Nicht als Kompromiss, sondern als bewusste Entscheidung:

Kein zusätzlicher Betrieb. SOPS ist kein Dienst, der im Cluster läuft. Es ist ein CLI-Tool beim Verschlüsseln und eine kleine Flux-Integration beim Entschlüsseln. Kein zusätzlicher Pod, keine HA-Replikation, kein Backup-Konzept für das Secret-System selbst. Was läuft, ist der age-Key als Kubernetes-Secret im flux-system-Namespace — das war’s.

Git-nativ. Verschlüsselte Dateien sind ganz normale YAML-Dateien. Sie landen im Commit, sie landen im Diff, sie landen in der History — nur eben verschlüsselt. SOPS verschlüsselt pfiffigerweise nur die Werte, nicht die Schlüssel, sodass Diffs trotz Verschlüsselung noch lesbar bleiben: man sieht, dass sich database.password geändert hat, aber nicht worauf.

Passt zur Philosophie. Wer eine private Cloud ohne Over-Engineering aufbauen will, will nicht nebenbei einen HashiCorp-Vault-Cluster betreiben. Vault ist ein exzellentes Werkzeug — aber es ist eben auch ein eigenes verteiltes System mit Seal/Unseal-Prozedur, eigenem Backup, eigenem Monitoring, eigener Auth-Konfiguration. Für drei bis fünf selbstgehostete Dienste ist das ein Missverhältnis von Aufwand zu Nutzen.

Wie das Setup konkret aussieht #

Das Setup in groben Zügen: Ein age-Keypair wird lokal generiert, der öffentliche Teil landet in der .sops.yaml im Repo, der private Teil wird einmalig als Kubernetes-Secret in den Cluster gebracht (per Ansible oder manuell beim Bootstrap). Flux bekommt in seinen Kustomizations die Anweisung, SOPS-verschlüsselte Dateien vor dem Anwenden mit diesem Key zu entschlüsseln. Ab dann funktioniert es transparent: Wer ein neues Secret hinzufügen will, schreibt die YAML, verschlüsselt sie mit sops --encrypt, committet sie. Flux rollt sie beim nächsten Reconcile aus.

Die .sops.yaml legt dabei pro Pfad oder Dateinamen-Muster fest, mit welchem Key verschlüsselt wird und welche Felder überhaupt verschlüsselt werden sollen — typischerweise data und stringData bei Kubernetes-Secrets, damit die umgebenden Metadaten (Name, Namespace, Labels) weiterhin lesbar sind.

Vergleich: Sealed Secrets und External Secrets #

Im Kubernetes-Ökosystem gibt es zwei weitere populäre Ansätze, die sich in der Philosophie unterscheiden:

Sealed Secrets (von Bitnami) funktioniert ähnlich wie SOPS: verschlüsselte Secrets im Repo, Entschlüsselung im Cluster. Der entscheidende Unterschied ist, dass Sealed Secrets einen Controller im Cluster braucht, der sein eigenes Schlüsselpaar verwaltet — und dieses Schlüsselpaar ist nicht portabel. Wird der Controller neu aufgesetzt (zum Beispiel bei einem Cluster-Rebuild), sind alle alten Sealed Secrets wertlos, wenn das Schlüsselpaar nicht gesondert gesichert wurde. SOPS mit age hat diesen Bruch nicht: der Key ist eine Datei, die man wie jeden anderen Backup-Artefakt behandelt.

External Secrets Operator (ESO) verfolgt einen ganz anderen Ansatz: Secrets liegen gar nicht im Repo, sondern in einem externen Secret-Manager (Vault, AWS Secrets Manager, 1Password, Azure Key Vault). ESO holt sie dort ab und erstellt daraus Kubernetes-Secrets. Das ist mächtig, besonders wenn man ohnehin schon einen Secret-Manager betreibt — aber es verlagert die Komplexität nur: jetzt muss der externe Dienst betrieben und abgesichert werden. Für eine private Cloud, die bewusst ohne externe Abhängigkeiten auskommen will, ist das der falsche Weg.

Die Reihenfolge in der Praxis ist also oft: SOPS für den Start, ESO mit Vault wenn man in eine Größenordnung wächst, in der dynamische Credentials und zentrales Audit-Logging zum Thema werden.

Die ehrlichen Grenzen von SOPS #

Es wäre unseriös, SOPS als Universallösung zu verkaufen. Es gibt klare Grenzen, die man kennen sollte — und die bei kleinen Umgebungen nicht weh tun, bei größeren aber zunehmend unangenehm werden:

Manuelle Key-Rotation. Will man den age-Key wechseln (regelmäßig empfehlenswert, spätestens wenn jemand das Team verlässt, der Zugriff hatte), bedeutet das: alle Secrets im Repo mit dem neuen Key neu verschlüsseln, alten Key aus der Konfiguration entfernen, neuen Key im Cluster deployen. SOPS hat für die Massen-Neuverschlüsselung zwar den sops updatekeys-Befehl, aber der Vorgang ist trotzdem ein bewusster, koordinierter Eingriff — kein automatischer Prozess, wie ihn zum Beispiel Vault mit seinen dynamischen Credentials bieten würde.

Kein zentrales Audit-Log. Wer hat wann auf welches Secret zugegriffen? Bei Vault: vault audit. Bei SOPS: die Antwort ist eine Mischung aus git log (wer hat das Secret geändert), Cluster-Audit-Logs (wer hat das Kubernetes-Secret gelesen) und dem Vertrauen darauf, dass jeder, der den age-Key hat, ihn sachgemäß behandelt. Für eine Ein-Personen-Umgebung völlig ausreichend — für einen Compliance-Kontext mit mehreren Admins und Nachweispflichten nicht mehr.

Key-Management ist Admin-Sache. Der private age-Key ist die Achillesferse des gesamten Setups. Wer ihn verliert, verliert den Zugriff auf alle Secrets im Repo — und damit potenziell die Fähigkeit, den Cluster nach einem Totalausfall wieder aufzubauen. Wer ihn unkontrolliert verteilt, hat ein unkontrolliertes Secret. Es gibt keine automatische Rotation, kein eingebautes Backup, keine Key-Escrow-Mechanik. All das liegt in der Verantwortung des Admins — was gleichzeitig die größte Stärke (volle Kontrolle, keine Abhängigkeiten) und die größte Schwäche (menschliches Versagen ist die wahrscheinlichste Ausfallursache) ist.

Diese drei Punkte sind der Grund, warum ich immer sage: SOPS ist die richtige Wahl für den Start. Wer irgendwann an einen Punkt kommt, an dem dynamische Datenbank-Credentials, revozierbare API-Tokens oder nachweisbare Zugriffsaudits zum Thema werden, der sollte den Umstieg auf Vault oder einen vergleichbaren Secret-Manager nicht aussitzen. Bis dahin gilt: weniger ist mehr.


Reflector — der unterschätzte Helfer #

Ein kleines Tool, das unverhältnismäßig viel Arbeit abnimmt: Reflector kopiert Kubernetes-Secrets und ConfigMaps automatisch zwischen Namespaces. Klingt unspektakulär, ist aber in der Praxis wichtig: TLS-Zertifikate, die cert-manager in einem Namespace ausstellt, müssen oft in anderen Namespaces verfügbar sein. Ohne Reflector wäre das manuelle Kopieren — oder ein komplexerer Ansatz mit gemeinsamen Namespaces.


Monitoring: Prometheus, Grafana, Loki, Alloy und Gatus #

Ein Cluster ohne Monitoring ist ein Cluster, bei dem man Probleme erst merkt, wenn es zu spät ist. Mein Monitoring-Stack besteht aus mehreren Komponenten, die gut zusammenspielen:

Prometheus sammelt Metriken von allen Cluster-Komponenten — Node-Auslastung, Pod-Zustand, Kubernetes-Events. Grafana visualisiert diese Metriken in Dashboards, die ich über die Zeit angepasst habe. Loki ist Grafanas Log-Aggregationslösung: alle Container-Logs landen zentral in Loki und lassen sich direkt neben den Metriken in Grafana durchsuchen. Alloy — der Nachfolger des Grafana Agents — ist der Sammler, der Logs und Metriken von den Nodes an Loki und Prometheus weiterleitet.

Ergänzt wird das Ganze durch Gatus, einen schlanken Status- und Health-Check-Dienst. Während Prometheus die interne Sicht auf den Cluster liefert, prüft Gatus die Endpunkte von außen — also so, wie ein Nutzer sie auch erreichen würde. Damit fällt sofort auf, wenn ein Service zwar im Cluster „grün" aussieht, aber von außen nicht erreichbar ist.

Das Besondere an diesem Stack: alles läuft auf dem Cluster selbst, nichts wird an externe Dienste geschickt. Digitale Souveränität gilt auch für Monitoring-Daten.


RustDesk — Fernwartung aus dem eigenen Cluster #

Eine private Cloud ist kein reines Home-Lab-Projekt — sie ist Infrastruktur, die betrieben werden will. Und Betrieb heißt: auch dann auf Systeme zugreifen können, wenn man gerade nicht im selben Netz sitzt. Dafür gibt es einen ganzen Markt an Fernwartungslösungen, aber die meisten haben dieselbe Eigenschaft wie viele andere Dienste auch: Sie laufen in fremden Rechenzentren, oft außerhalb der EU, und jede Verbindung geht zuerst durch Server, die jemand anderem gehören.

RustDesk ist die Open-Source-Antwort auf genau dieses Problem. Es ist funktional mit TeamViewer oder AnyDesk vergleichbar — Bildschirmfreigabe, Dateitransfer, plattformübergreifende Clients — mit dem entscheidenden Unterschied, dass der Server-Teil selbst gehostet werden kann. Und genau das passt perfekt in einen Kubernetes-Cluster.

Wie RustDesk technisch aufgebaut ist #

RustDesk besteht serverseitig aus zwei Komponenten, die beide als einfache Deployments im Cluster laufen:

hbbs (Hybrid Rendezvous Server) ist der Vermittler. Wenn ein Client sich verbinden will, fragt er zuerst bei hbbs nach, wie der andere Client erreichbar ist. hbbs kennt die registrierten Geräte, verwaltet die IDs und hilft beim Aufbau einer direkten Peer-to-Peer-Verbindung — ähnlich wie ein STUN-Server bei WebRTC.

hbbr (Hybrid Relay Server) kommt ins Spiel, wenn die direkte Peer-to-Peer-Verbindung nicht zustande kommt — etwa weil beide Clients hinter restriktiven NATs oder Firewalls sitzen. In diesem Fall wird der Traffic über hbbr relayed. Das kostet etwas Bandbreite auf dem Server, ist aber der einzige verlässliche Fallback.

Im Cluster deployt man beide als separate Deployments mit jeweils einem LoadBalancer-Service — hbbs auf den Ports 21115–21116, hbbr auf 21117. Persistente Daten (die Geräte-IDs und das Schlüsselmaterial) landen auf einem Longhorn-Volume. Das ist ein überschaubares Manifest von vielleicht hundert Zeilen YAML, plus die üblichen Flux-Einträge.

Warum das in einer privaten Cloud dazugehört #

Es gibt einen pragmatischen und einen prinzipiellen Grund:

Pragmatisch: Ohne eine funktionierende Fernwartungslösung ist jeder Ausflug aus dem Heimnetz ein Risiko. Man sitzt im Zug, bekommt eine Fehler-Mail aus dem Monitoring, und dann? VPN aufbauen, SSH starten, Logs wälzen — das geht bei einem Linux-Server. Aber was ist mit einem Windows-Rechner im Büro, einem Mac im Homeoffice, der iPad eines Kunden? Dafür braucht es eine GUI-Fernwartung, und genau das liefert RustDesk.

Prinzipiell: Wenn der Gedanke hinter dieser ganzen Serie digitale Souveränität ist, dann gehört auch der Fernwartungskanal dazu. Jedes Werkzeug, mit dem man auf eigene Systeme zugreift, ist ein Werkzeug, das man im Zweifel verlieren kann — durch Preisänderungen, Lizenzumstellungen, oder weil der Anbieter einfach nicht mehr da ist. Ein selbst gehosteter RustDesk-Server gehört mir, läuft auf meinem Cluster, und die Verbindung zwischen zwei Clients kennt keinen dritten Beobachter.

Der Hinweis, den man bei RustDesk machen muss #

RustDesk ist Open Source, aber der offizielle öffentliche Server ist nicht der Weg, den man gehen sollte — die Betreiber weisen selbst darauf hin, dass er nicht für produktive Nutzung gedacht ist. Wer RustDesk ernsthaft einsetzen will, muss selbst hosten. Für diese Serie ist das keine Einschränkung, sondern der Normalfall: Ein weiterer Dienst, der ohnehin im Cluster läuft, mit kleinem Footprint und klarer Zuständigkeit. Das Stück Kuchen, das man sonst einer Fernwartungs-Firma abgibt, bleibt einfach auf dem eigenen Teller.


Fazit: Der Unterbau entscheidet #

Alle hier beschriebenen Komponenten haben eines gemeinsam: Man merkt sie nicht, wenn sie funktionieren. Aber sie sind der Grund, warum die Applikationen im zweiten Teil einfach laufen — zuverlässig, automatisch aktualisiert, mit Zertifikaten und Logs und Metriken. Den Unterbau richtig zu machen ist keine Fleißarbeit, die man hinter sich bringen muss. Es ist die eigentliche Arbeit.

Und er hört nicht beim Cluster selbst auf: Secret-Management mit SOPS schließt die Lücke zwischen GitOps-Anspruch und der Realität von Passwörtern und Tokens. RustDesk macht den Cluster über die Netzwerkgrenze hinaus erreichbar, ohne Abhängigkeit von Fremdanbietern. Beide sind Beispiele für Werkzeuge, die nicht zum Kern einer Kubernetes-Installation gehören, in einer souverän betriebenen privaten Cloud aber trotzdem dazugehören müssen.

Im nächsten Teil schauen wir uns die Applikationsschicht an — und warum ich bewusst auf bestimmte vermeintlich bequeme Lösungen verzichtet habe.


Dieser Artikel erschien zuerst auf LinkedIn. Gedanken dazu, Fragen oder eigene Erfahrungen — ich freue mich auf die Diskussion:

Diskussion auf LinkedIn öffnen