Veröffentlicht am

Kubernetes Network Policies: Calico & Cilium Guide

Teilen:
Authors

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-PluginNetwork PoliciesL7-PoliciesPerformance
FlannelNeinNeinGut
CalicoJaJa (CRD)Sehr gut
CiliumJaJa (CRD, eBPF)Exzellent
Weave NetJaNeinMittel
Canal (Flannel + Calico)JaTeilweiseGut

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.com statt 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

PolicyZweckPrioritaet
Default-Deny (Ingress + Egress)Baseline pro NamespaceP0 -- sofort
DNS-AllowGrundfunktionalitaet sicherstellenP0 -- sofort
Ingress pro ServiceNur erlaubte QuellenP1 -- pro Service
Egress pro ServiceExfiltration verhindernP1 -- pro Service
Namespace-IsolationCross-Namespace-Zugriff regelnP1 -- pro Namespace
Monitoring-EgressPrometheus Scraping erlaubenP1 -- einmalig
L7-Policies (optional)HTTP/gRPC-FilterungP2 -- 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