
Containerisierung? Microservices? Kubernetes? Braucht man das wirklich? Ist das nicht ein ziemlicher Overhead für die meisten Anwendungen? Solche Fragen hörte man in den letzen fünf Jahren sehr häufig. Oft zu Recht, weil es früher sehr aufwändig war, alle diese Konzepte unter einem Hut zu bringen. Mittlerweile hat sich dies geändert. Technologien wie Docker sind Mainstream geworden, Microservice-Frameworks gibt es wie Sand am Meer, Cloud-Anbieter sind bezahlbar. Und wenn wir nach Lösungen suchen, all das zu managen, landen wir bei Kubernetes.
Skalierbare, ausfallsichere, containerisierte, in der Cloud lebende Anwendungen sind mittlerweile Standard. Sie bringen durch ihre Flexibilität einen entscheidenden Vorteil gegenüber Anwendungen, die sich nur schwerfällig an steigende oder fallende Anforderungen anpassen können. Wenn man früher mehr Kapazitäten für einen Dienst benötigte, war das oft mit einem langwierigen Prozess und dem Kauf eines zusätzlichen Servers verbunden. Selbst virtualisierte Server stießen bald an ihre Grenzen.
Durch die Containerisierung von Anwendungen ist man hier heute viel flexibler. Containerisierung bedeutet, dass man einzelne Anwendungen innerhalb einer linux-basierten Containerumgebung laufen lässt, die in sich nur Systeme bereithält, die von der Anwendung benötigt werden. Sie läuft somit isoliert vom unterliegenden Serverbetriebssystem und benutzt nur die ihr zugeteilten Ressourcen. Dies bringt den Vorteil, dass man Container sehr einfach skalieren kann, indem man je nach Bedarf mehrere Container der gleichen Anwendung laufen lässt, um etwa auf steigende Benutzerzahlen zu reagieren. Auf diese Weise lässt sich die Anwendung perfekt dem Bedarf anpassen, so dass man, gerade in der Cloud, nur die genutzte Rechenleistung bezahlt, und keine brachliegenden Server.
Kubernetes: Plattform für andere Plattformen
Möchten wir diese Container steuern oder automatisieren, hilft eine Orchestrierungsplattform: Als diese hat sich mittlerweile Kubernetes als Standard durchgesetzt. Kubernetes ist ein Open-Source-Projekt mit über 31.000 Kontributoren, welches komplett community-gesteuert entwickelt wird. Alle großen IT-Konzerne wie Google, Amazon oder IBM unterstützen und nutzen Kubernetes, um ihre Dienste im Netz anzubieten. Da Kubernetes somit auch keinen Betreiber vorgibt, besteht auch keine Gefahr eines Vendor-Lock-ins bei der Nutzung.
Kubernetes bietet eine API (kubectl) und ein Konfigurationsmanagement, welches es ermöglicht, ganze Infrastruktur- und Softwararchitekturen zu beschreiben und zu steuern, wobei es keinerlei Vorgaben macht und komplett auf Individualität setzt. Container werden zu Pods zusammengefasst und durch so genannte Resource Types beschrieben. So lassen sich alle Arten von Diensten wie etwa Loadbalancern (z. B. Ingress), verteilte Loggingsysteme (z. B. Fluentd oder Elasticstack), Monitoring (z.B. Prometheus), Statefull Services wie Datenbanken oder Message-Queues im Cluster verteilen, neben den eigentlichen fachlichen Anwendungen. Configmaps und verschlüsselte Secrets dienen dem Parametriesieren von Services und dem Verwalten von Passwörtern oder Zertifikaten. Ein so genannter Service Mesh (z.B. linkerd) beschreibt, wie diese verschiedenen Dienste untereinander kommunizieren und der Netzwerkverkehr sich verhält.
Kubernetes bietet zudem eine Vielzahl an Möglichkeiten, um mithilfe von Health- oder Readyness Checks Probleme im Cluster zu erkennen und automatisch zu beheben (self-healing). Im Zusammenspiel mit Cloud-Providern wie AWS, Digital Ocean oder Google Cloud lassen sich automatisch weitere Server Nodes provisionieren oder deprovisionieren – je nachdem, ob mehr oder weniger Leistung gefordert ist. Aber auch in privaten Clouds oder On-Premise-Anwendungen spielen diese Werte eine Rolle. So bietet ein Mischmodell aus verschiedenen Clustern und Clouds insbesondere im Bereich Ausfallsicherheit und Disaster Recovery Vorteile, weil redundante Systeme in verschiedenen Verfügbarkeitszonen einerseits die Latenzen zum Benutzer verkürzen können und sich andererseits gegenseitig abfangen, wenn ein Cluster ausfallen sollte. Im Bestfall merkt ein User dann gar nichts davon.
Microservices und Legacy Software
Anwendungen, die modular gebaut wurden und als Microservice-Architektur gestaltet sind, haben in diesem Modell entscheidende Vorzüge. Weil viele Teile der Anwendung unabhängig voneinander arbeiten, können diese viel einfacher containerisiert und unabhängig deployt bzw. skaliert werden. So lassen sich bei Lastspitzen nur die Teile skalieren, die gerade benötigt werden. Somit ist in einer verteilten Anwendung der Ressourcen-Footprint (CPUs und RAM-Verbrauch) viel besser steuerbar und sorgt so für eine Kosteneinsparung. Bei einer monolithischen Architektur hat man im Gegensatz dazu den Nachteil, dass das gesamte System komplett dupliziert werden muss.
Dies bedeutet allerdings nicht, dass Containerisierung in der Cloud für Legacy-Projekte oder monolithische Anwendungen keine Vorteile bringt. Zum Einen kann man auch bei containerisierten Monolithen durch andere anderen Vorteile punkten, wie etwa High Availibility oder eine einfache Integration in Release- und Deploy-Pipelines. Andererseits ist es oft möglich Monolithen sinnvoll aufzubrechen oder zumindest Front- und Backend-Systeme zu trennen. Auch die Komplexität eines alten Enterprise-Palastes lässt sich einfacher kontrollieren und handhaben, wenn man ihn in modulare Services aufteilt. Durch die Trennung der Zuständigkeiten (Seperation of Concern) erreichen wir auch hier eine bessere Wart- und Erweiterbarkeit, sowie meist auch ein besseres Security-Konzept in der Anwendung. Kubernetes hilft hier mit einer Vielzahl an unterstützenden Systemen oder einer leichteren Integrierbarkeit in Third-Party-Lösungen.
Integration von Tools, Release Management und CI/CD
Ein Nachteil, der bei Kubernetes oft genannt wird, ist seine Komplexität und die damit verbundene hohe Lernkurve beim Betrieb eines Kubernetes-Clusters. Mittlerweile muss man allerdings dazusagen, dass um Kubernetes herum inzwischen eine ganze Menge weiterer Technologien und Frameworks entstanden ist, welche die Komplexität einer Cluster-Orchestrierung kontrollierbar machen. So bieten fast alle großen Cloud-Anbieter gemanagete Kubernetes-Cluster an, so dass sich ein Softwareteam stärker auf die Entwicklung anstatt auf die Administration konzentrieren kann. Kubernetes unterstützt dazu selbst die Integration von Cloud-APIs, so dass Cloud-Dienste automatisiert werden können.
Dazu gibt es Release-Management-Tools von Drittherstellern wie etwa Helm, welche die Versionierung von Releases und Builds vereinfachen, sowie die Monitoring-Lösungen Prometheus, Grafana oder Instana usw., welche die Observability des Gesamtsystems verbessern.
Die Integration von Kubernetes in CI/CD-Pipelines mit No-Downtime-Strategien ist ebenso machbar wie die Möglichkeiten von Canary-Updates oder Tests, wo nur ein kleiner Teil der Nutzer ein Update zu Testzwecken zur Verfügung gestellt bekommt, so dass im Falle von Bugs schnell zurückgerollt werden kann.
Fazit
In der Softwareentwicklung sind verteilte, skalierbare Anwendungen nicht mehr wegzudenken. Die Infrastruktur in der Cloud zu kennen, die Containerisierung von Services und vor allem die Entscheidung, wie Software modular geschnitten werden muss, sind mittlerweile grundlegende Aufgaben. Kubernetes hat sich als Open-Source-Orchestrierungsplattform genau dafür als Standard durchgesetzt und ermöglicht es Entwicklern, ihre Dienste zu beschreiben und perfekt in eine Cluster-Infrastruktur einzubetten.
Durch die Trennung von Zuständigkeiten einzelner Services lassen sich bei sich weiterentwickelnden Anwendungen Features schneller implementieren (z. B. in Feature-Teams) und Abhängigkeiten aufbrechen. Durch automatische Skalierung und Provisionierung bietet Kubernetes außerdem eine effiziente Ressourcenverwaltung und Flexibilität. Man ist nicht an diverse Cluster-Anbieter gebunden, kann diese sogar mixen oder nicht-kubernetes-gemanagte Anwendungen einfach integrieren.
Der meiner Meinung nach größte Vorteil von Kubernetes liegt allerdings beim Endbenutzer. Denn eine gut verteilte Anwendung bedeutet eine extrem hohe Ausfallsicherheit und Verfügbarkeit der gebotenen Leistung.
Um also auf die Fragen vom Anfang zurückzukommen, ob man Kubernetes wirklich braucht, lautet die Antwort: Ja, absolut. Die Art der Softwareentwicklung und Infrastrukturarchitektur wird sich immer weiterentwickeln, doch die Konzepte von Kubernetes lösen schon heute einen Großteil der Probleme, die sich in den letzten Jahrzehnte auf diesem Weg ergeben haben.
Empfehlungen der Redaktion zum Thema: die JUGH-Vorträge Microservices. Patterns & Antipatterns (Stefan Tilkov) und Herausforderungen von Datenbanken in Containern (Johannes Unterstein). Außerdem thematisch zugehörig und interessant: die Erfahrungen und Möglichkeiten von DevOps (Tobias Pressel).