Network Policies auf Kubernetes: Umgebungen und Kunden wirklich voneinander trennen
Ein Pod von Kunde A ruft die interne API von Kunde B auf – und Kubernetes lässt ihn. Namespaces trennen Namen, keinen Netzverkehr. Wie zwei Network Policies das ändern, ohne laufende Apps abzuschneiden.

Ein Penetrationstest bei einer Agentur, die die Apps von drei Kunden auf einem Kapsule-Cluster betreibt, jeder Kunde mit Staging und Produktion in eigenen Namespaces. Der Tester öffnet eine Shell im Staging-Pod von Kunde A und tippt curl http://api.kunde-b-prod.svc.cluster.local:8080/internal/stats. Die Antwort kommt sofort: ein interner Endpunkt ohne Login, gebaut in der Annahme, er sei nur von innen erreichbar. Niemand hatte etwas falsch konfiguriert – so verhält sich Kubernetes ab Werk.
Eine Kubernetes Network Policy ist ein Objekt, das festlegt, welcher Netzverkehr die Pods eines Namespaces erreichen und verlassen darf – und sie wirkt nur, wenn das Netzwerk-Plugin des Clusters sie durchsetzt. Im Folgenden: eine Baseline aus zwei Policies, die Umgebungen und Kunden trennt, ohne laufende Apps abzuschneiden, und die Stellen, an denen sie in der Praxis bricht.
Warum trennen Namespaces keinen Netzverkehr?
Namespaces trennen Namen, Berechtigungen und Quotas. Für das Netz sind sie bedeutungslos: Laut Kubernetes-Dokumentation ist ein Pod ohne Policy in keiner Richtung isoliert, alle Verbindungen sind erlaubt. Der Cluster-DNS löst jeden Service in jedem Namespace auf, und jeder Pod erreicht jeden anderen über dessen IP.
Für ein Team mit einer App ist das bequem. Für eine Agentur mit mehreren Kunden oder einen SaaS-Anbieter mit einem Namespace pro Tenant heißt es: Eine Lücke in einer App öffnet den Weg zu allen anderen. Wer Tenants per Namespace trennt, wie im Beitrag Multi-Tenant: Namespace oder Zeile?, braucht Network Policies, damit die Trennung auch im Netz gilt.
Wie funktioniert eine Kubernetes Network Policy?
Vier dokumentierte Regeln erklären fast jede Überraschung:
- Auswahl macht isoliert. Ein Pod wird für eine Richtung isoliert, sobald irgendeine Policy ihn auswählt und diese Richtung in
policyTypesnennt. Ein leererpodSelector: {}wählt alle Pods des Namespaces. - Policies addieren sich. Es gibt keine Deny-Regeln und keine Reihenfolge: Erlaubt ist die Vereinigung dessen, was alle zutreffenden Policies erlauben.
- Antworten sind implizit erlaubt. Regeln beschreiben nur, wer eine Verbindung beginnen darf.
- Ohne Durchsetzung keine Wirkung. Ohne Netzwerk-Plugin, das sie umsetzt, ist eine Policy nur ein Objekt in der Datenbank. Kapsule-Cluster laufen standardmäßig mit Cilium (Standardwert für
cniin der Scaleway-CLI), und Cilium setzt sie durch.
Eine Ausnahme: Verkehr von und zu der eigenen Node ist immer erlaubt. Die Prüfungen des Kubelets erreichen den Pod also auch in einem isolierten Namespace.
Wie sieht eine sinnvolle Baseline pro Umgebung aus?
Pro Umgebung – einem Namespace mit den Services einer App in Staging oder Produktion – genügen zwei Policies, die alle Pods des Namespaces auswählen:
- Eingehend: nur Ingress-Controller und Nachbarn. Erlaubt sind die Namespaces der installierten Ingress-Controller, ausgewählt über das automatisch gesetzte Label
kubernetes.io/metadata.name, und Pods im selben Namespace – die App erreicht ihren Worker oder Cache. Alles andere im Cluster wird abgewiesen. - Ausgehend: alles außer den Metadaten. Zuerst eine ausdrückliche Regel für den Cluster-DNS (Pods mit
k8s-app: kube-dnsinkube-system, UDP und TCP 53), dann0.0.0.0/0mit der Ausnahme169.254.0.0/16. In diesem link-lokalen Bereich liegt der Metadatendienst der Node, bei Scaleway unter169.254.42.42.
Warum nicht ausgehend alles verbieten? Weil fast jede App nach draußen spricht: zur Managed-Datenbank im privaten Netz, zu Object Storage, zu Zahlungs- und Mail-Diensten. Ein Default-Deny für Egress passt zu einer Umgebung, deren Ziele Sie vollständig kennen; als Baseline für bestehende Apps bricht es mehr, als es schützt. Die Sperre des Metadatenbereichs dagegen kostet keine App etwas und nimmt einer SSRF-Lücke (Server-Side Request Forgery) ein beliebtes Ziel.
Warum braucht Cilium eine eigene DNS-Regel?
Weil ein ipBlock mit 0.0.0.0/0 in Cilium nicht das ist, wonach er aussieht. Die Cilium-Dokumentation sagt es deutlich: CIDR-Regeln gelten nicht für Verkehr, bei dem beide Seiten von Cilium verwaltet werden, und ipBlock-Regeln treffen standardmäßig keine Pod- oder Node-IPs im Cluster. CoreDNS ist ein Pod im Cluster – also fällt er durch.
Das Symptom ist tückisch: Verbindungen zu IP-Adressen funktionieren, Namen lösen sich nicht mehr auf. Node.js meldet EAI_AGAIN, und wer nur auf den Pod-Status schaut, sieht alles grün. Die DNS-Regel gehört deshalb an den Anfang jeder Egress-Policy.
Welche Stolperfallen gibt es?
- Ein fest eingetragener Controller-Namespace. Wer neben ingress-nginx Envoy Gateway installiert, um Hosts schrittweise umzuziehen, hat zwei Controller in zwei Namespaces. Steht in der Policy nur
ingress-nginx, werden die Envoy-Proxys abgewiesen, und jeder umgezogene Host liefert einen Fehler statt der App. - Monitoring, das von außen abfragt. Ein Prometheus im Namespace
monitoring, der/metricsder Pods abholt, wird nach der Isolation abgewiesen; sein Namespace gehört ausdrücklich in die Ingress-Regel. - Aufrufe über Namespace-Grenzen. Ein Frontend, das die API eines anderen Namespaces über den Cluster-DNS ruft, erreicht sie nicht mehr. Entweder liegen beide in einer Umgebung, oder der Aufruf geht über den öffentlichen Host.
- Jobs mit eigenem Bedarf. Migrationen, Backups nach S3 und Webhooks brauchen Egress – die Baseline lässt ihn offen. Wer Egress später verschärft, prüft jeden CronJob.
- Policies, die still veralten. Ein Controller kommt dazu oder geht, die Policy bleibt. Das fällt erst auf, wenn ein Host umzieht – die Liste der zugelassenen Namespaces muss dem Cluster folgen, nicht einem Wiki-Eintrag.
Wie isoliert Clusterward Umgebungen?
In Clusterward ist die Isolation ein Schalter pro Umgebung: genau die zwei Policies von oben (bk-baseline-ingress und bk-baseline-egress), idempotent in den Namespace geschrieben. Zugelassen werden die Namespaces der gesunden Ingress-Controller des Clusters – nginx, Envoy Gateway oder Traefik. Vor dem Isolieren liest Clusterward neu ein, welche Controller wirklich installiert sind; kommt später einer dazu oder fällt einer weg, passt es die Ingress-Policy jeder isolierten Umgebung auf dem Cluster selbst an und hält das im Audit-Log fest. Eine bewusst entfernte Egress-Policy legt es dabei nicht wieder an.
Angeboten wird die Isolation nur, wo sie keine App abschneiden kann: auf einem Kapsule-Cluster mit hinterlegtem Zugang und mindestens einem installierten Ingress-Controller – sonst erscheint der Schalter nicht. Der Zustand ist gespeichert und wird täglich geprüft: Jede Umgebung trägt den Chip „Isolated“ oder „Open to the cluster“, und unter Settings → Security stehen offene Umgebungen zuerst. Neue Umgebungen lassen sich beim Anlegen isolieren, wirksam nach dem ersten erfolgreichen Rollout; in Tenant-Pipelines ist sie in jedem neuen Environment-Block vorausgewählt, und jeder Tenant der Pipeline startet isoliert. Mehr unter Sicherheit & Zugriff und Netzwerk & Ingress.
Fazit
Namespaces ordnen, Network Policies trennen. Eine Baseline aus zwei Policies – eingehend nur Ingress-Controller und Nachbarn, ausgehend alles außer dem Metadatenbereich, DNS ausdrücklich zuerst – schützt Umgebungen und Kunden voreinander, ohne laufende Apps zu brechen. Der schwierige Teil ist nicht das YAML, sondern dass die Liste der Controller aktuell bleibt.
Ihre Umgebungen sauber trennen? Erzählen Sie uns, wie viele Kunden und Umgebungen auf Ihrem Cluster laufen. Wir zeigen, wie die Isolation bei Ihnen aussähe. Frage stellen →
Quellen und weiterführende Links
Häufige Fragen
- Nein. Ohne Network Policy ist ein Pod weder für eingehenden noch für ausgehenden Verkehr isoliert, und jeder Pod erreicht jeden anderen, auch über Namespace-Grenzen hinweg. Namespaces trennen Namen, Berechtigungen und Quotas. Erst eine Network Policy, die ein Netzwerk-Plugin wie Cilium durchsetzt, schränkt den Verkehr zwischen Namespaces ein.