- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Network Policies: Zero-Trust Netzwerksegmentierung in der Praxis
TL;DR
- Ohne Network Policies kann jeder Pod im Cluster mit jedem anderen Pod kommunizieren -- das ist die Default-Einstellung und ein Sicherheitsrisiko
- Starten Sie mit Default-Deny per Namespace und oeffnen Sie dann gezielt die benoetigten Verbindungen (Allowlisting)
- Das Standard-NetworkPolicy-API reicht fuer Ingress/Egress auf L3/L4; fuer L7-Filtering (HTTP-Pfade, DNS-Namen) brauchen Sie Calico oder Cilium CRDs
- Testen Sie Policies in einer Staging-Umgebung, bevor Sie sie auf Produktion anwenden -- eine falsche Egress-Policy kann DNS brechen und damit alles
- Network Policies sind nur so gut wie Ihr CNI-Plugin: Flannel unterstuetzt sie nicht, Calico und Cilium schon
Das Problem: Flat Network by Default
Kubernetes erstellt standardmaessig ein flaches Netzwerk. Jeder Pod kann jeden anderen Pod erreichen, egal in welchem Namespace. Das ist bequem fuer die Entwicklung, aber ein Albtraum fuer die Sicherheit.
Stellen Sie sich vor, ein Angreifer kompromittiert einen einzelnen Pod (z.B. ueber eine Schwachstelle in einer Abhaengigkeit). Ohne Network Policies kann er von dort aus den gesamten Cluster scannen, auf Datenbanken zugreifen, interne APIs abfragen und sich lateral bewegen. Das ist kein theoretisches Szenario -- es passiert regelmaessig.
Network Policies aendern das. Sie definieren auf Pod-Ebene, wer mit wem ueber welche Ports kommunizieren darf. Alles andere wird geblockt.
Voraussetzung: CNI-Plugin pruefen
Bevor Sie eine einzige Policy schreiben, pruefen Sie Ihr CNI-Plugin. Nicht alle unterstuetzen Network Policies:
| CNI-Plugin | Network Policies | L7-Policies | Performance |
|---|---|---|---|
| Flannel | Nein | Nein | Gut |
| Calico | Ja | Ja (CRD) | Sehr gut |
| Cilium | Ja | Ja (CRD, eBPF) | Exzellent |
| Weave Net | Ja | Nein | Mittel |
| Canal (Flannel + Calico) | Ja | Teilweise | Gut |
Wenn Sie K3s nutzen (wie im Artikel zu Kubernetes unter 500 Euro beschrieben), ist Flannel der Standard. Sie muessen Flannel durch Calico oder Cilium ersetzen, um Network Policies nutzen zu koennen:
# K3s mit Cilium statt Flannel installieren
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --flannel-backend=none --disable-network-policy" sh -
# Cilium installieren
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
curl -L --fail --remote-name-all "https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-amd64.tar.gz"
tar xzvf cilium-linux-amd64.tar.gz
sudo mv cilium /usr/local/bin/
cilium install --version 1.16.4
cilium status --wait
Schritt 1: Default-Deny pro Namespace
Der erste und wichtigste Schritt: Verbieten Sie allen Traffic in einem Namespace und oeffnen Sie dann gezielt, was erlaubt sein soll.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Diese Policy waehlt alle Pods im Namespace production aus (leerer podSelector) und blockiert sowohl eingehenden als auch ausgehenden Traffic. Ab jetzt ist jeder Pod in diesem Namespace komplett isoliert.
Achtung: Das blockiert auch DNS-Lookups (UDP Port 53). Ohne DNS funktioniert fast nichts. Deshalb brauchen Sie sofort eine begleitende Policy, die DNS erlaubt:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
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
Diese Kombination (Default-Deny + DNS-Allow) ist Ihre Baseline fuer jeden Namespace. Wenden Sie sie auf alle Namespaces an, bevor Sie weitermachen.
Schritt 2: Applikations-Traffic freigeben
Jetzt oeffnen Sie gezielt die Kommunikationspfade, die Ihre Anwendung braucht. Ein typisches 3-Tier-Setup (Frontend, Backend, Datenbank) sieht so aus:
# Frontend darf vom Ingress Controller erreicht werden
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-frontend
namespace: production
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- protocol: TCP
port: 3000
---
# Frontend darf zum Backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
# Backend darf zur Datenbank
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-database
namespace: production
spec:
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 5432
Jede Policy ist eine explizite Erlaubnis. Alles, was nicht explizit erlaubt ist, bleibt geblockt. Das ist das Zero-Trust-Prinzip in der Praxis.
Schritt 3: Egress kontrollieren
Ingress-Policies allein reichen nicht. Wenn ein Pod kompromittiert wird, wollen Sie verhindern, dass er Daten nach aussen exfiltriert oder Command-and-Control-Server kontaktiert.
# Backend darf nur zur Datenbank und zum DNS
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-egress
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
# DNS erlauben
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
# Datenbank erlauben
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
# Externen API-Zugriff auf spezifische IPs beschraenken
- to:
- ipBlock:
cidr: 104.16.0.0/12
ports:
- protocol: TCP
port: 443
Der ipBlock-Selektor ist nuetzlich fuer externe Abhaengigkeiten (Payment Provider, externe APIs). Dokumentieren Sie, welche IPs warum erlaubt sind -- sonst versteht in sechs Monaten niemand mehr, warum ein bestimmter CIDR-Block freigeschaltet ist.
Fortgeschritten: L7-Policies mit Cilium
Das Standard-NetworkPolicy-API arbeitet auf Layer 3/4 (IP + Port). Wenn Sie auf Layer 7 filtern wollen (HTTP-Methoden, Pfade, DNS-Namen), brauchen Sie die CRDs von Calico oder Cilium.
Beispiel: Cilium CiliumNetworkPolicy fuer HTTP-basiertes Filtering:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: api-l7-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: GET
path: "/api/products.*"
- method: POST
path: "/api/orders"
egress:
- toFQDNs:
- matchName: "api.stripe.com"
toPorts:
- ports:
- port: "443"
Das ist deutlich maechtigter als Standard-Policies. Sie koennen:
- HTTP-Methoden und Pfade einschraenken (nur GET auf
/api/products, nur POST auf/api/orders) - Egress auf DNS-Namen statt IP-Adressen beschraenken (
api.stripe.comstatt hartcodierter IPs) - Kafka-Topics, gRPC-Methoden und DNS-Queries filtern
Der Nachteil: Sie binden sich an ein bestimmtes CNI-Plugin. Standard NetworkPolicies sind portabel.
Policies testen
Network Policies ohne Tests sind gefaehrlich. Eine fehlerhafte Policy kann den gesamten Service-Traffic unterbrechen. Hier zwei Ansaetze:
Manuell mit temporaeren Debug-Pods:
# Pruefen, ob Frontend den Backend erreicht
kubectl run test-curl --rm -it --image=curlimages/curl \
--labels="app=frontend" \
-n production \
-- curl -s -o /dev/null -w "%{http_code}" http://backend:8080/health
# Pruefen, ob ein nicht-autorisierter Pod geblockt wird
kubectl run test-blocked --rm -it --image=curlimages/curl \
--labels="app=unauthorized" \
-n production \
-- curl -s --connect-timeout 3 http://backend:8080/health
# Erwartung: Connection timeout
Automatisiert mit Policy-Validierung:
Tools wie kubectl np-viewer oder Cilium's cilium connectivity test validieren Policies systematisch. Integrieren Sie diese Tests in Ihre CI/CD-Pipeline, damit Policy-Aenderungen vor dem Rollout geprueft werden.
Haeufige Fehler
DNS vergessen: Die haefigste Ursache fuer "alles ist kaputt nach Policy-Rollout" ist eine fehlende DNS-Egress-Regel. Testen Sie immer zuerst DNS.
podSelector vs. namespaceSelector verwechselt: Wenn Sie podSelector und namespaceSelector in einer from- oder to-Regel kombinieren, ist die Logik UND (beide muessen zutreffen). Wenn Sie sie als separate Listenelemente angeben, ist es ODER. Dieser Unterschied hat schon viele Stunden Debugging verursacht.
# UND: Pod muss Label app=frontend haben UND im Namespace frontend sein
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
podSelector:
matchLabels:
app: frontend
# ODER: Entweder aus Namespace frontend ODER Pod mit Label app=frontend
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
- podSelector:
matchLabels:
app: frontend
Zu breite ipBlock-Regeln: 0.0.0.0/0 in einer Egress-Rule hebt die gesamte Egress-Kontrolle auf. Seien Sie so spezifisch wie moeglich.
Kein Monitoring: Sie haben Policies deployt, aber sehen nicht, ob Traffic geblockt wird. Nutzen Sie die Metriken Ihres CNI-Plugins. Calico und Cilium bieten Prometheus-Metriken fuer zugelassene und geblockteVerbindungen. Mehr zum Thema Monitoring im Artikel zu Observability Stack.
Policy-Uebersicht: Checkliste
| Policy | Zweck | Prioritaet |
|---|---|---|
| Default-Deny (Ingress + Egress) | Baseline pro Namespace | P0 -- sofort |
| DNS-Allow | Grundfunktionalitaet sicherstellen | P0 -- sofort |
| Ingress pro Service | Nur erlaubte Quellen | P1 -- pro Service |
| Egress pro Service | Exfiltration verhindern | P1 -- pro Service |
| Namespace-Isolation | Cross-Namespace-Zugriff regeln | P1 -- pro Namespace |
| Monitoring-Egress | Prometheus Scraping erlauben | P1 -- einmalig |
| L7-Policies (optional) | HTTP/gRPC-Filterung | P2 -- nach Bedarf |
Schrittweiser Rollout-Plan
Rollen Sie Network Policies nicht in einem Schritt auf den gesamten Cluster aus. Ein pragmatischer Plan:
Woche 1-2: Bestandsaufnahme. Welche Pods kommunizieren mit welchen? Tools wie Cilium Hubble oder kubectl logs auf dem CNI-Plugin helfen. Zeichnen Sie eine Kommunikationsmatrix.
Woche 3-4: Default-Deny + DNS-Allow auf einem nicht-kritischen Namespace (z.B. Staging). Beobachten. Beheben, was bricht.
Woche 5-8: Ingress- und Egress-Policies fuer alle Services im Staging-Namespace. Automatisierte Tests schreiben. Policies als Code in Git verwalten.
Woche 9-12: Rollout auf Produktions-Namespaces. Erst im Audit/Monitor-Modus (Cilium bietet das nativ), dann scharf schalten. Alerting fuer unerwartet geblockten Traffic einrichten.
Mehr zu Security-Themen in Kubernetes finden Sie in den Artikeln zu Runtime Security und Security Scanning Tools.
Zusammenfassung
Network Policies sind kein Nice-to-have, sondern Pflicht fuer jeden Cluster, der ueber eine Spielumgebung hinausgeht. Die gute Nachricht: Das Konzept ist einfach (Default-Deny, dann Allowlist). Die Herausforderung liegt im Detail -- DNS nicht vergessen, AND vs. OR verstehen, und vor allem: testen, testen, testen.
Starten Sie mit einem Namespace, sammeln Sie Erfahrung, und rollen Sie dann aus. Der Aufwand lohnt sich: Lateral Movement wird drastisch erschwert, Compliance-Audits werden einfacher, und Sie schlafen nachts besser.
Weitere relevante Artikel:
Falls Sie Unterstuetzung bei der Implementierung von Network Policies oder einem Security-Audit Ihres Clusters benoetigen, stehen wir gerne zur Verfuegung -- melden Sie sich 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
Netzwerk-Mikrosegmentierung in Kubernetes umsetzen
Mikrosegmentierung in Kubernetes mit Default-Deny, Zonen-Architektur und Cilium ClusterWide NetworkPolicy praktisch umsetzen.
Network Policies: Kubernetes-Traffic richtig absichern
Kubernetes erlaubt standardmäßig allen Pod-Traffic. Mit Network Policies sichern Sie Ingress und Egress gezielt ab. Praxis-Guide mit YAML-Beispielen.
Kubernetes Mikrosegmentierung: NetworkPolicies und Cilium
Mikrosegmentierung in Kubernetes mit NetworkPolicies und Cilium umsetzen: Deny-all-Baseline, Layer-7-Policies und praktische YAML-Beispiele erklärt.
CNI-Vergleich: Calico vs Cilium für Kubernetes
Calico und Cilium im direkten Vergleich: Architektur, Performance, Network Policies und Observability. Welches CNI-Plugin passt zu deinem Cluster?
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.