TL;DR
Kubernetes Network Policies implementieren das Least-Privilege-Prinzip auf Netzwerkebene im Cluster. Ohne Policies können alle Pods miteinander kommunizieren, was bei einem kompromittierten Pod zum Einfallstor für alle anderen wird. Policies sind Whitelist-basiert und additiv: ein Pod ohne Policy hat keine Einschränkung, ein selektierter Pod wird auf alle nicht explizit erlaubten Verbindungen blockiert. Praxisempfehlungen sind Default-Deny-Policies pro Namespace, explizite Ingress- und Egress-Regeln sowie Service-Mesh-Alternativen wie Istio oder Cilium für erweitertes Traffic-Management.
Diese Zusammenfassung wurde KI-gestützt erstellt (EU AI Act Art. 50).
Inhaltsverzeichnis (5 Abschnitte)
In einem Standard-Kubernetes-Cluster ohne Network Policies können alle Pods miteinander kommunizieren - jeder kann jeden erreichen. Das ist für die Entwicklung praktisch, aber sicherheitstechnisch ein Problem: ein kompromittierter Pod kann alle anderen Pods im Cluster angreifen. Network Policies implementieren Mikrosegmentierung und das Least-Privilege-Prinzip auf Netzwerkebene.
Grundkonzept
Namespace production mit drei Pods: frontend (Port 3000), backend (Port 8080), database (Port 5432).
OHNE Network Policies sind alle Verbindungen erlaubt:
frontend <-> backend <-> database (gewünscht)
frontend -> database (UNERWÜNSCHT! Frontend sollte DB nicht erreichen)
database -> frontend (UNERWÜNSCHT! DB sollte keine ausgehenden Connections machen)
Ein kompromittiertes Frontend kann direkt auf database:5432 zugreifen - keine zusätzliche Hürde.
MIT Network Policies (richtig konfiguriert):
frontend -> backend (8080): ERLAUBT
frontend -> database (5432): BLOCKIERT
backend -> database (5432): ERLAUBT
database -> irgendwo: BLOCKIERT
Network Policy Grundregeln:
- Policies sind ADDITIV: eine Allow-Regel reicht für Erlaubnis
- Policies sind WHITELIST-basiert: wenn eine Policy einen Pod selektiert, wird ALLES andere blockiert was nicht explizit erlaubt ist
- Kein Policy = kein Restriction (alle Verbindungen erlaubt!)
- Default-Deny: muss explizit durch Policy implementiert werden
Network Policy Syntax
Grundstruktur:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-policy
namespace: production
spec:
podSelector: # Auf welche Pods wird diese Policy angewendet?
matchLabels:
app: backend
policyTypes: # Was wird spezifiziert?
- Ingress # Eingehender Traffic
- Egress # Ausgehender Traffic
ingress: # Eingehende Traffic-Regeln
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress: # Ausgehende Traffic-Regeln
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
Selektoren im Detail:
podSelector (Pods im gleichen Namespace):
- from:
- podSelector:
matchLabels:
app: frontend
namespaceSelector (Pods aus anderem Namespace):
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
Kombination (Pods in spezifischem Namespace, UND-Verknüpfung durch gleichen Listeneintrag - zwei getrennte Einträge wären ODER!):
- from:
- namespaceSelector:
matchLabels:
environment: production
podSelector: # UND-Verknüpfung (gleicher Listeneintrag!)
matchLabels:
app: prometheus
ipBlock (externe IP-Bereiche):
- from:
- ipBlock:
cidr: 10.0.0.0/8
except:
- 10.1.1.0/24 # Diese Range ausschließen
Praktische Policy-Patterns
Pattern 1 - Default-Deny-All (Basis für jede sichere Konfiguration):
# Kein Traffic erlaubt zu diesem Pod (Ingress + Egress)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {} # Leerer Selektor = ALLE Pods im Namespace
policyTypes:
- Ingress
- Egress
# Keine ingress/egress Regeln = alles verboten!
---
# Dann gezielt erlauben:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-db
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- port: 5432
Pattern 2 - Namespace-Isolation (empfohlen für alle Namespaces):
# Kein Ingress aus anderen Namespaces
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-from-other-namespaces
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {} # Nur Pods im GLEICHEN Namespace
# Kein namespaceSelector = nur gleicher Namespace!
Pattern 3 - Zugriff nur vom Monitoring-Namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-prometheus-scraping
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
purpose: monitoring
podSelector:
matchLabels:
app: prometheus
ports:
- port: 9090 # Metrics-Port
Pattern 4 - DNS-Egress erlauben (häufig vergessen - Pods brauchen DNS-Zugriff!):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: production
spec:
podSelector: {} # Alle Pods
policyTypes:
- Egress
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
# Gleichzeitig kube-dns/CoreDNS erlauben:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
Pattern 5 - Internet-Egress für spezifische Pods:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-external-api
namespace: production
spec:
podSelector:
matchLabels:
app: api-client
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0 # Ganzes Internet
except:
- 10.0.0.0/8 # Private Ranges ausschließen
- 172.16.0.0/12 # (Kubernetes-interne Isolation)
- 192.168.0.0/16
ports:
- port: 443
- port: 80
CNI-Plugins und Service Mesh
Nicht alle CNI-Plugins unterstützen Network Policies!
| Plugin | Network Policy Support |
|---|---|
| Flannel | KEIN Support (nur Layer-3-Routing) |
| Calico | Full Support + erweiterte Features |
| Cilium | eBPF-basiert, L7-Policies, beste Performance |
| WeaveNet | Support |
| Canal | Flannel + Calico-Policy-Enforcement |
Calico NetworkPolicy (erweiterte Syntax, erlaubt mehr als Standard-K8s-Policies):
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-https-only
spec:
selector: app == 'frontend'
types:
- Egress
egress:
- action: Allow
protocol: TCP
destination:
ports: [443]
- action: Deny # Explizites Deny!
Cilium (eBPF-basierte L7-Policies - nur GET/POST auf spezifische Pfade, Layer-7-Filtering ohne Service Mesh!):
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: api-policy
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/.*"
- method: "POST"
path: "/api/v1/orders"
Service Mesh - Istio AuthorizationPolicy (ergänzend zu K8s Network Policies):
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: backend-policy
spec:
selector:
matchLabels:
app: backend
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/prod/sa/frontend-sa"]
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/*"]
Network Policies vs. Service Mesh: Network Policies arbeiten auf IP/Port-Level (Layer 3/4), Service Mesh bietet mTLS, L7-Filtering, RBAC und Observability. Beste Sicherheit: beides kombinieren!
Troubleshooting und Best Practices
Fehler 1 - ODER statt UND bei Selektoren:
FALSCH (OR-Semantik - zwei getrennte Listeneinträge):
ingress:
- from:
- podSelector: # Regel 1: Pods mit app=api
matchLabels:
app: api
- namespaceSelector: # Regel 2: ODER alle aus monitoring-NS
matchLabels:
purpose: monitoring
RICHTIG (AND-Semantik - gleicher Listeneintrag):
ingress:
- from:
- podSelector: # Pods mit app=api
matchLabels:
app: api
namespaceSelector: # UND im monitoring-NS
matchLabels:
purpose: monitoring
Fehler 2 - DNS vergessen: Default-Deny-Egress blockiert DNS-Auflösung - App kann Service-Names nicht auflösen. IMMER DNS-Egress (Port 53 UDP+TCP) erlauben!
Fehler 3 - Kube-System vergessen: Manche K8s-interne Services im kube-system Namespace (Health-Checks, Metrics, Admission Webhooks) brauchen Zugriff. Nach Policy-Deployment Cluster-Health prüfen!
Fehler 4 - NodePort/LoadBalancer vergessen: Externe Anfragen kommen von Node-IP (andere IP als Pod-IP) - ipBlock mit Cluster-IP-Range nötig für externe Anfragen.
Debugging:
# Alle Network Policies im Namespace:
kubectl get networkpolicies -n production
kubectl describe networkpolicy my-policy -n production
# Pod-Konnektivität testen (wenn blockiert: Connection refused oder timeout):
kubectl exec -n production frontend-pod -- curl -v backend-service:8080/api/health
# Cilium: Netzwerkflüsse beobachten:
cilium monitor --type drop # Zeigt geblockte Verbindungen!
cilium monitor --type trace # Alle Verbindungen
# Calico: Flow-Logs aktivieren (kommerzielles Feature)
# Netreap / Retina (Microsoft): eBPF-basiertes Network-Monitoring
Verifikation der Policy:
kubectl auth can-i --list --as=system:serviceaccount:prod:default
# Zeigt ob Service Account erwartete Rechte hat
# Tool: kubectl-np-viewer (Visualisierung):
kubectl np-viewer -n production
Network Policies sind ein unverzichtbares Sicherheitselement in Kubernetes-Produktionsclustern. Der Aufwand für ihre Implementierung zahlt sich durch erheblich reduziertes Lateral-Movement-Risiko aus: ein kompromittierter Pod kann nicht mehr alle anderen Pods und Services erreichen. AWARE7 überprüft Kubernetes-Cluster-Konfigurationen auf fehlende oder zu permissive Network Policies als Teil von Cloud-Security-Assessments.
Nächster Schritt
Unsere zertifizierten Sicherheitsexperten beraten Sie zu den Themen aus diesem Artikel, unverbindlich und kostenlos.
Kostenlos · 30 Minuten · Unverbindlich