Unterwegs im Sidecar – Wann lohnt sich der Einsatz eines Service Mesh?

Ein Service Mesh ist ein vielversprechender Ansatz, die gesteigerte Kommunikation und Komplexität in Microservices-Architekturen durch eine dedizierte Infrastrukturschicht unter Kontrolle zu bekommen.

In immer mehr neuen Softwaresystemen oder bei der Ablösung bzw. dem Refactoring veralteter Architekturen kommen Microservices zum Einsatz. Mit dem Ansatz wird eine lose Kopplung von Modulen erreicht und die Geschwindigkeit und Flexibilität der Bereitstellung von Software erheblich verbessert. Für unterschiedliche fachliche Aufgaben kommen dabei meist separate Services zum Einsatz, die größtenteils unabhängig voneinander durch interdisziplinäre Teams entwickelt werden. Beim Betrieb des Systems ist es dadurch zum Beispiel möglich, die Instanzen unabhängig voneinander zu skalieren, um die geforderte Performance gezielt bereitstellen zu können. Bei der Ablösung von Altsystemen können einzelne Module Step by Step abgelöst werden, ohne der Gefahr eines Big Bang Release und den damit verbundenen Herausforderungen und Risiken ausgesetzt zu sein.

Neben den genannten Vorzügen hat der Ansatz aber auch Nachteile: Die Kommunikation und betriebliche Komplexität werden stark erhöht. In jedem Service müssen Funktionen wie Monitoring oder Resilienz gelöst werden. Es wandern mehr Aufgaben, die in monolithischen Architekturansätzen beim Betrieb verortet sind, in die Entwicklungsteams, die sich dadurch weniger der Entwicklung der eigentlichen Fachlichkeit widmen können.

Eine Möglichkeit, um diese Aufgaben innerhalb eines Microservice zu lösen, können spezifische Frameworks sein. Ein bekanntes und verbreitetes Beispiel aus der Java-Welt ist Spring Cloud. Das Framework bringt einige Funktionen für Standardprobleme mit, etwa für Service Discovery und Circuit Breaking. Da die Implementierung dieses Frameworks selbst in Java erfolgt, geht der Vorteil der Technologieunabhängigkeit, den Microservices bringen, jedoch wieder verloren. Ist für die Lösung eines speziellen Problems eine andere Technologie die bessere, ist man trotzdem durch das Framework beschränkt oder muss, wenn vorhanden, ein zusätzliches Framework verwenden.

Die Nachteile der technologieabhängigen Frameworks und der weiterhin anhaltende Trend zu Microservices haben zur Entstehung von sogenannten Service Meshes geführt. Es handelt sich hierbei um einen vielversprechenden Ansatz, der durch Einführung einer dedizierten Infrastrukturschicht zur Minderung der genannten Probleme führt.

Aufbau eines Service Mesh

Der grundlegende Aufbau eines Service Mesh besteht aus zwei Komponenten: einer Control Plane und einer Data Plane. Abbildung 1 zeigt den Aufbau der beiden Komponenten und eine Gegenüberstellung zu einem Entwurf ohne Service Mesh.

