Bei Microservices handelt es sich um einen Architekturansatz im Zusammenhang mit der Erstellung von Cloud-Applikationen. Jede Applikation wird als ein Set von Services angelegt, die über APIs kommunizieren. Jeder dieser Services wird in eigenen Prozessen ausgeführt. Die Weiterentwicklung, die zur Cloud-Microservices-Architektur führte, begann vor über 20 Jahren. Das Konzept einer Servicestruktur ist älter als Container und stammt aus der Zeit vor den modernen Webapplikationen. Eine Microservices-Architektur ist eine Methode zur Entwicklung von Applikationen, die sich im Laufe der Zeit zu einer Best Practice weiterentwickelt hat.
Um die Vorteile heutiger Microservices-Architekturen zu verstehen, ist es wichtig, die Anfänge zu kennen.
Monolithische Applikationen
Zu Beginn befand sich jede Applikation auf einem einzelnen Server und bestand aus drei Ebenen:
Diese Ebenen waren in einen einzelnen, verflochtenen Stack integriert, der sich auf einem einzelnen, monolithischen Server in einem Datacenter befand. Dieses Muster war in allen Branchen und Technologiearchitekturen üblich. Im Allgemeinen handelt es sich bei einer Applikation um eine Sammlung von Code-Modulen für eine bestimmte Funktion – zum Beispiel eine Datenbank, verschiedene Arten von Geschäftslogik, Code für das Rendern von Grafiken oder Protokollierung.
In dieser monolithischen Architektur interagierten die Benutzer mit der Präsentationsschicht. Sie tauschte Daten mit der Geschäftslogik- und der Datenbankschicht aus, und die Informationen wurden dann wieder auf den Stack zum Anwender übertragen. Dies war zwar eine effiziente Möglichkeit, eine Applikation zu organisieren, führte jedoch zu vielen Schwachstellen – was wiederum bei einem Hardware- oder Codefehler zu langen Ausfällen führen konnte. Leider gab es in dieser Struktur keine „Selbstreparatur“. Wenn ein Teil des Systems beschädigt war, musste es durch menschliches Eingreifen mit einem Hardware- oder Software-Fix repariert werden.
Darüber hinaus musste für die Skalierung auf einer dieser Ebenen ein völlig neuer Server erworben werden. Sie mussten eine monolithische, auf einem einzelnen Server ausgeführte Applikation erwerben und einen Teil der Benutzer auf das neue System segmentieren. Diese Segmentierung führte zu Silos mit Benutzerdaten, die durch nächtliche Batch-Berichte abgeglichen werden mussten. Glücklicherweise sanken die Client-Anforderungen mit der zunehmenden Verbreitung von Webseiten und mobilen Anwendungen, sodass sich neue Methoden der Applikationsentwicklung heraubildeten.
Serviceorientierte Architektur (SOA)
Mitte der 2000er-Jahre veränderten sich die Architekturen, und es gab verschiedene Schichten als unabhängige Servicesilos außerhalb eines einzelnen Servers. Applikationen wurden entwickelt, um diese Services mithilfe eines Enterprise-Service-Bus für die Kommunikation zu integrieren. Mit diesem Ansatz können Administratoren diese Services unabhängig skalieren, indem Server über Proxy-Funktionen aggregiert werden. Der Ansatz ermöglichte den Entwicklern außerdem kürzere Zyklen, da sie sich auf einen Teil der Applikations-Servicestruktur konzentrieren konnten. Die Entkopplung von Services und die unabhängige Entwicklung erforderten die Verwendung von APIs, dem Set von Syntaxregeln, die Services zur Kommunikation untereinander verwenden.
Serviceorientierte Architekturen fielen auch mit dem Aufstieg der Virtual Machine (VM) zusammen, mit der physische Serverressourcen effizienter wurden. Services konnten viel schneller auf kleineren VMs bereitgestellt werden als die vorherigen monolithischen Applikationen auf Bare-Metal-Servern. Mit dieser Kombination von Technologien wurden bessere Hochverfügbarkeitslösungen (HA) entwickelt, sowohl innerhalb der Servicearchitektur als auch mit den zugehörigen Infrastrukturtechnologien.
Microservices
Heute wird die SOA-Strategie durch Cloud-Microservices als eine Sammlung granularer Services für Funktionen noch weiter aufgegliedert. Sammlungen von Microservices werden zu großen Macroservices kombiniert, wodurch der Code einer einzelnen Funktion im gesamten Service oder in einer größeren Endbenutzeranwendung noch schneller aktualisiert werden kann. Ein Microservice kümmert sich um eine einzelne Angelegenheit, zum Beispiel eine Datensuche, eine Protokollierungs- oder Webservice-Funktion. Dieser Ansatz erhöht die Flexibilität – zum Beispiel die Aktualisierung des Codes einer einzelnen Funktion, ohne dass ein Refactoring oder sogar eine erneute Bereitstellung der restlichen Microservices-Architektur erforderlich ist. Die Ausfallpunkte sind unabhängiger voneinander, wodurch eine insgesamt stabilere Anwendungsarchitektur entsteht.
Dieser Ansatz bietet Microservices auch die Möglichkeit zur Selbstreparatur. Angenommen, ein Microservice in einem Cluster enthält drei Unterfunktionen. Wenn eine dieser Unterfunktionen ausfällt, wird sie repariert. Mit Orchestrierungs-Tools wie Kubernetes kann die Selbstreparatur ohne menschlichen Eingriff erfolgen. Sie läuft im Hintergrund ab, automatisch und für den Anwender transparent.
Microservices-Architekturen werden gemeinsam mit Docker-Containern eingesetzt – ein Konstrukt für Paketierung und Implementierung. VM-Images dienen seit vielen Jahren als bevorzugter Implementierungsmechanismus. Container sind jedoch noch effizienter als VMs. Sie ermöglichen die Implementierung des Code (und der erforderlichen Code-Bibliotheken) auf jedem beliebigen Linux-System (oder jedem Betriebssystem, das Docker-Container unterstützt). Container sind der perfekte Implementierungsvektor für Microservices. Sie lassen sich innerhalb von Sekunden starten, sodass sie nach Ausfällen oder Migration schnell neu bereitgestellt werden können. Darüber hinaus lassen sie sich schnell skalieren, um den Anforderungen gerecht zu werden. Da Container bei Linux nativ sind, kann Standard-Hardware für umfangreiche Microservices-Farmen in jedem Datacenter, in einer Private Cloud oder Hybrid-Multi-Cloud eingesetzt werden.
Microservices sind fast von Beginn an mit Cloud-nativen Architekturen verflochten, sodass sie sich in vielerlei Hinsicht nicht mehr voneinander unterscheiden lassen. Aufgrund ihres Abstrahierungsgrads können Microservices und Container auf jedem kompatiblen Betriebssystem (in der Regel Linux) ausgeführt werden. Dieses Betriebssystem kann überall eingesetzt werden: in der Public Cloud, lokal, in einem virtuellen Hypervisor oder sogar auf Bare Metal. Vor dem Hintergrund, dass die Entwicklung verstärkt in der Cloud stattfindet, werden Cloud-native Architekturen und Praktiken zurück in lokale Datacenter migriert. Viele Unternehmen bauen lokale Umgebungen auf, die dieselben grundlegenden Merkmale wie die Cloud nutzen. So wird für alle Standorte bzw. für alle Cloud-nativen Umgebungen eine einheitliche Entwicklung ermöglicht. Dieser Cloud-native Ansatz wird durch die Einführung von Microservices-Architekturen und Container-Technologien ermöglicht und erforderlich.
Microservices sind dezentralisiert und laufen auf verschiedenen Servern, aber sie funktionieren trotzdem zusammen für eine Applikation. Idealerweise erfüllt jeder Microservice eine einzelne Funktion, was ein einfaches Routing zwischen Diensten mit API-Kommunikation ermöglicht. Weitere Vorteile:
Container
Container sind unveränderlich: Nach der Implementierung können sie nicht mehr (oder sollten nicht mehr) verändert werden. Wenn eine neue Version des Codes verfügbar wird, wird der Container zerstört, und ein neuer Container mit dem neuesten Code wird an seiner Stelle bereitgestellt. Container lassen sich innerhalb von Sekunden oder Millisekunden starten. So können zusätzliche Servicekomponenten sofort nach Bedarf bereitgestellt werden. Aufgrund ihrer geringen Ressourcenanforderungen im Vergleich zu VMs oder Bare Metal sind Container der beste Implementierungsmechanismus für Microservices. Während VMs alle Betriebssystemkomponenten enthalten, enthalten Container nur den Microservice-Code selbst und die zugehörigen Code-Bibliotheken. Weitere benötigte Funktionen werden auf einem gemeinsamen Betriebssystem gemeinsam genutzt, während andere Microservices in Containern ausgeführt werden.
Orchestrierung
Container-Orchestrierungs-Tools gibt es fast so lange wie Container selbst. Tausende von Microservices arbeiten zusammen, um Services und Applikationen zu bilden, und eine manuelle Verwaltung wäre selbst mit einer Armee von Administratoren nahezu unmöglich. Vor dem Hintergrund, dass Budgets für die meisten IT-Abteilungen weiterhin knapp bemessen sind, haben verstärkte Automatisierung, die Einführung von DevOps-Praktiken und der Bedarf an guten Orchestrierungstools oberste Priorität.
Die erste Version von Kubernetes (K8s) wurde 2015 veröffentlicht, kurz nach dem Aufstieg von Docker-Containern, und K8s hat sich schnell zum vorherrschenden Orchestrierungs-Tool in Container-Umgebungen entwickelt. Mit Kubernetes können Entwickler eine Container-basierte Applikation oder einen Microservice in einer gemeinsamen Bibliothek registrieren und dem Kubernetes-Controller eine Manifest-Datei bereitstellen. Kubernetes implementiert die Applikation dann gemäß den Spezifikationen der Manifest-Datei auf seinen Worker-Nodes. Dabei wird das Container-Image in der allgemeinen Registry verwendet.
„Gewünschter Zustand“, ein wichtiges Konzept in Kubernetes, ermöglicht Selbstreparatur und automatische Upgrades als integrale Bestandteile der Lösung. Ein Beispiel: Angenommen, der gewünschte Zustand ist, dass 10 Instanzen eines bestimmten Microservices (in einem Container-Pod) immer in der Version 1.1 ausgeführt werden. Kubernetes überwacht die Implementierung, um diesen gewünschten Zustand zu gewährleisten. Wenn einer der Container ausfällt – und nur 9 ausgeführt werden –, implementiert Kubernetes einen weiteren Container und startet diesen, um den gewünschten Zustand von 10 Instanzen in der Version 1.1 zu erreichen. Wenn das Manifest geändert wird, um Version 1.2 anzugeben, ist für Kubernetes der gewünschte Zustand nicht erfüllt. Daraufhin wird ein paralleles Upgrade aller 10 Instanzen auf Version 1.2 durchgeführt (unter der Annahme, dass Version 1.2 ein verfügbares Image in der Container-Registry ist).
Es wird schnell deutlich, warum Kubernetes im Bereich der Container-Orchestrierung so schnell eine dominierende Rolle eingenommen hat und warum jeder große Public-Cloud-Provider (Amazon Web Services, Microsoft Azure, Google Cloud Platform) über eine eigene Version von Kubernetes verfügt.