Service Meshes: Einführung und Kurzvergleich von Istio und Linkerd

Von: Valentin Brückel
Datum: 7. Oktober 2019

Microservice-Architekturen erkaufen ihre Vorteile durch einen hohen Verwaltungsaufwand. Orchestration-Lösungen wie Kubernetes vereinfachen den Betrieb, benötigen jedoch Konfigurationsdaten, deren Komplexität mit der Anzahl der Microservices wächst. Szenarien wie der schrittweise Austausch von Versionen, die durch Orchestration erstmals praktikabel erscheinen, bringen einen beträchtlichen Administrations-Aufwand mit sich.

Ein Service Mesh verwaltet die Netzwerkverbindungen in containerisierten Umgebungen (typischerweise auf Kubernetes). Das Routing lässt sich dadurch flexibel anpassen und je nach Bedarf im laufenden Betrieb auf andere Services oder andere Versionen des gleichen Service umschalten.

Funktionsweise

Service-Mesh-Lösungen wie Istio und Linkerd haben alle gemeinsam, dass sie in einer vorhandenen Umgebung einen TCP-Proxy in jeden aktiven Dienst injezieren. Während ein Proxy normalerweise clientseitig oder (als Reverse Proxy) serverseitig eingesetzt wird, um als Relaisstation zur Außenwelt zu dienen, die Informationen zwischenspeichert, Interna verbirgt, und möglicherweise Daten filtert oder manipuliert, ist die Funktion im Mesh zweiseitig: Die Proxys hängen als "Beiwagen" (Sidecar) an jedem Dienst und übernehmen den gesamten Netzwerkverkehr. Das Mesh vernetzt also nicht mehr Dienste, sondern ihre Proxys.

Serivce Mesh

Abbildung : Funktionsschema eines Service Mesh

Oft werden zusätzliche eigenständige Proxy-Server als Gateway eingesetzt, die den in das Mesh ein- und ausbrechenden Datenverkehr steuern. Durch die zentrale Konfiguration der Sidecar-Proxys von der Kontrollschicht aus lässt sich der Datenverkehr innerhalb des Mesh komplett kontrollieren, wobei das Service-Mesh für die Dienste im Mesh unsichtbar bleibt und in deren Entwicklung nicht gesondert berücksichtigt werden muss.

Features

Traffic Management

Prinzipbedingt ermöglichen Service Meshes die vollständige Kontrolle über alle Datenströme und können bestimmen, wer welche Services oder die Außenwelt erreicht.

  • Routing: Datenverkehr kann in Abhängigkeit von definierbaren Regeln an unterschiedliche Services geroutet werden
  • Versionierung: Verwaltung verschiedener Versionen eines Services
  • Canary-Pattern: Bestimmten Anteile des Traffic an eine neue Version schicken, um deren Verhalten unter Realbedingungen zu beobachten, bevor auf alle Instanzen ausgerollt wird
  • A/B-Testing: Traffic auf unterschiedliche Versionen verteilen und deren Verhalten oder die Reation der Nutzer zu beobachten
  • Mirroring: Eine Kopie des realen Traffic (oder eines Teils davon) kann an weitere Dienste geleitet werden, z.B. zum Logging oder in eine Entwicklungsumgebung
  • Blue/Green Deployment: Zentrales Umschalten des gesamten Traffic auf ein anderes Deployment
  • Replication: Einige Service-Meshes erlauben zusätzlich die Verteilung des Traffic zwischen Instanzen in unterschiedlichen Netzen z.B. anderen Rechenzentren.

Security

Die Möglichkeit, über die Proxys in die Inhalte der Datenströme einzugreifen, erleichtert die zentrale Implementierung von Sicherheits-Features.

  • Authentication: Die Proxy-Server können zentral mit Zertifikaten versorgt werden, dadurch können sie in der Kommunikation untereinander ihre Identität prüfen
  • Encryption: Transportverschlüsselung wird durch das Proxy-Konzept erst wirklich prakitabel, da sie so zentral eingerichtet und umgesetzt werden kann, anstatt Anforderungen an jeden einzelnen Dienst zu stellen

