- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Sidecar Pattern: Erweiterte Funktionalitaet durch Sidecar-Container
TL;DR
- Das Sidecar Pattern erweitert einen Haupt-Container um zusaetzliche Funktionalitaet (Logging, Monitoring, Security), ohne dessen Code zu aendern.
- Sidecar und Haupt-Container teilen sich Netzwerk (localhost) und Volumes -- das macht die Integration einfach.
- Gaengige Sidecar-Typen: Fluentd/Fluent Bit (Logging), Prometheus Exporter (Monitoring), Vault Agent (Secrets), git-sync (Config), Envoy (Proxy).
- Seit Kubernetes 1.28 gibt es native Sidecar Containers mit definierter Start- und Shutdown-Reihenfolge.
- Sidecars verbrauchen Ressourcen: Bei 100 Pods mit Sidecar sind das schnell 10 GB RAM extra. Immer Resource Requests und Limits setzen.
Was ist das Sidecar Pattern?
Das Sidecar Pattern ist das grundlegendste Multi-Container-Pattern in Kubernetes. Ein zusaetzlicher Container (der Sidecar) laeuft im selben Pod wie der Haupt-Container und uebernimmt eine unterstuetzende Funktion. Der Name kommt vom Beiwagen eines Motorrads -- er faehrt mit, hat aber eine eigene Funktion.
Der Sidecar teilt sich mit dem Haupt-Container:
- Netzwerk: Beide Container nutzen dieselbe IP-Adresse und koennen ueber
localhostkommunizieren. - Volumes: Ueber Shared Volumes koennen beide Container auf dieselben Dateien zugreifen.
- Lifecycle: Beide Container starten und stoppen (idealerweise) zusammen.
+----------------------------------+
| Pod |
| |
| +------------+ +------------+ |
| | Haupt- | | Sidecar | |
| | Container | | Container | |
| | (App) | | (Helper) | |
| +-----+------+ +------+-----+ |
| | localhost | |
| +--------+--------+ |
| | |
| Shared Volume |
+----------------------------------+
Der entscheidende Vorteil: Die Anwendung muss nicht veraendert werden. Logging, Monitoring, TLS-Termination oder Secret-Injection werden vom Sidecar uebernommen. Das ist besonders wertvoll, wenn Sie Third-Party-Images oder Legacy-Anwendungen betreiben.
Sidecar-Typ 1: Logging mit Fluent Bit
Der klassische Logging-Sidecar: Die Anwendung schreibt Logs in eine Datei, Fluent Bit liest diese Datei und leitet die Logs an Elasticsearch, Loki oder einen Cloud-Dienst weiter.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: registry.internal/web-app:2.3.0
ports:
- containerPort: 8080
volumeMounts:
- name: app-logs
mountPath: /var/log/app
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
- name: log-forwarder
image: fluent/fluent-bit:3.0
volumeMounts:
- name: app-logs
mountPath: /var/log/app
readOnly: true
- name: fluent-bit-config
mountPath: /fluent-bit/etc
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
volumes:
- name: app-logs
emptyDir: {}
- name: fluent-bit-config
configMap:
name: fluent-bit-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
data:
fluent-bit.conf: |
[SERVICE]
Flush 5
Log_Level info
Daemon off
[INPUT]
Name tail
Path /var/log/app/*.log
Tag app.*
Read_from_Head true
[OUTPUT]
Name forward
Match *
Host fluentd.logging.svc.cluster.local
Port 24224
Der emptyDir-Volume ist der Verbindungspunkt: Die App schreibt nach /var/log/app/, Fluent Bit liest von dort. Wer seinen Monitoring-Stack optimieren moechte, findet Tipps im Beitrag zu Kubernetes Monitoring und Kosten.
Sidecar-Typ 2: Monitoring mit Prometheus Exporter
Manche Anwendungen exportieren keine Prometheus-Metriken nativ. Ein Sidecar-Exporter uebersetzt anwendungsspezifische Metriken in das Prometheus-Format:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-with-exporter
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9121"
spec:
containers:
- name: redis
image: redis:7.2
ports:
- containerPort: 6379
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
- name: redis-exporter
image: oliver006/redis_exporter:v1.58.0
ports:
- containerPort: 9121
name: metrics
env:
- name: REDIS_ADDR
value: "localhost:6379"
resources:
requests:
cpu: 50m
memory: 32Mi
limits:
cpu: 100m
memory: 64Mi
Der Redis-Exporter verbindet sich ueber localhost:6379 mit Redis und exportiert Metriken auf Port 9121. Prometheus scraped den Exporter ueber die Pod-Annotations. Das gleiche Pattern funktioniert fuer MySQL, PostgreSQL, NGINX und viele weitere Services.
Sidecar-Typ 3: Secrets mit Vault Agent
HashiCorp Vault Agent als Sidecar injiziert dynamische Secrets direkt in den Pod, ohne dass die Anwendung Vault kennen muss:
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
spec:
replicas: 3
selector:
matchLabels:
app: payment-service
template:
metadata:
labels:
app: payment-service
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "payment-service"
vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/payment-db"
vault.hashicorp.com/agent-inject-template-db-creds: |
{{- with secret "database/creds/payment-db" -}}
export DB_USER="{{ .Data.username }}"
export DB_PASS="{{ .Data.password }}"
{{- end }}
spec:
serviceAccountName: payment-service
containers:
- name: payment-service
image: registry.internal/payment-service:4.2.0
command:
- sh
- -c
- source /vault/secrets/db-creds && exec ./payment-service
ports:
- containerPort: 8080
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: "1"
memory: 1Gi
Der Vault Agent Injector (ein Admission Webhook) fuegt automatisch einen Sidecar-Container hinzu, der die Secrets aus Vault laedt und unter /vault/secrets/ bereitstellt. Die Anwendung liest die Secrets als Dateien. Wer mehr ueber Secrets Management erfahren moechte, findet Details im Beitrag zu Kubernetes Secrets Management mit Vault.
Sidecar-Typ 4: Config-Sync mit git-sync
Der git-sync Sidecar synchronisiert ein Git-Repository in ein Shared Volume. Nützlich fuer Konfigurationen, statische Inhalte oder Templates:
apiVersion: apps/v1
kind: Deployment
metadata:
name: docs-server
spec:
replicas: 2
selector:
matchLabels:
app: docs-server
template:
metadata:
labels:
app: docs-server
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
volumeMounts:
- name: docs-content
mountPath: /usr/share/nginx/html
readOnly: true
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
- name: git-sync
image: registry.k8s.io/git-sync/git-sync:v4.2.1
env:
- name: GITSYNC_REPO
value: "https://github.com/company/docs-content.git"
- name: GITSYNC_BRANCH
value: "main"
- name: GITSYNC_ROOT
value: "/git"
- name: GITSYNC_DEST
value: "current"
- name: GITSYNC_PERIOD
value: "30s"
volumeMounts:
- name: docs-content
mountPath: /git
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
volumes:
- name: docs-content
emptyDir: {}
Alle 30 Sekunden synchronisiert git-sync den neuesten Stand aus dem Repository. Der Nginx-Container liefert die Inhalte aus. Kein Redeploy noetig, wenn sich nur der Content aendert.
Sidecar-Typ 5: Envoy als Proxy-Sidecar
Envoy als Sidecar uebernimmt TLS-Termination, Retries, Circuit Breaking und Observability. Das ist im Prinzip das Ambassador Pattern:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
spec:
replicas: 3
selector:
matchLabels:
app: api-service
template:
metadata:
labels:
app: api-service
spec:
containers:
- name: api-service
image: registry.internal/api-service:3.0.0
ports:
- containerPort: 8080
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
- name: envoy-proxy
image: envoyproxy/envoy:v1.29.0
ports:
- containerPort: 8443
name: https
- containerPort: 9901
name: admin
volumeMounts:
- name: envoy-config
mountPath: /etc/envoy
- name: tls-certs
mountPath: /etc/certs
readOnly: true
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 300m
memory: 128Mi
volumes:
- name: envoy-config
configMap:
name: envoy-config
- name: tls-certs
secret:
secretName: api-service-tls
Fuer eine detaillierte Implementierung des Ambassador Patterns mit Envoy empfehle ich den Beitrag zum Kubernetes Ambassador Pattern.
Native Sidecar Containers ab Kubernetes 1.28
Vor Kubernetes 1.28 hatten Sidecar-Container ein grundlegendes Problem: Es gab keine garantierte Start- und Shutdown-Reihenfolge. Der Haupt-Container konnte starten, bevor der Sidecar bereit war. Beim Shutdown konnte der Sidecar vor dem Haupt-Container beendet werden.
Native Sidecar Containers loesen das. Sie werden als Init Containers mit restartPolicy: Always definiert:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-with-native-sidecar
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
initContainers:
# Regulaerer Init Container -- laeuft einmal
- name: setup
image: busybox:1.36
command:
- sh
- -c
- echo "Setup abgeschlossen"
resources:
requests:
cpu: 50m
memory: 32Mi
limits:
cpu: 100m
memory: 64Mi
# Nativer Sidecar -- startet VOR dem Haupt-Container, stoppt NACH ihm
- name: log-forwarder
image: fluent/fluent-bit:3.0
restartPolicy: Always
volumeMounts:
- name: app-logs
mountPath: /var/log/app
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
containers:
- name: app
image: registry.internal/my-app:1.0.0
ports:
- containerPort: 8080
volumeMounts:
- name: app-logs
mountPath: /var/log/app
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: app-logs
emptyDir: {}
Die Startreihenfolge ist nun:
setupInit Container laeuft und beendet sichlog-forwarderSidecar startet und laeuft weiterappHaupt-Container startet
Beim Shutdown:
apperhaelt SIGTERM und beendet sichlog-forwardererhaelt SIGTERM nach dem Haupt-Container
Das behebt Race Conditions, bei denen z.B. ein Logging-Sidecar beendet wurde, bevor der Haupt-Container seine letzten Logs schreiben konnte.
Shared Volumes: Der Verbindungspunkt
Shared Volumes sind das Rueckgrat der meisten Sidecar-Patterns. Die gaengigsten Volume-Typen fuer Sidecars:
| Volume-Typ | Zweck | Persistenz |
|---|---|---|
emptyDir | Temporaerer Speicher, verschwindet mit dem Pod | Keine |
emptyDir mit medium: Memory | RAM-basiert, schnell, fuer Caches | Keine |
configMap | Konfigurationsdateien | Cluster-Lifecycle |
secret | Sensible Daten (Zertifikate, Passwoerter) | Cluster-Lifecycle |
persistentVolumeClaim | Persistente Daten, ueberlebt Pod-Neustarts | Persistent |
Beispiel mit Memory-basiertem emptyDir fuer schnellen Datenaustausch:
volumes:
- name: shared-cache
emptyDir:
medium: Memory
sizeLimit: 256Mi
Wichtig: Bei medium: Memory zaehlt das Volume gegen die Memory-Limits des Pods. Setzen Sie immer ein sizeLimit, um zu verhindern, dass der Pod wegen OOM gekillt wird. Details dazu finden Sie in unserem Beitrag zu OOM Kills vermeiden.
Ressourcen-Overhead: Die Kosten von Sidecars
Jeder Sidecar-Container verbraucht CPU und RAM. Bei wenigen Pods faellt das kaum ins Gewicht. Bei 100 oder mehr Pods summiert sich der Overhead erheblich:
Sidecar: 50m CPU, 64Mi Memory (Requests)
10 Pods: 500m CPU, 640Mi Memory
50 Pods: 2.5 CPU, 3.2 Gi Memory
100 Pods: 5.0 CPU, 6.4 Gi Memory
200 Pods: 10.0 CPU, 12.8 Gi Memory
Best Practices fuer Sidecar-Ressourcen:
- Immer Resource Requests und Limits setzen. Sidecars ohne Limits koennen den Haupt-Container verdraengen.
- Requests realistisch dimensionieren. Messen Sie den tatsaechlichen Verbrauch mit
kubectl top pod. - Sidecar-Images schlank halten. Fluent Bit (unter 15 MB) statt Fluentd (100+ MB).
- Sidecar pro Funktion, nicht pro Feature. Kombinieren Sie verwandte Funktionen in einem Sidecar.
# Tatsaechlichen Ressourcenverbrauch messen
kubectl top pod my-pod --containers
# Beispielausgabe:
# POD NAME CPU(cores) MEMORY(bytes)
# my-pod app 120m 234Mi
# my-pod log-forwarder 12m 45Mi
# my-pod envoy-proxy 35m 62Mi
Verwandte Patterns: Ambassador und Adapter
Das Sidecar Pattern ist die Basis fuer zwei weitere Multi-Container-Patterns:
| Pattern | Zweck | Typischer Sidecar | Kommunikationsrichtung |
|---|---|---|---|
| Sidecar | Unterstuetzende Funktionalitaet | Fluent Bit, Prometheus Exporter | App-intern |
| Ambassador | Ausgehende Kommunikation vereinfachen | Envoy, HAProxy | App nach aussen |
| Adapter | Eingehende Daten transformieren | Protokoll-Konverter, Format-Transformer | Aussen nach App |
Ambassador Pattern: Der Sidecar agiert als Proxy fuer ausgehende Verbindungen. Die Anwendung spricht nur mit localhost, der Ambassador uebernimmt TLS, Retries und Routing.
Adapter Pattern: Der Sidecar transformiert eingehende Daten in ein Format, das die Anwendung versteht. Nützlich fuer Legacy-Integrationen.
Detaillierte Implementierungen finden Sie in unseren Beitraegen zum Ambassador Pattern und Adapter Pattern.
Wann KEIN Sidecar verwenden
Sidecars sind nicht immer die beste Loesung. Vermeiden Sie Sidecars in diesen Faellen:
Overhead uebersteigt den Nutzen
Wenn der Sidecar mehr Ressourcen verbraucht als der Haupt-Container, stimmt das Verhaeltnis nicht. Ein Envoy-Sidecar fuer einen einfachen Cron-Job ist Overkill.
Zentrale Loesung ist besser
Statt in jedem Pod einen Log-Sidecar zu betreiben, kann ein Node-Level DaemonSet (z.B. Fluentd als DaemonSet) alle Logs von allen Pods auf dem Node einsammeln. Das spart Ressourcen bei vielen Pods:
# Statt Sidecar in jedem Pod:
# DaemonSet auf Node-Ebene -- ein Fluentd pro Node statt pro Pod
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: logging
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
labels:
app: fluentd
spec:
tolerations:
- operator: "Exists"
containers:
- name: fluentd
image: fluent/fluentd:v1.16
volumeMounts:
- name: varlog
mountPath: /var/log
- name: containers
mountPath: /var/lib/docker/containers
readOnly: true
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: varlog
hostPath:
path: /var/log
- name: containers
hostPath:
path: /var/lib/docker/containers
Service Mesh ersetzt manuelle Sidecars
Wenn Sie bereits Istio oder Linkerd einsetzen, injiziert das Service Mesh automatisch Proxy-Sidecars. Dann brauchen Sie keinen manuellen Envoy-Sidecar. Einen Vergleich der Service-Mesh-Optionen finden Sie im Beitrag zu Istio vs. Linkerd.
Kurzlebige Pods und Jobs
Fuer Kubernetes Jobs oder CronJobs, die nur Sekunden laufen, ist der Startup-Overhead eines Sidecars unverhältnismaessig. Nutzen Sie stattdessen Init Containers fuer einmalige Setup-Tasks.
Sidecar Pattern: Entscheidungshilfe
# Brauche ich einen Sidecar?
# Ja, wenn:
# - Die Anwendung kann/soll nicht veraendert werden
# - Die Funktion ist Cross-Cutting (Logging, Monitoring, Security)
# - Der Sidecar braucht localhost-Zugriff auf die App
# - Die Funktion ist pro-Pod spezifisch (nicht pro-Node)
# Nein, wenn:
# - Ein DaemonSet (Node-Level) die gleiche Funktion effizienter erfuellt
# - Ein zentraler Service (z.B. Log-Aggregator) ausreicht
# - Der Overhead die Ressourcen des Haupt-Containers uebersteigt
# - Die Funktion nur beim Start noetig ist (dann Init Container)
Zusammenfassung
Das Kubernetes Sidecar Pattern ist eines der maechtigsten Werkzeuge fuer die Erweiterung von Container-Funktionalitaet, ohne Anwendungscode aendern zu muessen. Logging mit Fluent Bit, Monitoring mit Prometheus Exportern, Secrets mit Vault Agent, Config-Sync mit git-sync und Proxy-Funktionalitaet mit Envoy decken die haeufigsten Einsatzfelder ab.
Mit nativen Sidecar Containers seit Kubernetes 1.28 sind die frueheren Probleme mit Start- und Shutdown-Reihenfolge geloest. Behalten Sie aber immer den Ressourcen-Overhead im Blick: Jeder Sidecar braucht CPU und RAM, und bei vielen Pods summiert sich das schnell.
Waegen Sie ab, ob ein Sidecar die richtige Loesung ist, oder ob ein DaemonSet, ein zentraler Service oder ein Service Mesh besser passt.
Verwandte Artikel
- Kubernetes Ambassador Pattern
- Kubernetes Adapter Pattern
- Kubernetes Secrets Management mit Vault
- Istio vs. Linkerd Vergleich
- Kubernetes Monitoring und Kosten senken
Wenn Sie Unterstuetzung bei der Implementierung von Multi-Container-Patterns in Ihrem Kubernetes-Cluster brauchen, sprechen Sie uns an 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.
Resilience Patterns für Kubernetes Microservices
Resilience Patterns für Kubernetes-Microservices: Retry, Circuit Breaker, Bulkhead, Timeout, Health Checks und PDB mit YAML-Konfigurationen.
Ambassador Pattern in Kubernetes: Envoy als Sidecar-Proxy
Das Ambassador Pattern in Kubernetes erklärt: Envoy als Sidecar-Proxy für TLS-Termination, Retry-Logik und Routing mit YAML-Beispielen.
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.