- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Network Security: Network Policies, Service Mesh und Zero Trust
TL;DR
- Standardmaessig erlaubt Kubernetes allen Pod-zu-Pod-Traffic -- ohne Network Policies ist euer Cluster ein flaches Netzwerk ohne Segmentierung
- Startet mit Default-Deny-Policies pro Namespace und oeffnet dann gezielt nur die notwendigen Verbindungen (Least Privilege)
- Ein Service Mesh (Istio oder Linkerd) ergaenzt Network Policies um mTLS-Verschluesselung und L7-Autorisierung
- Linkerd hat deutlich weniger Overhead als Istio und ist fuer kleinere Teams oft die bessere Wahl
- Zero Trust ist kein Produkt, sondern ein Architekturprinzip: jede Verbindung wird authentifiziert und autorisiert, auch cluster-intern
Das Problem: Kubernetes ist standardmaessig offen
Frisch installiertes Kubernetes hat keine Netzwerkbeschraenkungen. Jeder Pod kann mit jedem anderen Pod im Cluster kommunizieren, ueber Namespaces hinweg. Das ist praktisch fuer die Entwicklung, aber ein Sicherheitsrisiko in Produktion.
Stellt euch vor, ein Angreifer kompromittiert einen einzelnen Pod -- zum Beispiel ueber eine Schwachstelle in einer Bibliothek. Ohne Network Policies kann dieser Pod frei im gesamten Cluster kommunizieren: Datenbanken abfragen, andere Services ansprechen, Secrets aus dem API-Server lesen (sofern RBAC das erlaubt). Das ist Lateral Movement, und es ist der Grund, warum ein einzelner kompromittierter Container zum Cluster-weiten Vorfall werden kann.
Network Policies sind die erste Verteidigungslinie dagegen.
Network Policies: Grundlagen und Default-Deny
Network Policies sind Kubernetes-native Ressourcen, die den Traffic auf L3/L4-Ebene steuern. Sie werden von einem CNI-Plugin (Calico, Cilium, Weave) durchgesetzt. Wichtig: Das Standard-CNI kubenet unterstuetzt keine Network Policies. Prueft also zuerst, ob euer CNI-Plugin sie implementiert.
Der wichtigste erste Schritt: eine Default-Deny-Policy fuer jeden Namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Diese Policy selektiert alle Pods im Namespace production (leerer podSelector) und verbietet jeglichen ein- und ausgehenden Traffic. Ab diesem Moment ist der Namespace isoliert. Kein Pod kann Verbindungen empfangen oder aufbauen, bis ihr explizite Allow-Policies erstellt.
Dann oeffnet ihr gezielt:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-to-database
namespace: production
spec:
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api-server
ports:
- protocol: TCP
port: 5432
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
Drei Policies, und euer Namespace hat ein klares Kommunikationsmodell: Frontend spricht mit API, API spricht mit Datenbank, alle Pods duerfen DNS-Aufloesung machen. Alles andere ist geblockt.
Ein haeufig vergessener Punkt: DNS-Egress. Ohne die dritte Policy funktioniert keine Service-Discovery mehr, weil die Pods kube-dns nicht erreichen koennen.
CNI-Vergleich: Calico vs Cilium
Nicht jedes CNI-Plugin ist gleich. Die beiden relevantesten fuer Network Security:
| Feature | Calico | Cilium |
|---|---|---|
| Network Policy Support | Kubernetes + eigene CRDs | Kubernetes + eigene CRDs |
| L7-Policies (HTTP) | Ueber eigene CRDs | Nativ (eBPF-basiert) |
| Verschluesselung | WireGuard | WireGuard oder IPsec |
| Performance-Overhead | Gering (iptables/eBPF) | Sehr gering (eBPF) |
| Observability | Flow Logs | Hubble (integriert) |
| Lernkurve | Moderat | Steiler |
| Kernel-Anforderungen | Standard | Kernel >= 5.10 empfohlen |
Cilium ist technisch ueberlegen, besonders bei L7-Policies und Observability durch Hubble. Calico ist ausgereifter und hat eine breitere Basis in bestehenden Installationen. Wenn ihr einen neuen Cluster aufsetzt, ist Cilium die Empfehlung. Bei bestehenden Calico-Installationen lohnt sich der Wechsel nur, wenn ihr konkret L7-Features braucht.
Service Mesh: mTLS und L7-Autorisierung
Network Policies arbeiten auf L3/L4: IP-Adressen und Ports. Sie koennen nicht zwischen HTTP GET und HTTP POST unterscheiden, keine Pfade filtern und keinen Traffic verschluesseln.
Ein Service Mesh schliesst diese Luecke. Es injiziert einen Sidecar-Proxy (typischerweise Envoy) in jeden Pod, der den gesamten Netzwerk-Traffic abfaengt. Dadurch kann das Mesh:
- mTLS automatisch aktivieren (jede Verbindung ist verschluesselt und beidseitig authentifiziert)
- L7-Autorisierung durchsetzen (Service A darf nur GET auf /api/health von Service B ausfuehren)
- Observability bereitstellen (Request Rate, Error Rate, Latenz pro Service-Paar)
Istio vs Linkerd
| Aspekt | Istio | Linkerd |
|---|---|---|
| Sidecar-Proxy | Envoy | linkerd2-proxy (Rust) |
| Memory pro Sidecar | ca. 50-100 MB | ca. 10-20 MB |
| Control Plane Footprint | Gross (istiod, ca. 1-2 GB) | Klein (ca. 200-500 MB) |
| Feature-Umfang | Sehr umfangreich | Fokussiert auf Kernfeatures |
| L7-Authorization | AuthorizationPolicy (maechtig) | Server/ServerAuthorization |
| Multi-Cluster | Ja (komplex) | Ja (einfacher) |
| Lernkurve | Steil | Moderat |
| CNCF-Status | Graduated | Graduated |
Fuer Teams unter 10 Personen ist Linkerd meist die bessere Wahl. Weniger Konfiguration, geringerer Ressourcenverbrauch, schnellere Time-to-Value. Istio lohnt sich, wenn ihr fortgeschrittenes Traffic Management braucht (Canary Deployments mit gewichteten Routing-Regeln, komplexe Retry-Policies, WASM-Plugins).
Beispiel: Istio AuthorizationPolicy
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: api-server-policy
namespace: production
spec:
selector:
matchLabels:
app: api-server
action: ALLOW
rules:
- from:
- source:
principals:
- "cluster.local/ns/production/sa/frontend"
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/v1/*"]
- from:
- source:
principals:
- "cluster.local/ns/monitoring/sa/prometheus"
to:
- operation:
methods: ["GET"]
paths: ["/metrics"]
Diese Policy erlaubt dem Frontend-ServiceAccount GET und POST auf /api/v1/* und Prometheus GET auf /metrics. Alles andere wird abgelehnt. Das ist deutlich granularer als eine Network Policy.
Zero Trust: Mehr als ein Buzzword
Zero Trust wird oft als Produkt verkauft, ist aber ein Architekturprinzip. Die Kernidee: Vertraue keiner Verbindung nur wegen ihrer Herkunft im Netzwerk. Jede Anfrage muss sich authentifizieren und autorisieren.
In Kubernetes setzt ihr Zero Trust durch die Kombination von:
- Network Policies -- Netzwerk-Segmentierung als Basis
- mTLS via Service Mesh -- Jede Verbindung ist verschluesselt und authentifiziert
- Workload Identity -- Pods werden ueber ServiceAccounts und SPIFFE-IDs identifiziert, nicht ueber IP-Adressen
- L7 Authorization Policies -- Zugriff wird pro Service, Pfad und Methode gesteuert
- RBAC -- API-Server-Zugriff ist rollenbasiert beschraenkt
Die Schichten ergaenzen sich. Network Policies allein sind kein Zero Trust (kein mTLS, kein L7). Ein Service Mesh allein reicht auch nicht (kein Schutz gegen Pods ausserhalb des Mesh). Erst die Kombination ergibt ein vollstaendiges Modell.
Schrittweise Einfuehrung
Alles auf einmal einzufuehren ist ein Rezept fuer Ausfaelle. Hier ein pragmatischer Stufenplan:
Phase 1 (Woche 1-3): Network Policies
- CNI-Plugin pruefen (Calico/Cilium vorhanden?)
- Default-Deny in einem Test-Namespace einrichten
- Kommunikationsmatrix der Services dokumentieren
- Allow-Policies schreiben und testen
- Auf weitere Namespaces ausrollen
Phase 2 (Woche 4-6): Service Mesh Pilot
- Istio oder Linkerd in einem Test-Namespace installieren
- mTLS im Permissive Mode aktivieren (verschluesselt, aber erzwingt nicht)
- Traffic-Metriken in Grafana visualisieren
- Anomalien und unerwartete Verbindungen identifizieren
Phase 3 (Woche 7-9): mTLS Strict und L7 Policies
- mTLS auf Strict Mode umstellen (unverschluesselter Traffic wird abgelehnt)
- L7-Authorization-Policies fuer kritische Services schreiben
- Alerting fuer Policy-Verletzungen einrichten
Phase 4 (Woche 10-12): Rollout und Haertung
- Service Mesh auf Produktions-Namespaces ausweiten
- Egress-Policies fuer externen Traffic definieren
- Penetration Test durchfuehren
- Dokumentation und Runbooks erstellen
Haeufige Fehler
Fehler 1: Network Policies ohne CNI-Support deployen. Die Policies werden von Kubernetes akzeptiert, aber nicht durchgesetzt. Ihr habt ein falsches Sicherheitsgefuehl. Testet immer, ob der Traffic tatsaechlich geblockt wird.
Fehler 2: DNS-Egress vergessen. Nach dem Default-Deny funktioniert keine Service-Discovery mehr. Immer eine Egress-Policy fuer kube-dns mitsenden.
Fehler 3: mTLS im Strict Mode ohne Rollout-Plan. Wenn ein Service noch keinen Sidecar hat, wird er von Services im Mesh nicht mehr erreicht. Startet mit Permissive Mode und wechselt erst nach vollstaendigem Rollout auf Strict.
Fehler 4: Zu breite Namespace-Selektoren. namespaceSelector: {} selektiert alle Namespaces, einschliesslich kube-system. Seid praezise mit Labels.
Fehler 5: Network Policies nicht versionieren. Policies gehoeren ins Git-Repository, nicht in kubectl apply aus der Shell. Behandelt sie wie Code.
Monitoring und Troubleshooting
Ohne Monitoring wisst ihr nicht, ob eure Policies funktionieren. Nuetzliche Tools:
- Cilium Hubble: Echtzeit-Flow-Logs und Policy-Verdicts (allowed/denied)
- Calico Flow Logs: Aehnlich, aber weniger integriert
- Istio/Linkerd Dashboards: Request-Metriken pro Service-Paar
- np-viewer (Open Source): Visualisiert Network Policies als Graph
Ein guter Test: Deployt einen Debug-Pod und versucht, Verbindungen aufzubauen, die geblockt sein sollten:
# Debug-Pod ohne spezifische Labels deployen
kubectl run nettest --rm -it --restart=Never \
--image=nicolaka/netshoot \
--namespace=production \
-- bash
# Innerhalb des Pods: Verbindung zur Datenbank versuchen
curl -v postgres:5432
# Sollte timeout/connection refused ergeben
# DNS pruefen
nslookup api-server.production.svc.cluster.local
Wenn der Debug-Pod die Datenbank erreichen kann, ist eure Network Policy falsch konfiguriert.
Weitergehende Themen
- Fuer fortgeschrittene Network Policy-Patterns: Kubernetes Network Policies Advanced
- Fuer Egress-Filtering und externe Verbindungen: Kubernetes Egress Filtering
- Fuer RBAC-Konfiguration auf API-Server-Ebene: Kubernetes RBAC Enterprise
- Fuer Observability des gesamten Stacks: Kubernetes Observability Stack
- Fuer Penetration Testing nach der Haertung: Kubernetes Penetration Testing
Wenn ihr Unterstuetzung bei der Netzwerk-Segmentierung oder Service-Mesh-Einfuehrung in eurem Cluster braucht, 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
Zero Trust Networking für Kubernetes umsetzen
Zero Trust in Kubernetes mit mTLS via Service Mesh, Network Policies und SPIFFE-Identitäten umsetzen. Praxisanleitung mit YAML.
Service Mesh Security: mTLS und Zero Trust in Kubernetes
Service Mesh Security mit mTLS in Kubernetes einrichten: Zero-Trust-Architektur, Istio-Policies und Service-zu-Service-Authentifizierung für DSGVO-Compliance.
Zero-Trust Architektur für Kubernetes Cluster
Zero-Trust in Kubernetes umsetzen mit Network Policies, mTLS und Identity Verification. Schritt-für-Schritt Anleitung für sichere Cluster-Kommunikation.
Netzwerk-Mikrosegmentierung in Kubernetes umsetzen
Mikrosegmentierung in Kubernetes mit Default-Deny, Zonen-Architektur und Cilium ClusterWide NetworkPolicy praktisch umsetzen.
Kubernetes Zero Trust: Architektur für Container-Umgebungen
Zero-Trust-Architektur in Kubernetes umsetzen: mTLS, Network Policies, RBAC und Service Mesh mit YAML-Praxisbeispielen konfigurieren.