Das Sidecar-Muster: Microservices erweitern, ohne Code zu ändern

Das Sidecar-Muster: Microservices erweitern, ohne Code zu ändern

In modernen Cloud-nativen Systemen wird von Microservices viel mehr erwartet, als nur Geschäftslogik auszuführen. Sie müssen sich um die Protokollierung kümmern, SSL/TLS-Zertifikate verwalten, Metriken sammeln, Wiederholungsmechanismen implementieren und sichere Kommunikation mit anderen Diensten koordinieren.

Wenn wir all diese übergreifenden Funktionen direkt in die Codebasis jeder Anwendung einbetten, kommt es zu Code-Aufblähung, enger Kopplung und Sprachbindung.

Hier kommt das Sidecar-Muster ins Spiel. In diesem Leitfaden erklären wir anhand einfacher Analogien und Kubernetes-Konfigurationsbeispiele, was das Sidecar-Muster ist, warum es für moderne Microservice-Architekturen unerlässlich ist und wie es funktioniert.


Die Analogie zur realen Welt: Der Motorrad-Beiwagen

Der einfachste Weg, dieses Muster zu verstehen, besteht darin, sich ein Motorrad mit Beiwagen vorzustellen.

Sidecar-Muster-Architekturdiagramm, das Anwendungs- und Sidecar-Container in einem Pod zeigt

Stellen Sie sich vor, Sie haben ein Hochleistungsmotorrad. Es ist darauf ausgelegt, eines besonders gut zu können: einen Fahrer schnell zu transportieren. Angenommen, Sie müssen Passagiergepäck befördern oder einen zusätzlichen Sitzplatz hinzufügen.

Sie könnten den Rahmen, den Motor und die Räder des Motorrads komplett neu gestalten, um daraus ein Auto zu machen. Dies erfordert jedoch einen enormen Aufwand, ruiniert die Einfachheit des Fahrrads und erschwert die Wartung.

Stattdessen befestigen Sie einen Beiwagen.

Der Beiwagen ist eine separate, eigenständige Einheit, die mit dem Motorrad verbunden wird. Es nimmt an der Fahrt des Motorrads teil, begleitet das Motorrad überall hin und arbeitet eng zusammen. Der Kernmotor des Motorrads bleibt jedoch unangetastet.

In der Softwarearchitektur:

  • Das Motorrad ist Ihr primärer Anwendungscontainer (der Ihre Kerngeschäftslogik wie Checkout oder Benutzerauthentifizierung ausführt).
  • Der Sidecar ist ein separater Hilfscontainer (der Dienstprogrammaufgaben wie SSL-Beendigung, Überwachung oder Protokollversand ausführt).
  • Die Reise ist der Lebenszyklus der Bereitstellung (z. B. eines Kubernetes-Pods).

Das Problem: Querschnittsthemen und Code-Aufblähung

Vor Sidecars mussten Entwickler Hilfsbibliotheken direkt in ihren Anwendungscode einbinden. Wenn Sie beispielsweise Protokolle an einen zentralen Server senden wollten, importierten Sie eine Protokollierungsbibliothek. Wenn Sie Metriken benötigten, haben Sie ein Metrik-SDK hinzugefügt.

Dieser bibliotheksbasierte Ansatz führte zu mehreren erheblichen Herausforderungen:

  • Sprachbindung: Wenn eine Überwachungsbibliothek nur in Go geschrieben ist, können Sie sie nicht einfach in einem Python- oder Java-Microservice verwenden. Sie müssen für jede Sprache in Ihrem Stapel eine Bibliothek finden oder erstellen.
  • Codeverschmutzung: Die Geschäftslogik wird mit infrastrukturspezifischem Code für Wiederholungsversuche, Diensterkennung, Verschlüsselung und Protokollierung überfüllt.
  • Komplexe Upgrades: Wenn in der Kommunikationsbibliothek eine Sicherheitslücke gefunden wird, muss jeder einzelne Mikrodienst seine Abhängigkeit aktualisieren, neu kompilieren und erneut bereitstellen.
  • Ressourcenkonflikt: Der Hilfscode wird im selben Laufzeitprozess wie die Hauptanwendung ausgeführt, was bedeutet, dass ein Speicherverlust im Logger Ihre gesamte Kernanwendung zum Absturz bringen kann.

Die Lösung: Das Sidecar-Muster

Das Sidecar Pattern löst diese Probleme, indem es Hilfsaufgaben aus dem Hauptanwendungsprozess verlagert und sie in einen separaten, unabhängigen Prozess platziert, der direkt neben der Anwendung ausgeführt wird.

In Containerumgebungen wie Kubernetes laufen der Anwendungscontainer und der Sidecar-Container im selben Pod. Weil sie denselben Pod teilen:

  • Gleicher Netzwerk-Namespace: Sie teilen sich die gleiche IP-Adresse und die gleichen Netzwerk-Ports. Sie können über localhost sofort und praktisch ohne Latenz miteinander kommunizieren.
  • Freigegebene Speichervolumes: Sie können auf genau denselben Festplattenspeicher zugreifen, sodass der Sidecar Protokolldateien lesen oder von der Hauptanwendung geschriebene Konfigurationsdateien laden kann.
  • Identischer Lebenszyklus: Der Sidecar wird zusammen mit der primären Anwendung bereitgestellt, gestartet, gestoppt und skaliert.

