Veröffentlicht am

Zero Trust Networking für Kubernetes umsetzen

Teilen:
Authors

TL;DR

Zero Trust in Kubernetes bedeutet: Kein Pod vertraut einem anderen Pod automatisch. Die Umsetzung erfolgt in drei Schichten — Network Policies als Basis-Firewall, mTLS via Service Mesh für verschlüsselte und authentifizierte Kommunikation, und SPIFFE/SPIRE für kryptografische Workload-Identitäten. Zusammen ergibt das Defense in Depth.


Zero Trust Networking in Kubernetes

In einem Standard-Kubernetes-Cluster kann jeder Pod mit jedem anderen Pod kommunizieren. Keine Authentifizierung, keine Verschlüsselung, kein Zugriffscontrol. Ein kompromittierter Pod hat freie Bewegung im gesamten Netzwerk.

# Beweis: Pod-zu-Pod-Kommunikation ist per Default offen
kubectl run attacker --image=nicolaka/netshoot -- sleep 3600
kubectl exec attacker -- curl -s http://backend-service.production.svc:8080/api/data
# Funktioniert — ohne jede Authentifizierung

Zero Trust eliminiert dieses implizite Vertrauen.

Die drei Säulen von Zero Trust

Zero Trust ist kein einzelnes Tool, sondern eine Architektur aus mehreren Schichten:

SchichtMechanismusTool
NetzwerkMicro-SegmentierungNetwork Policies (Calico, Cilium)
TransportVerschlüsselung + AuthentifizierungmTLS (Istio, Linkerd)
IdentitätWorkload IdentitySPIFFE/SPIRE

Jede Schicht allein ist unzureichend. Erst die Kombination ergibt echtes Zero Trust.

Schicht 1: Network Policies als Baseline

Network Policies sind die Firewall-Ebene. Sie kontrollieren, welche Pods miteinander kommunizieren dürfen — auf IP- und Port-Ebene.

Default Deny für alle Namespaces

Der erste Schritt: Alles blockieren, dann gezielt freigeben.

# default-deny-all.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
kubectl apply -f default-deny-all.yaml
# Ab jetzt ist JEDE Kommunikation in/aus dem Namespace blockiert

Gezielte Freigaben

Nach dem Default Deny gibst du nur die nötigen Verbindungen frei:

# allow-frontend-to-backend.yaml
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

Network Policies haben eine Einschränkung: Sie arbeiten auf Layer 3/4. Ein Pod mit dem Label app: frontend wird durchgelassen — egal ob der Pod tatsächlich der echte Frontend-Service ist. Für Identitätsprüfung brauchst du Schicht 2.

Schicht 2: mTLS mit Service Mesh

Mutual TLS (mTLS) verschlüsselt den gesamten Pod-zu-Pod-Traffic und authentifiziert beide Seiten. Istio und Linkerd injizieren dafür einen Sidecar-Proxy in jeden Pod.

Istio: Strict mTLS aktivieren

# peer-authentication-strict.yaml
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
  namespace: istio-system  # Cluster-weit
spec:
  mtls:
    mode: STRICT

Im STRICT-Modus lehnt Istio jede unverschlüsselte Verbindung ab. Pods ohne Sidecar können nicht mehr mit Mesh-Pods kommunizieren.

kubectl apply -f peer-authentication-strict.yaml

# Verifizieren: mTLS-Status prüfen
istioctl x describe pod backend-7d8f9b-abc12.production
# Erwartete Ausgabe zeigt mTLS STRICT

Authorization Policies: Wer darf was?

mTLS allein verschlüsselt und authentifiziert, aber erlaubt trotzdem alles. AuthorizationPolicies regeln den Zugriff auf Basis der Service-Identität:

# authz-backend.yaml
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: backend-access
  namespace: production
spec:
  selector:
    matchLabels:
      app: backend
  action: ALLOW
  rules:
    - from:
        - source:
            principals:
              - "cluster.local/ns/production/sa/frontend"
      to:
        - operation:
            methods: ["GET", "POST"]
            paths: ["/api/*"]

