Envoy - der Microservice-Proxy

Von: Valentin Brückel
Datum: 28. Januar 2021

Envoy ist ein forwarding und reverse Proxy, der auf den Einsatz in Microservice-Architekturen optimiert ist. Er kann als Edge-Proxy an der Schnittstelle zum öffentlichen Netz und als Sidecar-Proxy in Kubernetes eingesetzt werden.

Das ursprünglich vom Ridesharing-Anbieter Lyft entwickelte Open-Source-Projekt ist inzwischen ein graduiertes Projekt bei der Cloud Native Computing Foundation. Fast alle größeren (amerikanischen) Internet-Konzernen haben den populären Vermittler im Einsatz.

Die Service-Mesh-Lösung Istio und das API-Gateway Gloo verwenden Envoy als Proxy-Komponente für die Steuerung der Kommunikation.

1. Features

Neben TLS-Terminierung, API-Management und Request-Routing bietet Envoy:

  • Load-Balancing (Retries, Rate Limiting, Request Shadowing)
  • Service Discovery und Health Checking
  • Erzeugung von Metriken inklusive eindeutiger Request-IDs
  • vollständige Konfigurierbarkeit über APIs

Der Betrieb des Proxy erfordert nur wenige Megabytes, so dass jedem Microservice z.B. über ein Sidecar-Container eine Envoy-Instanz zur Seite gestellt werden kann. Eingehende und ausgehende Aufrufe der Microservices können über den Envoy geroutet werden, der sich um Routing und Sicherheit kümmert. Die Microservices benötigen kein Wissen über ihre Umgebung und können unverschlüsselt über localhost kommunizieren, der Proxy übernimmt den Rest.

Deployment von Envoy als Sidecar-Proxy

Abbildung : Deployment mehrerer Envoy-Instanzen im Sidecar-Pattern

2. Architektur

Envoy ist ein Proxy mit nativem HTTP/2-Support, der sowohl auf Netzwerk- (Layer 3/4), als auch auf Anwendungsebene (Layer 7) in Datenströme eingreifen kann.

Anstatt mehrere Funktionen wie Authentifizierung oder Logging mit einer Envoy Instanz zur Verfügung zu stellen, kann die Funktionalität auf mehrere Instanzen verteilte werden, die jeweils nur eine Aufgabe übernehmen. Mit diesem Microservice-artigen Muster erzielt Envoy eine bessere Performanz gegenüber einem monolithischen Deployment.

Envoy-Instanzen mit unterschiedlichen Aufgaben

Abbildung : Envoy-Instanzen mit unterschiedlichen Aufgaben

Envoy nutzt ein Threading-Modell mit einem Prozess, in dem ein Haupt-Thread eine Reihe von Worker Threads koordiniert. Es wird vorausgesetzt, dass einem Worker Thread eine eigene CPU bzw. ein eigener Hardware-Thread zur Verfügung steht. Eine TCP-Verbindung wird immer vom selben Thread bedient, bei langlebigen Verbindungen wie z.B. HTTP/2 ist es aus diesem Grund vorteilhaft einzelne Aufgaben auf mehrere hintereinander geschaltete Instanzen aufzuteilen.

Requests durchlaufen eine konfigurierbare Reihe von Filterregeln, die Adressierung und ggf. Änderungen am Inhalt bestimmen. Anfragen können um Daten ergänzt werden, auf die nachgeschaltete Instanzen zugreifen können.

3. Installation

In einem eigenen Repository stehen offizielle Binär-Pakete für Linux und Mac OSX bereit. Ferner existieren offizielle Docker-Images in mehreren Varianten.

4. Konfiguration

Üblicherweise wird Envoy über die Kommandozeile gestartet und erhält dabei eine Basis-Konfiguration im YAML- oder JSON-Format.

Zur weiteren Konfiguration gibt es drei Szenarien:

  • rein statische Konfiguration
  • dynamische Konfiguration über das Dateisystem (löst Neustart aus)
  • dynamische Konfiguration über ein API (wird von Kontrollschichten wie Gloo und Istio genutzt)

5. UI

Envoy stellt eine einfache Web-Oberfläche zur Verfügung, die das API mit allen Status- und Kontrollfunktionen abbildet.

Screenshot der Admin-Seite von Envoy

Abbildung : Screenshot der Admin-Seite von Envoy

6. Vergleich mit nginx

Nginx war über lange Jahre der de-facto Standard-Proxy. Das Open-Source-Produkt ist stabil, ausgereift und leistungsfähig. Allerdings wurde nginx zu einer Zeit entwickelt, als Server-Konfigurationen noch weitgehend statisch waren und Microservice-Architekturen völlig unbekannt. In diesem Kontext war es kein Problem, dass Konfigurations-Änderungen einen Neustart des Proxy erforderten. Die Verbreitung von Orchestrierungs-Lösungen wie Kubernetes änderte diese Voraussetzungen: Mit neuen Features wie Auto-Scaling können Routing-Änderungen im Sekunden-Takt notwendig werden.

Es existieren Lösungen, um nginx dynamisch konfigurierbar machen. Die meisten setzen auf die nginx-Erweiterung OpenResty, über die Lua-Skripte in die Konfiguration integriert werden können.

Im Gegensatz dazu wurde Envoy explizit als schlanker, über API konfigurierbarer Proxy für Microservice-Umgebungen konzipiert. Der geringe Speicherplatzbedarf macht es praktikabel, Envoy als Sidecar in sämtlichen Services einzusetzen. In dieser Konfiguration können die Envoy-Instanzen Aufgabenteilung nach Microservice-Prinzipien betreiben.

Die Performance von nginx und Envoy wird in diversen Benchmarks vergleichen. Dabei liegt Envoy im schlechtesten Fall auf einem ähnlichen Niveau wie nginx. In anderen Szenarien zeigen sich deutliche Vorteile für Envoy.

7. Fazit

Envoy kann seine Stärken am besten in einer Microservices- oder Services-Architektur ausspielen. Er zentralisiert alle Netzwerk-Funktionen wie Service Discovery und Load Balancing und vereinfacht die Administration mit weitestgehender Unabhängigkeit von Sprachen- oder Framework-abhängigen Bibliotheken. Wird Envoy allen Services mitgegeben, ermöglicht er umfangreiches sowie konsistentes Monitoring und die Nachverfolgung von Aufrufen (Tracing).

Zuletzt stellt sich die Frage, ob Envoy als eingenständiges Projekt oder als Bestandteil einer umfassenderen Lösung z.B. mit dem ServiceMesh Istio eingesetzt wird.

8. Links