Wichtige Anwendungsfälle des Sidecar-Musters

Beiwagen sind unglaublich vielseitig. Zu den häufigsten Anwendungen gehören:

1. Service Mesh Proxying (z. B. Envoy, Linkerd)

Anstatt dass Ihre Anwendung direkte HTTP-Aufrufe an andere Dienste durchführt, sendet sie Anforderungen an ihren lokalen Sidecar-Proxy. Der Sidecar-Proxy übernimmt Routing, Wiederholungsversuche, Lastausgleich, Leitungsunterbrechung und gegenseitige TLS-Verschlüsselung (mTLS) und leitet dann die Anfrage weiter. Die Anwendung ist sich dieser Netzwerkkomplexität überhaupt nicht bewusst.

2. Protokollerfassung und -weiterleitung (z. B. Fluent Bit)

Ihre Anwendung schreibt ihre Protokollanweisungen einfach in die Standardausgabe oder eine lokale Protokolldatei. Ein Sidecar-Container überwacht diese Datei, analysiert die Protokolle und leitet sie an eine zentrale Analyse-Engine wie Elasticsearch oder Datadog weiter.

3. Konfiguration und geheimes Neuladen

Ein Sidecar kann einen Remote-Server (wie Consul oder Vault) auf Konfigurationsaktualisierungen oder kryptografische Schlüsselrotationen überwachen. Wenn eine Änderung erkannt wird, lädt es die neuen Dateien auf ein freigegebenes Volume herunter und signalisiert der Hauptanwendung, sie neu zu laden, ohne dass ein Neustart erforderlich ist.


Kubernetes-Implementierungsbeispiel

Das Einrichten eines Sidecars ist in Kubernetes unkompliziert. Hier ist eine einfache YAML-Konfiguration, die einen Anwendungscontainer zeigt, der Protokolle auf ein freigegebenes Volume schreibt, und einen Fluent Bit-Sidecar-Container, der diese Protokolle liest und versendet:

apiVersion: v1
kind: Pod
metadata:
  name: app-with-logging-sidecar
  labels:
    app: billing-service
spec:
  containers:
    # 1. Primary Application Container
    - name: web-app
      image: node:18-alpine
      command: ["/bin/sh", "-c"]
      args:
        - >
          while true; do
            echo "$(date) [INFO] Transaction processed successfully" >> /var/log/app/output.log;
            sleep 5;
          done
      volumeMounts:
        - name: shared-logs
          mountPath: /var/log/app

    # 2. Sidecar Container (Log Shipper)
    - name: log-shipper
      image: fluent/fluent-bit:latest
      volumeMounts:
        - name: shared-logs
          mountPath: /var/log/app
      # In a real setup, Fluent Bit config would read /var/log/app/output.log
      # and forward it to an external logging system.

  # Shared disk storage accessible by both containers
  volumes:
    - name: shared-logs
      emptyDir: {}

Vor- und Nachteile des Sidecar-Musters

Wie jedes Designmuster gibt es auch bei Sidecars Kompromisse:

Advantage (Pro) Nachteil (Kontra)
Sprachunabhängig: Der Sidecar läuft in seiner eigenen Umgebung. Sie können denselben Sidecar-Helfer neben Go-, Java-, Python- oder Ruby-Apps verwenden. Ressourcenaufwand: Das Ausführen mehrerer Container pro Pod erhöht den CPU- und Speicherverbrauch.
Entkoppelter Lebenszyklus: Infrastrukturteams können die Sicherheitspatches des Sidecars aktualisieren, ohne den Anwendungscode zu berühren. Erhöhte Komplexität: Die Verwaltung von doppelt so vielen Containern erschwert die Bereitstellungskonfiguration, das Debugging und die Planung.
Unabhängige Fehlerisolierung: Wenn der Sidecar-Container abstürzt, kann Kubernetes ihn automatisch neu starten, ohne die Hauptanwendung herunterzufahren. Geringe Netzwerklatenz: Die Weiterleitung des Datenverkehrs über einen lokalen Proxy-Sidecar fügt einen kleinen Hop hinzu, der jedoch normalerweise vernachlässigbar ist (< 1ms).

Abschluss

Das Sidecar Pattern ist ein grundlegender Baustein moderner Cloud-nativer Architekturen. Durch die Isolierung übergreifender Belange – wie Netzwerk-Proxy, Sicherheit, Protokollierung und Konfigurationsmanagement – ​​in einem separaten Begleitprozess können sich Entwickler ausschließlich auf die Schaffung von Geschäftswerten konzentrieren.

Es führt zwar zu einem zusätzlichen Ressourcenaufwand und erfordert für eine effektive Verwaltung Container-Orchestrierungsplattformen wie Kubernetes, die Vorteile saubererer Codebasen, Sprachflexibilität und unabhängiger Skalierung machen es jedoch zu einem unverzichtbaren Muster für Unternehmens-Microservices.


Weitere Einblicke in Softwareentwicklung und Backend-Engineering finden Sie im Ghaznix-Blog →