- Gitpod hat 6 Jahre lang Kubernetes genutzt, um eine „Plattform für Remote-Entwicklungsumgebungen“ aufzubauen, unterstützt 1,5 Millionen Nutzer und stellt täglich Tausende von Entwicklungsumgebungen bereit
- Dabei wurde jedoch klar, dass Kubernetes für den Aufbau von Entwicklungsumgebungen nicht geeignet ist
- Es geht hier nicht darum, ob man Kubernetes für Produktions-Workloads verwenden sollte oder nicht, und auch nicht darum, wie man die Developer Experience für das Deployment von Anwendungen auf K8s gestaltet
→ Es geht darum, wie man Entwicklungsumgebungen in der Cloud aufbaut – oder eben nicht
[Warum Entwicklungsumgebungen besonders sind]
- Sie sind stark zustandsbehaftet und hochgradig interaktiv
- Sie lassen sich nicht zwischen Nodes verschieben
- Große Mengen an Quellcode, Build-Caches, Docker-Containern, Testdaten usw. ändern sich häufig, und die Migrationskosten sind hoch
- Anders als bei Produktionsdiensten gibt es eine 1:1-Interaktion zwischen Entwickler und Umgebung
- Entwickler sind eng mit ihrem Quellcode und ihren Änderungen verbunden
- Sie möchten weder Änderungen am Quellcode verlieren noch vom System blockiert werden
- Entwicklungsumgebungen sind besonders empfindlich gegenüber Ausfällen
- Sie haben unvorhersehbare Ressourcennutzungsmuster
- Die meiste Zeit wird nicht viel CPU-Bandbreite benötigt, aber innerhalb weniger hundert ms können mehrere Kerne nötig sein
- Ist das langsamer, führt das zu inakzeptabler Latenz und fehlender Reaktionsfähigkeit
- Sie benötigen weitreichende Berechtigungen und Funktionen
- Anders als Produktions-Workloads brauchen sie Root-Zugriff und die Fähigkeit, Pakete herunterzuladen und zu installieren
- Dinge, die bei Produktions-Workloads Sicherheitsprobleme wären, sind in Entwicklungsumgebungen erwartetes Verhalten (Root-Zugriff, erweiterte Netzwerkfunktionen, zusätzliche Dateisystem-Mounts usw.)
- Diese Eigenschaften unterscheiden sie von typischen Anwendungs-Workloads und beeinflussen Infrastrukturentscheidungen stark
[Aktuelles System: Kubernetes]
- In der Anfangszeit von Gitpod schien Kubernetes die ideale Infrastrukturlösung zu sein
- Skalierbarkeit, Container-Orchestrierung und das reichhaltige Ökosystem passten gut zur Vision von Cloud-Entwicklungsumgebungen
- Mit wachsendem Maßstab und steigender Nutzerbasis traten jedoch Schwierigkeiten bei Sicherheit und Zustandsverwaltung auf
- Kubernetes wurde dafür entworfen, gut kontrollierte Anwendungs-Workloads auszuführen, nicht schwer beherrschbare Entwicklungsumgebungen
- Kubernetes im großen Maßstab zu betreiben ist komplex
- Managed Services wie GKE oder EKS entschärfen einige Probleme, bringen aber ihre eigenen Einschränkungen und Grenzen mit sich
- Viele Teams, die CDE betreiben wollen, unterschätzen die Komplexität von Kubernetes
- Das führte beim früheren selbstverwalteten Gitpod-Produkt zu erheblichem Support-Aufwand
Schwierigkeiten beim Ressourcenmanagement
- Die größte Herausforderung sind CPU- und Speicherzuweisung
- Es klingt attraktiv, Umgebungen auf einem Node gemeinsam zu betreiben, in der Praxis tritt aber der Noisy-Neighbor-Effekt stark auf
- CPU-Probleme
- Entwicklungsumgebungen brauchen oft lange wenig CPU und dann schlagartig sehr viel
- Es wurde mit CFS-basierten Lösungen, benutzerdefinierten Controllern usw. experimentiert, aber Vorhersagen sind schwierig
- Selbst mit statischen CPU-Limits konkurrieren mehrere Prozesse miteinander
- Speichermanagement
- Fester Speicher ist einfach zuzuweisen, aber einschränkend
- Overbooking kann zum Beenden von Prozessen führen
- Durch die Einführung von Swap wurde die Notwendigkeit von Overbooking etwas gemildert
Optimierung der Storage-Performance
- IOPS und Latenz beeinflussen die Erfahrung in Entwicklungsumgebungen
- Mit verschiedenen Setups wurde experimentiert, um ein Gleichgewicht zwischen Geschwindigkeit, Stabilität, Kosten und Performance zu finden
- SSD RAID 0
- Block-Storage wie EBS und Persistent Disks
- PVC
- Backup und Restore sind kostspielige Vorgänge
Optimierung von Auto-Scaling und Startzeiten
- Die Minimierung der Startzeit hatte höchste Priorität
- Man ging davon aus, dass mehrere Workspaces auf einem Node wegen gemeinsamer Caches bessere Startzeiten bringen würden, doch das war nicht der Fall
- Kubernetes setzt den Startzeiten eine Untergrenze
- Entwicklung der Scale-out-Methoden
- Mit Ghost-Workspaces und Ballast-Pods wurde beim Scale-out experimentiert
- Die Einführung eines Autoscaler-Plugins verbesserte die Skalierungsstrategie deutlich
- Proportionales Auto-Scaling für Lastspitzen
- Leere Pods werden gestartet, um auf Nachfragespitzen schnell reagieren zu können
- Verschiedene Ansätze zur Optimierung des Image-Pullings
- DaemonSet-Pre-Pulls, maximale Wiederverwendung von Layers, vorgebackene Images, Stargazer und Lazy Pulling, Registry-facade + IPFS
Komplexität beim Networking
- Zugriffskontrolle für Entwicklungsumgebungen
- Umgebungen müssen vollständig voneinander isoliert sein
- Network Policies helfen, aber mit zunehmender Zahl von Services treten Zuverlässigkeitsprobleme auf
- Geteilte Netzwerkbandbreite
- Manche CNI unterstützen Network Shaping, das ist aber ein weiterer Regelungsbereich
Sicherheit und Isolation: Balance zwischen Flexibilität und Schutz
- Die größte Herausforderung ist es, Nutzern Flexibilität zu geben und gleichzeitig eine sichere Umgebung bereitzustellen
- Root-Rechte für Nutzer zu gewähren, ist mit vielen Problemen behaftet
- User Namespaces sind eine feinere Lösung
- Dateisystem-UID-Übersetzung, maskierte
proc-Mounts, FUSE-Unterstützung, Bereitstellung von Netzwerkfunktionen, Aktivierung von Docker
- Dateisystem-UID-Übersetzung, maskierte
- Schwierigkeiten bei der Implementierung von User Namespaces
- Performance-Auswirkungen, Kompatibilitätsprobleme, Komplexität, Unterstützung verschiedener Kubernetes-Versionen
[Experimente mit Micro-VMs]
- Als die Grenzen von Kubernetes deutlich wurden, begann Gitpod, Micro-VM-Technologien (uVM) wie Firecracker, Cloud Hypervisor und QEMU als Mittelweg zu untersuchen
- Man hoffte, die Vorteile der Containerisierung zu behalten und zugleich bessere Ressourcenisolierung, Kompatibilität mit anderen Workloads (einschließlich Kubernetes) und mehr Sicherheit zu erreichen
- Vorteile von Micro-VMs
- Sie bieten attraktive Vorteile, die gut zu den Zielen von Cloud-Entwicklungsumgebungen passen
- Verbesserte Ressourcenisolierung: Die Fähigkeit zum Overbooking sinkt, aber die Ressourcenisolierung ist besser als bei Containern. Konkurrenz um gemeinsame Kernel-Ressourcen entfällt, wodurch die Performance je Entwicklungsumgebung besser vorhersagbar wird
- Memory-Snapshots und schnelles Resume: Firecrackers
userfaultfdunterstützt Memory-Snapshots. Dadurch kann die gesamte Maschine inklusive laufender Prozesse nahezu sofort fortgesetzt werden. Für Entwickler bedeutet das deutlich schnellere Starts und die Möglichkeit, genau dort weiterzumachen, wo sie aufgehört haben - Verbesserte Sicherheitsgrenzen: uVMs können als starke Sicherheitsgrenze dienen, sodass die in Kubernetes implementierten komplexen Mechanismen mit User Namespaces entbehrlich werden. Dadurch wäre vollständige Kompatibilität mit einem breiteren Spektrum an Workloads möglich, einschließlich verschachtelter Containerisierung (Docker oder Kubernetes innerhalb der Entwicklungsumgebung)
- Herausforderungen von Micro-VMs
- Die Experimente mit Micro-VMs zeigten jedoch mehrere wesentliche Herausforderungen
- Overhead: Selbst leichte VMs verursachen mehr Overhead als Container. Das wirkt sich sowohl auf Performance als auch Ressourcenauslastung aus – ein entscheidender Faktor für Plattformen für Cloud-Entwicklungsumgebungen
- Image-Konvertierung: Um OCI-Images in ein für uVMs nutzbares Dateisystem umzuwandeln, sind benutzerdefinierte Lösungen nötig. Das verkompliziert die Image-Management-Pipeline und kann Startzeiten beeinträchtigen
- Technologiespezifische Einschränkungen
- Firecracker: keine GPU-Unterstützung (für einige Entwicklungs-Workflows zunehmend wichtig), keine
virtiofs-Unterstützung (schränkt effiziente Optionen zur Dateisystemfreigabe ein) - Cloud Hypervisor: keine
userfaultfd-Unterstützung, wodurch Snapshot- und Restore-Prozesse langsamer werden (und ein Hauptvorteil von uVMs geschwächt wird)
- Firecracker: keine GPU-Unterstützung (für einige Entwicklungs-Workflows zunehmend wichtig), keine
- Datenbewegung als Problem: uVMs bringen große Memory-Snapshots mit sich, wodurch Datenbewegung schwieriger wird. Das beeinflusst sowohl Scheduling als auch Startzeiten – zentrale Elemente der Nutzererfahrung bei Cloud-Entwicklungsumgebungen
- Storage-Aspekte: Experimente mit an Micro-VMs angeschlossenen EBS-Volumes eröffneten neue Möglichkeiten, warfen aber auch neue Fragen auf
- Persistenter Storage: Wenn Workspace-Inhalte auf angeschlossenen Volumes liegen, müssen Daten nicht wiederholt aus S3 geholt werden, was schnellere Starts und geringere Netzwerknutzung verspricht
- Performance-Aspekte: Die gemeinsame Nutzung von Volumes mit hohem Durchsatz zwischen Workspaces könnte die I/O-Performance verbessern, wirft aber Fragen nach effektiven Quoten, Latenzmanagement und Skalierbarkeit auf
- Erkenntnisse aus den Micro-VM-Experimenten
- Micro-VMs wurden am Ende zwar nicht zur primären Infrastrukturlösung, lieferten aber wertvolle Erkenntnisse
- Besonders positiv waren vollständige Workspace-Backups für Entwicklungsumgebungen sowie die Erfahrung, Laufzeitstatus anzuhalten und später fortzusetzen
- Zum ersten Mal wurde erwogen, Kubernetes zu verlassen. Nach Bemühungen, KVM und uVMs in Pods zu integrieren, begann man Optionen außerhalb von Kubernetes zu prüfen
- Storage wurde erneut als entscheidender Faktor erkannt, um drei Ziele gleichzeitig zu erreichen: stabile Start-Performance, stabile Workspaces ohne Datenverlust und optimale Maschinenauslastung
Kubernetes ist als Plattform für Entwicklungsumgebungen äußerst anspruchsvoll
- Wie oben beschrieben, braucht es für Entwicklungsumgebungen ein System, das deren besondere Zustandsbehaftung respektiert
- Es muss Entwicklern die nötigen Berechtigungen für produktives Arbeiten geben und zugleich sichere Grenzen gewährleisten
- All das muss mit geringem Betriebsaufwand und ohne Kompromisse bei der Sicherheit erreicht werden
- Heute ist es zwar möglich, all das mit Kubernetes zu erreichen, aber zu erheblichen Kosten
- Man hat den Unterschied zwischen Anwendungs-Workloads und System-Workloads auf die harte Tour gelernt
- Kubernetes ist unglaublich stark
- Es wird von einer leidenschaftlichen Community getragen und verfügt über ein wirklich reichhaltiges Ökosystem
- Für Anwendungs-Workloads ist Kubernetes weiterhin eine gute Wahl
- Für System-Workloads wie Entwicklungsumgebungen bringt Kubernetes jedoch enorme Herausforderungen bei Sicherheit und Betriebsaufwand mit sich
- Micro-VMs und klar definierte Ressourcenbudgets helfen, aber die Kosten werden zum dominierenden Faktor
- Deshalb trat man nach Jahren, in denen Entwicklungsumgebungen effektiv in die Kubernetes-Plattform hineindesignt und hineingezwungen wurden, einen Schritt zurück und überlegte, wie eine künftige Entwicklungsarchitektur aussehen sollte
- Im Januar 2024 begann der Aufbau, im Oktober wurde Gitpod Flex veröffentlicht
- Mehr als 6 Jahre hart erarbeiteter Erkenntnisse darüber, wie sich Entwicklungsumgebungen im Internet-Maßstab sicher betreiben lassen, sind in die Architektur eingeflossen
Die Zukunft der Entwicklungsumgebungen
- Mit Gitpod Flex übernimmt Gitpod grundlegende Aspekte von Kubernetes – die freie Anwendung von Regelungstheorie und deklarativen APIs – vereinfacht aber die Architektur und verbessert die Sicherheitsbasis
- Die Orchestrierung von Entwicklungsumgebungen erfolgt über eine stark von Kubernetes inspirierte Control Plane
- Es werden die nötigen Abstraktionsebenen eingeführt, die speziell auf Entwicklungsumgebungen zugeschnitten sind, während der größte Teil unnötiger Infrastrukturkomplexität entfällt
- All das geschieht mit Zero-Trust-Sicherheit als oberster Priorität
- Dank dieser neuen Architektur lassen sich Dev Container nahtlos integrieren
- Zudem eröffnet sich die Möglichkeit, Entwicklungsumgebungen auf dem Desktop auszuführen
- Da die schwere Last der Kubernetes-Plattform entfällt, lässt sich Gitpod Flex nun in weniger als 3 Minuten selbst hosten und in beliebig vielen Regionen ausrollen
- Das bietet feinere Kontrolle über Compliance sowie mehr Flexibilität bei der Modellierung organisatorischer Grenzen und Domains
(Ursprünglich war das ein anderer Artikel, aber es schien sinnvoll, ihn zusammen zu behandeln, daher hier gemeinsam übertragen.)
Gitpod Flex
- Die erste Automatisierungsplattform für Zero-Trust-Entwicklungsumgebungen
- Entwickelt für den Betrieb auf Laptops, in der Cloud und On-Premises, wobei Quellcode, Daten und geistiges Eigentum innerhalb privater Netzwerke bleiben
- Bietet Bausteine zur Automatisierung des Softwareentwicklungslebenszyklus, beginnend mit Entwicklungsumgebungen
- Automations
- Programmierbare Aufgaben und Services, definiert über Repositories oder APIs
- Helfen Entwicklern, Probleme selbst zu lösen, und ermöglichen es Teams für Entwicklerproduktivität, Verbesserungen an Entwicklungsumgebungen zu zentralisieren
- Sie bieten mehr als das bloße Ausführen einfacher Skripte
- Möglich sind unter anderem Datenbank-Provisionierung und Seeding, Anpassung von Entwickler-Workflows, Betrieb temporärer Cluster, Einrichtung LLM-basierter Agenten-Workflows sowie zentralisierte globale oder regionale Durchsetzung von Sicherheit und Compliance
- Zero-Trust-Umgebungen
- Jeder Akteur und jeder Service wird nach dem Prinzip „never trust, always verify“ behandelt
- Vollständige Blockierung böswilliger Akteure, deutliche Verringerung der Angriffsfläche, geringeres Risiko für Malware oder Code-Abfluss
- Umfasst kontinuierliche Bewertung und explizite Verifizierung, verifizierte Enterprise-Verschlüsselung, granulare Zugriffskontrolle, vollständige Kontrolle über das Networking und vollständige Audit-Logs
- Am wichtigsten ist, dass Quellcode, Daten und geistiges Eigentum innerhalb privater Netzwerke bleiben
- Gitpod Desktop
- Ermöglicht Standardisierung und Automatisierung lokaler Entwicklungsumgebungen
- Startet mit Unterstützung für Apple Silicon
- Bietet null Latenz, eine schnellere, leichtere und einfachere Alternative zu Docker Desktop für Entwicklung, Kostenoptimierung durch Nutzung lokaler Rechenleistung sowie Disaster Recovery bei Ausfällen in Cloud oder auf Endpunkten
- Unterstützung für Development Container
- Vollständige Integration der Dev-Container-Spezifikation
- Bestehende Dev-Container-Konfigurationen können unverändert weiterverwendet werden
- Kompatibilität mit VS Code und anderen unterstützten Tools
- Konsistentes Arbeiten lokal oder in der Cloud
- Durch die Übernahme des Dev-Container-Standards wird das Definieren, Teilen und Verwalten von Entwicklungsumgebungen einfacher
Soll zur Grundlage für die Automatisierung der Softwareentwicklung der nächsten 10 Jahre werden
- Wir haben Entwicklungsumgebungen zu eng gedacht
- Eine Entwicklungsumgebung ist mehr als IDE, Abhängigkeiten und Tools – sie ist der grundlegende Raum, in dem Software entsteht
- Hier werden Code-Prototypen erstellt, von Menschen und Maschinen geformt, getestet, refaktoriert, kompiliert, paketiert, signiert und ausgerollt
- Sie bietet unvergleichlichen Zugang zu Entwicklungskontext, Workflows und Erkenntnissen und ermöglicht dadurch Funktionen, die andere Entwicklungsplattformen nicht bieten
- Produktvision
- Continuous Integration (CI) verschmilzt mit der Entwicklungsumgebung
- Sie dient als System of Record der Softwareentwicklung
- Eine Plattform für die nächste Generation von Entwickler-Tools
- Es geht nicht nur darum, Coding-Praktiken zu verbessern, sondern darum, den schnellsten und sichersten Weg zu schaffen, auf dem Unternehmen – vom Startup bis zum Fortune-50-Konzern – in den kommenden 10 Jahren skalieren und erfolgreich sein können
3 Kommentare
Bitter, dass inländische Unternehmen unter dem Vorwand der Sicherheit die Nutzung virtueller Desktops mit 8 GB RAM zur Pflicht machen.
Schon fähige Leute zu finden, die sich mit Kubernetes gut auskennen, ist schwierig — und ich denke, es wäre noch schwieriger, Leute zu finden, die die hier als Alternative vorgeschlagenen Dinge verstehen und ausprobieren wollen.
Hacker-News-Kommentare
Entwickler sollten die Geräte, auf denen sie entwickeln, selbst besitzen. Wenn eine konsistente Umgebung nötig ist, sollten Entwickler ihre eigenen Geräte besitzen und ein stabiles VM-Image erhalten. Versuche, die Entwicklungsumgebung auf einen Remote-Host zu verlagern, scheitern meist. Entwicklern passende Hardware bereitzustellen ist kosteneffizienter als Remote-Ressourcen. Die Ausführung des lokalen Stacks sollte unterstützt werden, und Container helfen dabei, Konsistenz zu wahren. Es werden Werkzeuge benötigt, die Daten in der lokalen Umgebung erzeugen; das lässt sich automatisieren. Zwar gibt es Nachteile beim Datenmanagement, aber in den meisten Unternehmen ist die Umsetzungskraft des Teams wichtiger als der Quellcode.
Der Einsatz von Kubernetes für Produktions-Workloads ist eine andere Frage; hier geht es darum, wie man Entwicklungsumgebungen in der Cloud aufbaut. Ein interessanter Artikel über die komplexen Engineering-Trade-offs von Kubernetes.
Der Beitrag erklärt die Probleme von Kubernetes und die ausprobierten Lösungsansätze, aber es fehlt letztlich an einer Erklärung der gewählten Alternative. Eine neue Lösung namens Gitpod Flex wird erwähnt, aber dazu gibt es kaum Informationen.
Kubernetes eignet sich für zustandslose Workloads, aber bei zustandsbehafteten Fällen ist LXC besser geeignet. LXC lässt sich ähnlich wie K8S clustern und stellt Werkzeuge auf der Datenebene bereit. Es bietet Systeminstanzen ähnlich wie VMs und erreicht eine Performance ähnlich wie Docker-Container. Es verwendet eine deklarative Syntax und kann als Basisschicht eines Kubernetes-Clusters eingesetzt werden.
Bei der Entwicklung einer CI-Lösung Kubernetes zu wählen, bedeutet, das Problem nicht richtig verstanden zu haben. Aus Sicherheitsgründen sollte man Werkzeuge wie Firecracker verwenden.
Kubernetes ist für Entwicklungsumgebungen nicht geeignet. Entwicklungsumgebungen befinden sich ständig in Veränderung. Ich verstehe den Bedarf an Cloud-Entwicklungsumgebungen nicht. Der Zweck containerisierter Apps ist es, die Synchronisierung von Entwicklungsumgebungen zwischen Teams zu vermeiden.
Das Kubernetes-Paper nennt die Kombination aus Low-Latency- und High-Latency-Workflows als einzigen Use Case. Es ist schwer zu rechtfertigen, Kubernetes für das Problem von Gitpod in Betracht zu ziehen.
Ich habe an einem Projekt ähnlich wie Gitpod gearbeitet, und ich verstehe nicht, warum man MicroVMs einsetzen würde, um Kubernetes zu ersetzen. Kubernetes kann externe Container orchestrieren und auch zum Ausführen von MicroVMs genutzt werden. Das größte Problem betrifft den Storage.
Entwicklungsumgebungen auf Kubernetes aufzubauen ist verschwenderisch. Wenn das Produkt als Self-Hosting in der Infrastruktur des Kunden läuft, sind Debugging und Support schwierig. Es ist wirksam, Ingenieure mit Netzwerk-, Speicher-, Compute- und Storage-Problemen direkt zu konfrontieren. Für große Teams ist Kubernetes ein Upgrade.