Zum Inhalt springen

Service-Mesh-Grundlagen: Netzwerke auf Infrastrukturebene

Ein Service Mesh verlagert Netzwerkaufgaben wie Retries, Circuit Breaking, mTLS und Observability aus dem Anwendungscode in die Infrastrukturebene.

3 Min. Lesezeit
Service-Mesh-Architektur mit Sidecar-Proxys für die Kommunikation zwischen Services

In einer Microservices-Architektur benötigt jeder Service Retries, Timeouts, Circuit Breaking, gegenseitiges TLS, Traffic-Splitting und Observability. Wird das alles im Anwendungscode jedes einzelnen Service implementiert, entstehen Duplikate und Inkonsistenzen. Ein Service Mesh übernimmt all das auf der Infrastrukturebene: Ein Sidecar-Proxy fängt jeden Netzwerkaufruf ab und wendet die Richtlinien einheitlich an, ohne dass der Anwendungscode geändert werden muss.

Das Sidecar-Pattern

Jede Serviceinstanz erhält einen Sidecar-Proxy (meist Envoy). Der gesamte ein- und ausgehende Traffic läuft durch den Proxy, der die Netzwerkrichtlinien transparent anwendet.

ymlyaml
# Without service mesh: application handles networking
# Every service needs retry logic, circuit breakers, TLS, etc.
 
# With service mesh: sidecar proxy handles networking
# Kubernetes pod with a sidecar injected by Istio
apiVersion: v1
kind: Pod
metadata:
  name: order-service
  labels:
    app: order-service
  annotations:
    sidecar.istio.io/inject: "true"  # Istio injects the sidecar automatically
spec:
  containers:
    - name: order-service
      image: registry.example.com/order-service:v1.2.0
      ports:
        - containerPort: 3000
    # Istio automatically adds:
    # - name: istio-proxy
    #   image: docker.io/istio/proxyv2
    #   ports:
    #     - containerPort: 15001 (outbound)
    #     - containerPort: 15006 (inbound)

Traffic-Management

Ein Service Mesh ermöglicht anspruchsvolles Traffic-Routing, ohne den Anwendungscode anzufassen.

ymlyaml
# Retry policy — automatically retry failed requests
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: payment-service
spec:
  hosts:
    - payment-service
  http:
    - route:
        - destination:
            host: payment-service
      retries:
        attempts: 3
        perTryTimeout: 2s
        retryOn: "5xx,reset,connect-failure,retriable-4xx"
 
---
# Timeout policy — fail fast if the service is slow
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: recommendation-service
spec:
  hosts:
    - recommendation-service
  http:
    - route:
        - destination:
            host: recommendation-service
      timeout: 5s  # Fail after 5 seconds instead of waiting indefinitely

Gegenseitiges TLS (mTLS)

Ein Service Mesh kann mTLS zwischen allen Services erzwingen: Jede Verbindung wird verschlüsselt und authentifiziert, ohne dass die Anwendung Zertifikate verwalten muss.

ymlyaml
# ❌ Without mesh: plaintext HTTP between services
# Any compromised pod can eavesdrop on inter-service traffic
 
# ✅ With Istio: strict mTLS for all services in the namespace
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT  # All traffic must use mTLS
 
---
# Authorization policy — only specific services can call payment
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: payment-service-access
  namespace: production
spec:
  selector:
    matchLabels:
      app: payment-service
  rules:
    - from:
        - source:
            principals:
              - "cluster.local/ns/production/sa/order-service"
              - "cluster.local/ns/production/sa/refund-service"
      to:
        - operation:
            methods: ["POST"]
            paths: ["/api/charge", "/api/refund"]

Circuit Breaking auf Mesh-Ebene

Statt in jedem Service einen eigenen Circuit Breaker zu implementieren, wird er einmalig im Mesh konfiguriert.

ymlyaml
# ❌ Every service implements its own circuit breaker in application code
# Inconsistent thresholds, different libraries, duplicated logic
 
# ✅ Mesh-level circuit breaking — consistent across all services
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: payment-service
spec:
  host: payment-service
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        h2UpgradePolicy: DEFAULT
        http1MaxPendingRequests: 50
        http2MaxRequests: 100
    outlierDetection:
      consecutive5xxErrors: 5        # Eject after 5 consecutive errors
      interval: 10s                   # Check every 10 seconds
      baseEjectionTime: 30s           # Eject for 30 seconds minimum
      maxEjectionPercent: 50          # Never eject more than 50% of hosts

Observability ohne Codeänderungen

Der Sidecar-Proxy erfasst Metriken, Traces und Zugriffslogs für jede Anfrage, ganz ohne Instrumentierung im Anwendungscode.

tstypescript
// Without service mesh: manual instrumentation required
app.use((req, res, next) => {
  const start = Date.now();
  res.on("finish", () => {
    metrics.histogram("http_duration", Date.now() - start, {
      method: req.method,
      path: req.path,
      status: res.statusCode,
    });
  });
  next();
});
 
// With service mesh: metrics are collected automatically by the proxy
// Available as Prometheus metrics:
// istio_requests_total{source_app="order-service", destination_app="payment-service", response_code="200"}
// istio_request_duration_milliseconds{...}
// istio_tcp_sent_bytes_total{...}
ymlyaml
# Grafana dashboard JSON model for mesh metrics
# These metrics exist without any application instrumentation
panels:
  - title: "Request Rate"
    targets:
      - expr: 'sum(rate(istio_requests_total{destination_app="payment-service"}[5m]))'
  - title: "P99 Latency"
    targets:
      - expr: 'histogram_quantile(0.99, sum(rate(istio_request_duration_milliseconds_bucket{destination_app="payment-service"}[5m])) by (le))'
  - title: "Error Rate"
    targets:
      - expr: 'sum(rate(istio_requests_total{destination_app="payment-service",response_code=~"5.."}[5m])) / sum(rate(istio_requests_total{destination_app="payment-service"}[5m]))'

Wann man auf ein Service Mesh verzichten sollte

Ein Service Mesh bringt zusätzliche Latenz (der Hop über den Sidecar-Proxy), Speicher-Overhead (ein Proxy pro Pod) und operative Komplexität (die Verwaltung der Control Plane) mit sich. Das lohnt sich bei vielen Services mit komplexen Netzwerkanforderungen. Bei einer Handvoll Services sind Bibliotheken auf Anwendungsebene die einfachere Lösung.

Die wichtigsten Erkenntnisse

  1. Ein Service Mesh übernimmt das Networking auf der Infrastrukturebene – Retries, Timeouts und Circuit Breaking ohne Änderungen am Anwendungscode
  2. mTLS verschlüsselt und authentifiziert den gesamten Traffic zwischen Services – das Mesh verwaltet die Zertifikate automatisch
  3. Traffic-Richtlinien sind deklarativ – Routing, Retries und Circuit Breaking werden per YAML konfiguriert
  4. Observability gibt es kostenlos dazu – der Sidecar erfasst Metriken, Traces und Logs für jede Anfrage
  5. Autorisierungsrichtlinien steuern den Zugriff zwischen Services – sie legen fest, welche Services welche Endpunkte aufrufen dürfen
  6. Den Overhead abwägen – ein Mesh kostet Latenz und Speicher pro Pod, das rechtfertigt sich erst bei ausreichend Services und Komplexität
Wilfredo Rujel

Wilfredo Rujel

Full-Stack-Softwareentwickler

Diesen Beitrag teilenX