Nur der Service Account frontend im Namespace production darf GET- und POST-Requests an /api/* senden. Alles andere wird mit 403 Forbidden abgelehnt.

Linkerd als leichtgewichtige Alternative

Linkerd aktiviert mTLS automatisch — ohne Konfiguration:

# Linkerd installieren
linkerd install --crds | kubectl apply -f -
linkerd install | kubectl apply -f -

# Namespace in den Mesh aufnehmen
kubectl annotate namespace production linkerd.io/inject=enabled

# Pods neustarten, damit Sidecars injiziert werden
kubectl rollout restart deployment -n production

# mTLS verifizieren
linkerd viz stat deploy -n production
# MESHED-Spalte zeigt, welche Pods im Mesh sind

Schicht 3: Workload Identity mit SPIFFE

SPIFFE (Secure Production Identity Framework for Everyone) gibt jedem Workload eine kryptografische Identität — unabhängig vom Netzwerk-Standort.

Jeder Workload erhält eine SPIFFE ID im Format:

spiffe://cluster.example.com/ns/production/sa/backend

SPIRE (SPIFFE Runtime Environment) ist die Referenzimplementierung und attestiert Workloads über Node- und Workload-Attestation. Istio nutzt intern bereits SPIFFE-IDs für seine mTLS-Zertifikate.

# SPIRE Server installieren
helm repo add spiffe https://spiffe.github.io/helm-charts-hardened/
helm install spire spiffe/spire \
  --namespace spire-system \
  --create-namespace \
  --set spire-server.enabled=true \
  --set spire-agent.enabled=true

# Registrierten Workload prüfen
kubectl exec -n spire-system spire-server-0 -- \
  spire-server entry show

Defense in Depth: Alle Schichten zusammen

So greifen die drei Schichten ineinander:

  1. Network Policy blockiert Traffic auf Netzwerk-Ebene — ein kompromittierter Pod im monitoring-Namespace erreicht production gar nicht erst
  2. mTLS verschlüsselt allen erlaubten Traffic und authentifiziert die Gegenseite — Spoofing wird verhindert
  3. Authorization Policy prüft auf Anwendungsebene, welche Methoden und Pfade erlaubt sind — selbst ein authentifizierter Service bekommt nur Zugriff auf das Nötigste

Ein Angreifer müsste alle drei Schichten überwinden. Das ist Zero Trust.

FAQ

Brauche ich zwingend ein Service Mesh für Zero Trust?

Nicht zwingend, aber für mTLS praktisch. Ohne Mesh müsstest du TLS-Zertifikate manuell in jede Anwendung integrieren. Network Policies allein sind kein vollständiges Zero Trust, da sie keine Verschlüsselung oder Identitätsprüfung bieten.

Welches Service Mesh passt zu mir — Istio oder Linkerd?

Linkerd ist einfacher zu installieren und ressourcenschonender, hat aber weniger Features. Istio bietet mehr Kontrolle (Authorization Policies, Traffic Management), ist aber komplexer. Für reines mTLS reicht Linkerd. Für granulare Access Control nimm Istio.

Wie teste ich, ob mein Zero Trust Setup funktioniert?

Deploye einen Test-Pod ohne Mesh-Sidecar und versuche, auf Services zuzugreifen. Der Zugriff sollte auf jeder Schicht fehlschlagen — Network Policy blockt, mTLS lehnt ab, Authorization Policy verweigert.

Was ist der Performance-Overhead von mTLS?

Der Latenz-Overhead liegt typischerweise unter 1ms pro Hop. CPU-Overhead durch TLS-Handshakes und Verschlüsselung ist bei modernem Hardware vernachlässigbar. Linkerd-Sidecars verbrauchen etwa 10-20 MB RAM pro Pod.


Nächster Schritt: Sichere auch deine Software Supply Chain ab — mit Container Image Signing via Cosign und Sigstore, damit nur verifizierte Images in deinen Zero-Trust-Cluster gelangen.

Kubernetes-Security & Compliance?

Security-Audits, Penetration Tests und Compliance-Beratung für Ihre Container-Infrastruktur. BSI-Grundschutz, DSGVO, ISO 27001.

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