wies_servicemesh_1.tif_fmt1.jpgAbb. 1: Gegenüberstellung Microservices und zusätzliches Service Mesh (Quelle: https://servicemesh.es)

Innerhalb der Data Plane werden neben jedem Fachdienst sogenannte Sidecars bereitgestellt, die als Proxys agieren. Funktionen, die jeder Dienst benötigt, werden dabei in einen zusätzlichen Container (das Sidecar) ex-trahiert. Die Services kommunizieren bei diesem Pattern nicht direkt untereinander, die Kommunikation findet immer über das Sidecar statt, das dann die weitere Kommunikation mit anderen Sidecars oder der Control Plane steuert.

In der zweiten Komponente, der Control Plane, erfolgt die Konfiguration der Service Proxies. Ist eine Änderung des Verhaltens des Service Mesh nötig, wird das zentral konfiguriert, auf die Control Plane angewendet und automatisch an die Service Proxies verteilt. Eine zusätzliche Funktion ist die Verarbeitung von Metriken, die durch die Service Proxies erfasst und an die Control Plane weitergeleitet werden. Je nach genutzter Lösung können die empfangenen Daten anschließend über vorgefertigte Dashboards dargestellt und überwacht werden.

Funktionen des Service Mesh

Wie bereits dargestellt, haben in einer verteilten Microservices-Architektur Monitoring, Resilienz sowie Routing und Securityaspekte eine besonders große Relevanz. Inwiefern hier ein Service Mesh helfen kann, wird nachfolgend genauer beschrieben.

Monitoring: In einer auf Microservices basierenden Architektur sollte es ein zentrales Monitoring geben, das Informationen von allen Services sammelt und zentral bereitstellt. Dadurch ist es beispielsweise möglich, Alarmfunktionen zu implementieren, die in Fehlerfällen automatisch auf die Probleme aufmerksam machen. Innerhalb der Data Plane messen hierfür die Service Proxies grundlegende Informationen, wie z. B. die Latenz und den Durchsatz. Weiterhin können Daten, die etwa die Kommunikationsprotokolle betreffen, analysiert werden. Findet eine synchrone Kommunikation über HTTP statt, können beispielsweise die Status Codes verarbeitet und analysiert werden, um basierend darauf z. B. Fehlerraten darzustellen.

Mit den Metriken ist es zudem möglich, die Zuverlässigkeit und Performance eines Systems darzustellen. Gegenüber Kunden kann das beispielsweise die Einhaltung von Service Level Agreements bestätigen. Dadurch, dass das Service Mesh diese Funktion übernimmt, bleibt der Code der Fachdienste unberührt und jeder Service liefert unabhängig von der gewählten Technologie die gleichen Daten.

Allerdings gibt es auch Limitierungen. Für das Mesh ist der eigentliche Service eine Blackbox. Er kann zwar Metriken bezüglich der ein- und ausgehenden Requests liefern, interne Infos aber, etwa über Threads oder Datenbankverbindungen, kennt nur der Service selbst. Dadurch sind Service Meshes auch nur bedingt für die Funktion des Tracings nützlich. Mittels Tracing sollen die Routen innerhalb einer Microservices-Architektur nachvollzogen werden können. Es soll also aufgezeigt werden, dass beispielsweise ein eingehender Request A einen ausgehenden Request B verursacht. Um diese Kette darzustellen, benötigt das Service Mesh Informationen aus dem Dienst, es muss also eine eindeutige ID mitgeführt werden, wodurch eine Anpassung direkt im Fachdienst nötig ist. Beim Tracing kann ein Service Mesh somit zwar helfen, es ist aber nicht komplett eigenständig möglich.

Resilienz: In einer Microservices-Architektur versteht man unter Resilienz die Fähigkeit des Gesamtsystems, auch bei Nichtverfügbarkeit oder Ausfall einzelner Services weiter zu funktionieren bzw. zumindest kontrolliert mit dem Problem umgehen zu können. Im Falle von asynchroner Kommunikation, also beispielsweise dem Datenaustausch per Messaging, übernimmt die Messagingplattform große Teile dieser Aufgabe, da sie sozusagen als Puffer zwischen den Services dient und Nachrichten bis zur erneuten Verfügbarkeit eines Zielservices vorhält.

Im Falle eines synchronen Nachrichtenaustauschs, zum Beispiel über REST APIs mittels HTTP, kommen hierfür in Microservices-Architekturen meist sogenannte Circuit Breaker zum Einsatz. Steht ein Zielservice aktuell unter sehr hoher Last oder gibt es ein temporäres Problem, wird die Kommunikation unterbrochen. Der Ansatz ist vergleichbar mit einer Sicherung in einem Stromkreislauf, die der Namensgeber für dieses Pattern ist.

Die Dauer der Unterbrechung kann konfiguriert werden und nach ihrem Ablauf werden in bestimmten Zyklen Retries durchgeführt. War die Störung nur vorrübergehend, wird das System dadurch wieder in einen stabilen Zustand zurückgeführt. Zu häufige Retrieskönnen das System aber auch unter noch mehr Last setzen. Die Konfiguration muss somit sehr feingranular durchgeführt werden und auf die fachlichen Szenarien zugeschnitten sein.

Da in einem Service Mesh die Kommunikation immer über den Service Proxy bzw. das Sidecar läuft, kann dieser die genannten Aufgaben übernehmen, ohne Anpassungen im Fach-Service-Code vornehmen zu müssen. Besonders im Falle unterschiedlicher Technologien besteht der Vorteil darin, keine verschiedenen Frameworks einsetzen zu müssen.

Routing: In jedem auf Microservices aufgebautem System muss es ein Regelwerk für das Routing geben, also eine bestimmte Anzahl von Definitionen, wie die Services untereinander kommunizieren oder wie Anfragen von außerhalb behandelt werden.

In einem Service Mesh können diese Routingregeln zentral über die Control Plane an die Service Proxies verteilt werden. Mit den Definitionen ist es möglich, zu bestimmen, welche Services basierend auf HTTP-Metadaten angesprochen werden sollen. Dabei sind folgende Szenarien möglich:

  • Anfragen von Nutzern aus Land A werden an Service B geleitet, alle anderen weiterhin an Service A

  • sende generell 10 Prozent der Requests an Service A, 90 Prozent an Service B

  • sende Anfragen von Endnutzern eines bezahlten Premiumabonnements an Service B, mit Standardabonnement an Service A

Bei einer großen Anzahl von Services und einem regelmäßigem Deployen in die Produktionsumgebung – wie es etwa in agilen Vorgehensmodellen angestrebt wird – kann das auch bei sogenannten Canary Releases helfen. Dabei wird ein neu deployter Dienst oder eine neue Version zunächst nur mit einem Bruchteil von Requests angesprochen. Stellt sich heraus, dass das stabil läuft und die gewünschte Funktionalität wie erwartet bereitsteht, wird der Traffic sukzessive erhöht bis ausschließlich der neue Service im Einsatz ist.

Security: In einem verteilten System ist es wichtig, nicht nur die Eintrittspunkte in das Netzwerk, sondern auch die Kommunikation der Services untereinander entsprechend abzusichern. Welcher Service worauf zugreifen darf oder welcher Endnutzer welche Berechtigungen hat sind hier nur zwei Fragen von vielen, die es in diesem Themenkomplex zu beantworten gilt.

Die Control Plane eines Service Mesh kann hier helfen und Zertifikate an die Proxys verteilen und diese in regelmäßigen Abständen automatisiert aktualisieren, wodurch eine beidseitige Authentifizierung umgesetzt werden kann. Zur Aktivierung genügt oft das Hinzufügen einer einzigen Konfigurationszeile.

Eine Form der Autorisierung kann durch übermittelte Tokens – zum Beispiel JSON Web Tokens, die den HTTP Requests angehängt sind – realisiert werden. Die Proxys können die Tokens überprüfen und basierend darauf die Berechtigungen steuern.

LUST AUF NOCH MEHR API-TRENDS?

Entdecke Workshops vom 25. - 27. November 2024

Marktüberblick

Obwohl einige gestartete Projekte mittlerweile nicht mehr existieren, ist die Liste von Lösungen, die zur Realisierung eines Services Mesh eingesetzt werden können, lang. Bevor ein Anbieter gewählt wird, sollte man sich intensiv damit beschäftigen, wie die aktuelle Architektur aufgebaut ist, welche der Features eines Service Mesh man nutzen möchte und welche dabei den meisten Mehrwert bieten.

Zwei Projekte aus den Anfängen, die auch heute noch bestehen und mit zu den prominentesten Kandidaten gehören, sind Istio und Linkerd. Letzteres ist inzwischen in Version 2 erschienen, für die ein vollständiger Rewrite erfolgte.

Hinter dem Projekt Linkerd steckt das Unternehmen Buoyant. Die beiden Gründer sind ehemalige Mitarbeiter von Twitter. Linkerd war das erste Produkt, das ein Service Mesh implementierte und somit den Begriff definiert hat.

Istio entstand 2018 aus einer Kooperation von Lyft, Google und IBM. Es ist eine der flexibelsten und vollständigsten Lösungen, die für alle Unternehmensgrößen und Softwarelandschaften geeignet ist.

Beide Frameworks haben Vor- und Nachteile. Istio bietet den größeren Funktionsumfang und eine höhere Konfigurierbarkeit, benötigt allerdings mehr Ressourcen, was sich auf die Performance auswirkt. Aus der Community kommen zudem immer wieder Stimmen, Istio sei zu kompliziert und umständlich und die Einarbeitungshürde falle eher hoch aus.

Beim Einsatz von Linkerd ist man auf Kubernetes als Orchestrierungsplattform beschränkt, Istio hingegen bietet an dieser Stelle mehr Möglichkeiten.

Weiterhin gibt es den interessanten Ansatz des Service Mesh Interface (SMI). Das ist keine direkte Implementierung, sondern ein Ansatz, die zentralen Funktionen eines auf Basis von Kubernetes betriebenen Services Mesh über ein standardisiertes API nutzen zu können. Das API wird vollumfänglich von Istio und dem Open Service Mesh von Microsoft supportet. Wird gegen das API implementiert, kann bei Wechsel des implementierenden Frameworks die Konfiguration beibehalten werden, da diese standardisiert ist.

Das Open Service Mesh von Microsoft ist ein Open-Source-Projekt, das unter der Kontrolle der Cloud Native Computing Foundation (CNCF) steht. Anders als Istio, das von Google nicht an die CNCF übergeben wurde, befinden sich Kubernetes und das Open Service Mesh also innerhalb der Kontrolle der CNCF, die dadurch natürlich den Anspruch hat, die beiden Projekte sehr gut zu integrieren.

Am Ende muss je nach Projektkontext, vorhandener Systemlandschaft und Funktionalität, die das Mesh abdecken soll, entschieden werden. Folgende Leitfragen können bei der Wahl unterstützen:

  • Wie hoch ist die Anzahl der betriebenen Services? Bei weniger als zehn entsteht vermutlich durch den Einsatz eines Service Mesh mehr Overhead als Nutzen.

  • Wird aktuell Kubernetes oder eine andere Orches-trierungsplattform eingesetzt? Wird kein Kubernetes eingesetzt, ist die Auswahl möglicher Frameworks sehr viel kleiner.

  • Wie hoch ist aktuell die Technologievielfalt? Sind zum Beispiel alle Services mit Java implementiert, können Service-interne Libraries die bessere Wahl sein.

  • Welches Wissen ist vorhanden und wie sind meine Ressourcen ausgelastet? Durch den Einsatz eines Service Mesh wird die Komplexität erhöht. Sie muss sowohl mental als auch vom Aufwand her beherrschbar sein.

Zusammenfassung: Wann ist der Einsatz sinnvoll?

Wie ist der Einsatz eines Service Mesh abschließend also zu beurteilen – als überbewerteter Hype oder sinnvolle Erleichterung im Entwickleralltag?

In Umgebungen mit vielen Services – als grober Richtwert mehr als zehn –, vielen unterschiedlichen Technologien und viel synchroner Kommunikation kann der Mehrwert das initiale Set-up durchaus überwiegen. Besonders bei höheren Aufruftiefen, also wenn an einer fachlichen Aktion mehrere Services beteiligt sind, kann der Einsatz dem Team die Fehlersuche erheblich erleichtern.

Gibt es außerdem bisher ungelöste Probleme, etwa in Bezug auf Monitoring und Resilienz, und lassen sich diese nicht mit Libraries lösen oder wären aufgrund der Technologievielfalt zu viele unterschiedliche nötig, kann der Einsatz ebenfalls sinnvoll sein. Zu berücksichtigen ist jedoch die Performance des Systems, da der Einsatz immer zu höheren Latenzen führt.

Ergibt sich aus den aufgeführten Abwägungen, dass ein Einsatz erstrebenswert ist, sollten außerdem das initiale Set-up und die Ressourcen, vor allem auch in Form von Mitarbeitern, nicht unterschätzt werden. Wichtig dabei ist auch die Beschaffung des nötigen Know-hows, da eine neue Technologie auch immer eine mentale Hürde ist.

Top Articles About Domain-driven Design

Nichts mehr verpassen!