Monitioring

Die Proxy-Server protokollieren den Traffic und erstellen umfangreiche Metriken. Monitoring-Tools wie Prometheus und Grafana werden von vielen Service-Mesh-Lösungen bereits in der Standardinstallation mitgeliefert, so dass sie nicht gesondert installiert und eingerichtet werden müssen.

Performance

Jede Service-Mesh-Lösung bringt Performance-Verluste gegenüber "reinen" Konfigurationen mit sich. Jeder Datenverkehr eines Services muss zusätzlich zwei Proxys durchlaufen - eingehend und ausgehend - was zwangsläufig die Latenz verlängert. Die eingesetzten Proxys sind hochoptimiert und erledigen beispielsweise Monitoring/Logging erst, nachdem sie den Traffic bereits weitergleitet haben. Dennoch bleibt eine Verzögerung messbar. Durch das Monitoring entsteht eine weitere geringe Verzögerung, bis der nächste Datenstrom verarbeitet werden kann, wodurch insgesamt auch der Durchsatz leicht sinkt.

Diese Performance-Verluste sind normalerweise gering, sollten aber beachtet werden.

Service-Mesh-Lösungen

Die populärsten Service-Mesh-Lösungen sind Istio und Linkerd:

Linkerd

Der Begriff "Service Mesh" wurde durch Linkerd geprägt, das erstmals 2016 von Buoyant veröffentlicht wurde. Ursprünglich war Linkerd in der JVM-Sprache Scala geschrieben und stand im Ruf, speicherhungrig zu sein. In der Folge entstand das Conduit-Projekt, das eine rein auf Kubernetes optimierte Version von Linkerd in Rust und Go implementierte und 2018 als Linkerd 2.0 veröffentlichte. In der Folge werden wir uns auf Linkerd 2.x konzentrieren.

Istio

Istio entstammmt einer Kooperation von Lyft, Google und IBM. Es erreichte nach einer einjährigen Entwicklungsphase 2018 die Version 1.0. Die in Go geschrieben Kernkomponenten setzen auf dem von Lyft stammenden C++ Proxy Envoy auf. Obwohl Istio stark auf das Zusammenspiel mit Kubernetes und Envoy ausgerichtet ist, werden auch andere Orchestration-Lösungen und Proxy-Server unterstützt.

Vergleich von Istio und Linkerd

Istio Linkerd
Initiatoren Lyft, Google, IBM Buoyant, Cloud Native Foundation
Lizenz Apache 2.0 Apache 2.0
Github-Sterne (10/2019) 19.8k 4.6k (Linkerd 1.x: 5.1k)
Sprachen Go, C++ Rust, Go
Proxy Envoy (oder API-kompatibel) intern
Umgebung Kubernetes, Consul/Nomad, Cloud Foundry, VMs Kubernetes

Im direkten Vergleich zeigt sich, dass Istio deutlich mehr Features bietet und flexibler ist als Linkerd. Linkerd punktet dagegen durch klar bessere Performance und komfortablere Einrichtung inklusive eines Webinterfaces.

Fazit

Ein Service Mesh ist eine zusätzliche Abstraktionsebene in Micorservice-Umgebungen, die die Administration vereinfachen und Flexibilität im Betrieb ermöglichen kann. Dem gegenüber steht die zusätzliche Komplexität. Ein Einsatz kann sinnvoll sein, ist es aber in längst nicht jedem Fall. Vorteile scheinen sich vor allem in Umgebungen mit erheblicher Netzwerklast und einer Vielzahl von Microservices zu ergeben, insbesondere wenn häufig zwischen Versionen einzelner Services migriert werden soll oder wenn Features wie Transportverschlüsselung ausgerollt werden müssen.