Service Meshes mit Istio machen Microservices beherrschbar
Von: Valentin Brückel
Datum: 20. Dez. 2019
Abbildung :
1. Was ist ein Service Mesh?
Ein Service Mesh ist ein Geflecht von Services, die über das Netzwerk miteinander kommunizieren und gemeinschaftlich eine Aufgabe erfüllen. Service-Mesh-Lösungen übernehmen in diesem Geflecht mittels Proxy-Servern die Kontrolle über die Datenströme. Konfiguriert und kontrolliert werden die Proxys von einer separaten Kontrollschicht. Etabliert wurde der Begriff Service Mesh 2016 durch Linkerd und später Istio, in jüngster Zeit erscheinen weitere Produkte oder werden um Service-Mesh-Fähigkeiten ergänzt, beispielsweise Consul, AWS App Mesh, Mæsh und Kuma.
2. Einsatzfelder
Istio ermöglicht die Zentralisierung von Verwaltungsaufgaben in einer Microservice-Architektur. Das vereinfacht insbesondere:
- Die Durchsetzung von Sicherheits-Richtlinien (Transportverschlüsselung, Zugangsbeschränkungen)
- Das Versions-Management (Rollout, A/B-Testing, Fallback-Lösungen)
- Das Monitoring (Metriken, Logging, Tracing)
- Das Routing
Das Gesamtsystem aus einzelnen Services kann dynamisch zur Laufzeit konfiguriert werden, ohne dass Änderungen an den Services notwendig sind.
3. Architektur
Istio setzt auf einer Orchestrierungs-Lösung auf, die die eigentlichen Services verwaltet. Typischerweise ist dies Kubernetes, aber offiziell werden auch andere Alternativen unterstützt. Kubernetes übernimmt in einer Istio-Installation zusätzlich zu seinen übrigen Aufgaben auch die Verknüpfung der Istio-Komponenten mit den Microservices mittels automatischer Pod-Injection bzw. Sidecar Injection.
3.1 Sidecar Injection
Kubernetes verwaltet Services in Form von Pods (Kapseln), in denen typischerweise ein Service mit einem oder wenigen Docker-Containern zusammengefasst ist. Die Pods baut Kubernetes nach Standardrezepten aus vorgegebenen Images zusammen. Im Grundzustand tut ein Pod nicht viel mehr, als den oder die Container zu überwachen und bei Absturz neu zu starten und ansonsten allen Netzwerkverkehr durchzureichen.
Abbildung :
Istio verändert die Pod-Baupläne von Kubernetes derart, dass neben dem eigentlichen Service ein weiterer Container mit dem Proxy-Server als Sidecar (Beiwagen) eingebaut wird. Zusätzlich wird ein spezieller Init-Container definiert. Ein Init-Container wird von Kubernetes beim Start des Pods ausgeführt und muss sich selbst beendet haben, bevor die restlichen Container gestartet werden. Einzige Aufgabe des Init-Containers von Istio ist es, die Firewall-Regeln des Pods so umzukonfigurieren, dass der gesamte ein- und ausgehende Datenverkehr über den Proxy läuft.
Abbildung :
Der Proxy kommuniziert seinerseits mit der Istio-Kontrollschicht und ist dadurch jederzeit in der Lage, sein Verhalten während der Laufzeit anzupassen.
Neuere Istio-Versionen unterstützen optional ein Alternativverfahren über das Container Network Interface, das den Bedenken mancher Unternehmen mit restriktiven Prozessen Rechnung trägt, die es als problematisch ansehen, dass der InitContainer im Pod Admin-Rechte benötigt.
3.2 Komponenten
Arbeitspferd von Istio ist der Proxy-Server Envoy, der vollautomatisch als fertig konfigurierter Container an jeden einzelnen Service angehängt wird. Dort fängt Envoy den gesamten Datenverkehr ab und behandelt ihn entsprechend seiner Konfiguration.
Der Mixer wird von den Proxys bei jeder Aktion kontaktiert. Er prüft, ob alle Bedingungen zur korrekten Bearbeitung erfüllt sind, sammelt Telemetrie-Daten und stellt eine Schnittstelle für weitere Module (Adapter) bereit, die in die Verarbeitung einbezogen werden sollen.
Eingesetzt und gesteuert werden die Proxy-Server vom Pilot, der die abstrakte Systembeschreibung der Konfigurationsdateien in konkrete Regeln übersetzt. Dies ermöglicht unter anderem Service Discovery, also die Adressierung der Services untereinander, Intelligentes Routing in Abhängigkeit von konfigurierbaren Regeln und steigert die Ausfallsicherheit, indem bei Problemen Datenverkehr auf vereinfachte (statische) Ersatz-Dienste oder ältere, bekanntermaßen funktionierende Versionen oder auf komplett andere Cluster umgeleitet werden können.
Die Sicherheits-Komponente Citadel verwaltet Identitäten und Zertifikate. Sie ermöglicht Authentifizierung von Services und Usern, Zugriffskontrolle auf Services und TLS-Verschlüsselung des Datenverkehrs.
Die Konfiguration des Gesamtsystems wird durch Galley verwaltet. Galley stellt die Schnittstelle zwischen den Istio-Komponenten und der darunter liegenden Plattform, in der Regel Kubernetes, dar.
Abbildung :
4. Traffic Management
Istio setzt auf der Netzwerkebene auf und ermöglicht dort die Lenkung von Datenströmen. Interessant ist diese Möglichkeit vor allem, wenn unterschiedliche Versionen der Services im Einsatz sind. So kann ein bestimmter Prozentsatz des Datenverkehrs an eine neue Version geleitet werden, um die Funktionsfähigkeit zu prüfen oder Änderungen im Nutzerverhalten zu beobachten. Ebenso können Anfragen aus bestimmten Regionen oder von angemeldeten Benutzern an angepasste Services geleitet werden. Auch können vollständige Kopien von Datenströmen an Hintergrunddienste, etwa zu Logging-Zwecken, weitergeleitet oder bei Bedarf vollständig auf ein anderes Cluster beispielsweise in einem anderen Rechenzentrum umgeleitet werden. Die folgenden Diagramme zeigen die Lenkung der Datenströme am Beispiel eines Canary Deployment auf. Bei einem Canary Deployment werden zunächst die alte und die neue Version eines Service parallel betrieben, um einen Schaden bei einer fehlerhaften neuen Version zu begrenzen.
Beispiel Canary-Deployment: Ein bestehendes Service Mesh wird mit einer neuen Version eines Service versehen. Der Traffic läuft weiter zur alten Version.
Beispiel Canary-Deployment: Die neue Version wird zunächst mit einem geringen Anteil des realen Traffic belastet
Beispiel Canary-Deployment: Nach einem Funktionstest übernimmt die neue Version alle Aufgaben
5. Sicherheit
Die Gewährleistung eines vorgegebenen Sicherheitsniveaus in Microservice-Architekturen ist eine komplexe Aufgabe, da sämtliche Komponenten betrachtet werden müssen und ein Sicherheitskonzept umgekehrt in jedem einzelnen Service berücksichtigt werden muss.
Istio sitzt auf der Netzwerkebene, vorgelagert zu den Services und bleibt für diese unsichtbar. An dieser zentralen Stelle ist es möglich
- Transportverschlüsselung
- Prüfung und Verteilung von Zertifikaten und Identitäten (Authentication)
Zugriffskontrolle (Authorization)
für alle Services umzusetzen.
Aus Sicht eines Microservices kann dieser im Klartext kommunizieren, der Datenstrom kann aber vom Proxy noch vor Verlassen des Kubernetes-Pods abgefangen und verschlüsselt werden. Ebenso kann Istio durchsetzen, dass Microservices nur von außen erreichbar sind, wenn die Anfrage von einem Berechtigten stammt.
6. Observability - Überwachungs- und Auswertungsfunktionen
Die Proxy-Server melden jeden einzelnen Aufruf zur Protokollierung an die Kontrollschicht. So steht der gesamte Datenverkehr für Auswertungen zur Verfügung. In der Standard-Konfiguration von Istio sind zur Auswertung bereits die Monitoring-Lösung Prometheus, das graphische Dashboard Grafana und die Analyse-Lösung Kiali enthalten und vorkonfiguriert.
Abbildung :
Die ebenfalls vorkonfigurierten Tracing-Lösungen Jaeger und Zipkin ermöglichen detailliertere Auswertungen. In diesem Fall sind Anpassungen an den Microservices notwendig, damit HTTP-Header von eingehenden Requests an nachgelagerte Dienste weitergereicht werden (Header Propagation), anhand derer Kausalverbindungen zwischen Datenströmen nachvollzogen werden können.
7. Installation
Obwohl Istio ausdrücklich andere Konfigurationen als Kubernetes ermöglicht, ist eine Kubernetes-basierte Installation der De-Facto-Standard. Für eine lokale Testumgebung empfiehlt sich Minikube. Sofern Minikube bereits eingerichtet ist, beschränkt sich die Installation von Istio auf wenige Zeilen auf der Konsole. Je nach Leistungsfähigkeit der eingesetzten Hardware ist Istio nach wenigen Minuten einsatzbereit.
Zur eigentlichen Installation wird Istio in ein lokales Verzeichnis geladen und über die Kommandozeile mit kubectl
mit Kubernetes verknüpft.
Anschließend besteht die Möglichkeit, Kubernetes so zu konfigurieren, dass Istio in einem beliebigen Namespace in alle Pods injiziert wird.
8. Abgrenzung
Service-Mesh-Lösungen wie Istio ermöglichen die zentrale, flexible Verwaltung von Microservices und erhalten die Kernvorteile von Microservice-Architekturen. Jeder Microservice kann weitgehend frei von technischen Schulden entworfen werden. Ein Service benötigt nur minimales Wissen von seiner Umgebung. Sicherheitseinstellungen, neue Versionen und Load Balancing können zentral konfiguriert werden, ohne dass ein einzelner Service davon Kenntnis erlangen muss.
Microservices in einer Service-Mesh-Umgebung sind naturgemäß polyglott: Technisch ist ein Service ausschließlich durch seine definierten Schnittstellen festgelegt, die Implementierung kann für jeden Anwendungsfall in der jeweils effizientesten Programmiersprache erfolgen. Wegen der sauberen Trennung von Kontroll- und Datenschicht muss sich kein Microservice um Verwaltungsaufgaben wie Load Balancing, Service Discovery und Retries/Fallback-Lösungen kümmern.
Dies steht im Gegensatz zu "Microservice"-Lösungen aus der Java-Welt, die die notwendigen Komponenten in jeden Service einbauen und Entwickler zwingen, ausschließlich Java zu verwenden. In einem Service Mesh ist jedes native Programm Cloud-fähig, ohne dass aufwendige Frameworks wie Spring Boot/Cloud oder das MicroProfile eingebunden werden müsste, weil deren Aufgaben zentral und von der Anwendungslogik getrennt auf der Netzwerkebene erledigt werden.
9. Fazit
Istio ist ein mächtiges Werkzeug zur Verwaltung von Microservices, insbesondere zum Aufsetzen von Transportverschlüsselung und bei der Migration von Services auf neue Versionen.
Seine Stärken kann es vor allem dann ausspielen, wenn bereits eine Kubernetes-Umgebung vorhanden und eingerichtet ist. In diesem Fall beschränkt sich die Installation auf das Einspielen einiger Konfigurationsdateien mit kubectl und das Hinzufügen einiger weniger Zeilen zur Cluster-Konfiguration. Alle weiteren Schritte wie die Installation und Konfiguration der Proxy-Server in allen existierenden und zukünftigen Pods kann Istio dann automatisch übernehmen.
Für Service Meshes und Istio spricht auch die Unabhängigkeit von Entwicklungsplattformen. Es spielt keine Rolle, ob ein Service mit Java, .Net oder Python realisiert ist.
Der Einarbeitungsaufwand hängt stark davon ab, ob bereits Kubernetes-Kenntnisse vorhanden sind. Ist das der Fall, so kann in Minuten ein funktionsfähiges Beispiel eingerichtet und innerhalb von wenigen Stunden ein umfassendes Grundverständnis erlangt werden. Wird dagegen noch kein Kubernetes eingesetzt, dann ist mit dem Einsatz von Istio eine steile Lernkurve verbunden, weshalb in diesen Fällen kritisch abgewogen werden muss, ob die Vorteile den Mehraufwand rechtfertigen.
Im Vergleich zu einer händisch konfigurierten Kubernetes-Umgebung bekommen die Vorteile eines Istio-Service Mesh vor allem mit steigender Komplexität des Systems Gewicht. Wenn nur ein oder zwei Services eingesetzt werden, ist der Mehraufwand durch Istio schwer zu rechtfertigen, während in komplexen Microservice-Geflechten klare Vorteile bestehen. Es ist absehbar, dass sich die Grenze, ab der ein Einsatz von Istio lohnt, mit zunehmender Reife von Istio und seiner Administrations-Werkzeuge zukünftig nach unten verschieben wird.