- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Ambassador Pattern: Sidecar-Proxy fuer sichere Service-Kommunikation
TL;DR
- Das Ambassador Pattern platziert einen Proxy-Container (typischerweise Envoy) als Sidecar im selben Pod wie der Anwendungscontainer.
- Der Sidecar uebernimmt TLS-Termination, Retries, Circuit Breaking und Routing -- der Anwendungscode bleibt davon frei.
- Der Unterschied zum Service Mesh: Das Ambassador Pattern wird manuell pro Service konfiguriert, ein Service Mesh injiziert Sidecars automatisch clustersweit.
- Der Ressourcen-Overhead liegt bei ca. 50-100 MB RAM und 0.1 CPU pro Sidecar -- bei 10 Pods sind das 1 GB RAM extra.
- Sinnvoll fuer Teams, die gezielte Proxy-Funktionalitaet fuer einzelne Services brauchen, ohne ein volles Service Mesh einzufuehren.
Was das Ambassador Pattern ist (und was nicht)
Das Ambassador Pattern ist eines der drei klassischen Sidecar-Muster in Kubernetes (neben Adapter und Ambassador). Die Idee: Ein zweiter Container im Pod fungiert als Proxy fuer alle Netzwerkinteraktionen des Hauptcontainers.
Der Hauptcontainer spricht nur mit localhost. Der Ambassador-Sidecar uebernimmt alles, was mit dem Netzwerk zu tun hat: TLS handshake, Connection Pooling, Retries bei Fehlern, Load Balancing zu Upstream-Services.
Was es nicht ist: Ein Ersatz fuer einen Ingress Controller oder ein API Gateway. Der Ambassador sitzt innerhalb des Pods und steuert die Kommunikation eines einzelnen Services. Ein Ingress Controller sitzt am Clusterrand und routet externen Traffic.
Ambassador Pattern vs. Service Mesh vs. API Gateway
| Kriterium | Ambassador Pattern | Service Mesh (Istio/Linkerd) | API Gateway (Kong/APISIX) |
|---|---|---|---|
| Scope | Einzelner Pod | Gesamter Cluster | Cluster-Eingang |
| Sidecar-Injection | Manuell (im Deployment-YAML) | Automatisch (Namespace-Label) | Kein Sidecar |
| Konfiguration | Per ConfigMap/Volume pro Pod | Zentral via CRDs | Zentral via CRDs |
| TLS/mTLS | Ja, manuell konfiguriert | Ja, automatisch | TLS-Termination am Edge |
| Retry/Circuit Breaking | Ja | Ja | Begrenzt |
| Observability | Manuell integrieren | Built-in | Built-in |
| Overhead | Gering (nur wo noetig) | Hoch (jeder Pod bekommt Sidecar) | Gering (zentraler Proxy) |
| Wann sinnvoll | 1-5 Services mit Proxy-Bedarf | Ab 10+ Services | Externe API-Absicherung |
Architektur: So sieht das im Cluster aus
Ein typischer Aufbau:
Ingress Controller
|
Kubernetes Service
|
+----------+-----------+
| Pod |
| |
| +----------------+ |
| | Envoy Sidecar | |
| | (Port 8000) | |
| +-------+--------+ |
| | |
| +-------v--------+ |
| | App Container | |
| | (Port 8080) | |
| +----------------+ |
+----------------------+
Der Ingress Controller leitet Traffic an den Kubernetes Service. Der Service verweist auf Port 8000 des Pods -- das ist der Envoy-Sidecar. Envoy leitet nach Pruefung und ggf. Transformation an localhost:8080 weiter, wo der eigentliche Anwendungscontainer laeuft.
Praktische Implementierung mit Envoy
Hier ein vollstaendiges Beispiel: Ein Deployment mit einem Python-API-Container und einem Envoy-Sidecar, der TLS-Termination und Basic Routing uebernimmt.
Deployment mit Sidecar
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
labels:
app: order-service
spec:
replicas: 2
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
# Anwendungscontainer -- spricht nur mit localhost
- name: order-api
image: registry.example.com/order-service:1.4.2
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: order-db-credentials
key: url
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
# Ambassador-Sidecar: Envoy Proxy
- name: envoy-ambassador
image: envoyproxy/envoy:v1.31-latest
args: ["-c", "/etc/envoy/envoy.yaml", "--log-level", "info"]
ports:
- containerPort: 8000
name: proxy
- containerPort: 9901
name: admin
volumeMounts:
- name: envoy-config
mountPath: /etc/envoy
readOnly: true
- name: tls-certs
mountPath: /etc/tls
readOnly: true
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
volumes:
- name: envoy-config
configMap:
name: order-service-envoy-config
- name: tls-certs
secret:
secretName: order-service-tls
Envoy-Konfiguration als ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: order-service-envoy-config
data:
envoy.yaml: |
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 8000
filter_chains:
- transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain:
filename: /etc/tls/tls.crt
private_key:
filename: /etc/tls/tls.key
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
access_log:
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: local_app
timeout: 30s
retry_policy:
retry_on: "5xx,connect-failure,refused-stream"
num_retries: 3
per_try_timeout: 10s
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: local_app
connect_timeout: 0.5s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: local_app
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8080
circuit_breakers:
thresholds:
- max_connections: 100
max_pending_requests: 50
max_requests: 200
max_retries: 3
admin:
address:
socket_address:
address: 127.0.0.1
port_value: 9901
Service-Definition
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector:
app: order-service
ports:
# Traffic geht an den Envoy-Sidecar, nicht direkt an die App
- name: https
port: 443
targetPort: 8000
Der wichtige Punkt: Der Kubernetes Service zeigt auf Port 8000 (Envoy), nicht auf 8080 (App). Alle Aufrufer im Cluster sprechen mit Envoy, der dann TLS terminiert, Retries durchfuehrt und an die lokale App weiterleitet.
Was der Sidecar uebernehmen kann
Durch die Envoy-Konfiguration lassen sich verschiedene Funktionen aktivieren, ohne den Anwendungscode zu aendern:
TLS-Termination -- wie im Beispiel oben gezeigt. Der Anwendungscontainer empfaengt unverschluesselten Traffic auf localhost. Envoy kuemmert sich um Zertifikate und TLS Handshake.
Automatic Retries -- bei 5xx-Fehlern oder Connection Failures versucht Envoy es automatisch erneut (konfigurierbar). Das ist besonders nuetzlich bei transienten Fehlern in Upstream-Services.
Circuit Breaking -- wenn ein Upstream-Service nicht antwortet, oeffnet Envoy den Circuit Breaker nach einer konfigurierbaren Anzahl Fehler. Neue Requests werden sofort mit einem Fehler beantwortet, statt den Thread zu blockieren.
Rate Limiting -- Envoy unterstuetzt lokales Rate Limiting ueber den envoy.filters.http.local_ratelimit-Filter. Nuetzlich, um einzelne Services vor Ueberlastung zu schuetzen.
Observability -- Envoy generiert automatisch Metriken (Prometheus-kompatibel), Zugriffslogs und unterstuetzt Distributed Tracing (Jaeger, Zipkin). Ohne eine Zeile Code in der Anwendung.
Wann das Pattern nicht sinnvoll ist
Nicht jeder Service braucht einen Sidecar. Ueberlegt euch, ob das Ambassador Pattern wirklich den Aufwand rechtfertigt:
- Wenige Services ohne komplexe Netzwerkanforderungen -- wenn ein einfacher ClusterIP Service reicht, ist ein Sidecar Overkill.
- Bereits ein Service Mesh im Einsatz -- Istio oder Linkerd injizieren bereits Envoy/Linkerd-Proxy als Sidecar. Ein zusaetzlicher Ambassador-Sidecar waere doppelt.
- Batch Jobs oder CronJobs -- kurzlebige Pods profitieren kaum von Retry-Logik und Circuit Breaking.
- Ressourcen sind knapp -- jeder Sidecar braucht CPU und RAM. Bei Hunderten von Pods laeppern sich 50-100 MB pro Sidecar.
Fuer die Entscheidung Service Mesh vs. manuelles Sidecar hilft der Vergleich unter Istio vs. Linkerd.
Deployment-Checkliste
Bevor ihr das Ambassador Pattern in Produktion bringt:
| Schritt | Details |
|---|---|
| Resource Limits fuer Sidecar definieren | CPU und Memory Limits setzen, sonst frisst Envoy unter Last beliebig Ressourcen |
| Liveness/Readiness Probes | Envoy Admin-API (/ready auf Port 9901) als Readiness-Probe nutzen |
| Log-Rotation konfigurieren | Access Logs koennen gross werden -- stdout + Log-Aggregation (Loki, Fluentd) |
| TLS-Zertifikate rotieren | cert-manager oder aehnliches Tool nutzen, nicht manuell |
| Metriken scrapen | Envoy /stats/prometheus Endpoint in Prometheus ServiceMonitor einbinden |
| Sidecar-Version pinnen | Kein latest-Tag verwenden, Envoy-Version explizit festlegen |
| Graceful Shutdown | preStop-Hook mit Sleep, damit Envoy laufende Connections sauber beenden kann |
Fuer Capacity Planning mit Sidecars empfiehlt sich der Beitrag zu Kubernetes Capacity Planning.
Weiter vertiefen
- Kubernetes Network Policies Advanced
- Kubernetes Security Hardening Checkliste
- Kubernetes Monitoring und Observability
- Istio vs. Linkerd Vergleich
Wenn ihr Hilfe bei der Entscheidung braucht, ob ein Ambassador-Sidecar, ein Service Mesh oder ein API Gateway fuer euren Fall passt, meldet euch unter /kontakt.
Kubernetes-Beratung gesucht?
Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.
📖 Verwandte Artikel
Weitere interessante Beiträge zu ähnlichen Themen
Dapr auf Kubernetes: Sidecar-Pattern für Microservices
Dapr auf Kubernetes einrichten: Building Blocks für Service Invocation, State Management, Pub/Sub und Secrets mit produktionsreifen YAML-Beispielen.
Kubernetes Sidecar Pattern: Multi-Container Pods erklärt
Sidecar Pattern in Kubernetes mit YAML-Beispielen: Logging, Monitoring und Security-Sidecars konfigurieren und native Sidecar Containers ab v1.28 nutzen.
Kubernetes Adapter Pattern: Legacy-Systeme integrieren
Das Adapter Pattern als Sidecar-Container in Kubernetes löst Protokoll- und Formatinkompatibilitäten zwischen Legacy-Systemen und modernen Services.
Kubernetes CQRS Pattern Microservices in Deutschland optimal nutzen
Optimieren Sie Skalierbarkeit und Performance Ihrer komplexen Microservices auf Kubernetes in Deutschland mit dem CQRS Pattern. Erfahren Sie, wie diese zukunftsweisende Architektur Compliance-Anforderungen erfüllt und digitale Souveränität für deutsche Unternehmen sichert.
Distributed Tracing: Jaeger auf Kubernetes einrichten
Jaeger für Distributed Tracing auf Kubernetes einrichten mit dem Jaeger Operator. OpenTelemetry-Instrumentation in Go und Python, Trace-Propagation zwischen Microservices und praktische Analyse von Latenz-Problemen.