Multi-Tenancy mit Namespaces
Der Einstieg, den die meisten Platform-Teams nehmen.
von PlatPrep
Namespace-Isolation ist kein einzelnes Kubernetes-Feature. Es ist ein Stack aus mehreren Schichten, die zusammen Tenants ausreichend voneinander trennen — und jede Schicht schützt gegen einen anderen Angriffsvektor. Wer im Interview “wir trennen Teams über Namespaces” sagt, bekommt garantiert die Nachfrage: Welche Schichten genau, und wogegen helfen sie?
RBAC ist die erste Schicht: Teams haben Rechte nur in ihren eigenen Namespaces. Das Standardmuster sind zentral definierte ClusterRoles, die per RoleBinding namespace-scoped gebunden werden — eine Rollendefinition, beliebig viele Team-Namespaces. Wichtig ist, die versteckten Eskalationspfade zu kennen: Wer Pods erstellen darf, kann jeden ServiceAccount seines Namespaces übernehmen; wer Secrets lesen darf, hat dessen Credentials. RBAC begrenzt API-Zugriff — gegen Netzwerk- oder Ressourcen-Probleme hilft es gar nicht.
NetworkPolicies kontrollieren den Traffic zwischen Namespaces, denn ohne sie ist ein Kubernetes-Cluster netzwerkseitig flach: Jeder Pod erreicht jeden Pod. Das solide Grundsetup ist Default-Deny pro Namespace plus explizite Freigaben:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: team-payments
spec:
podSelector: {}
policyTypes: ["Ingress"]
Dazu Ausnahmen für den Ingress-Controller, das Monitoring (Prometheus muss zum Scrapen in jeden Namespace) und definierte Service-Abhängigkeiten, jeweils per Namespace-Selektor statt über IP-Ranges. Zwei Dinge gehen hier in der Praxis regelmäßig schief: DNS vergessen (ohne Egress-Freigabe zu CoreDNS löst nichts mehr auf, sobald man auch Egress einschränkt) und vergessen, dass NetworkPolicies nur wirken, wenn das CNI sie durchsetzt. Mit Cilium bekommst du zusätzlich L7-Regeln und besseres Debugging — siehe Cilium und eBPF-NetworkPolicies.
ResourceQuotas und LimitRanges verhindern Noisy-Neighbor-Probleme. Die Arbeitsteilung: LimitRange setzt Defaults und Maxima pro Container — auch für Teams, die nie Requests definieren würden —, die ResourceQuota deckelt den Namespace insgesamt (CPU, Memory, aber auch Objektanzahl wie Services oder PVCs). Ohne Quota kann ein einzelnes fehlkonfiguriertes Deployment mit 50 Replicas das Autoscaling des ganzen Clusters in die Höhe treiben — die Rechnung zahlt die Plattform. Eine Quota macht daraus ein Team-Problem mit klarer Fehlermeldung.
Pod Security Standards steuern, was Pods dürfen. Durchgesetzt werden sie über Namespace-Labels:
metadata:
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/warn: restricted
Das restricted-Profil verbietet privilegierte Container, HostPath-Volumes, Host-Netzwerk und Privilege Escalation — also genau die Konfigurationen, mit denen ein Pod aus seiner Isolation auf den Node ausbricht. Das sollte Default für alle Tenant-Namespaces sein, mit dokumentiertem Opt-out-Prozess für die wenigen Workloads, die wirklich mehr brauchen. Wo die eingebauten Profile zu grob sind, übernehmen Admission-Policies mit Kyverno die Feinarbeit.
Eine fünfte Schicht wird oft vergessen: Scheduling-Isolation. Manche Tenants dürfen sich aus Compliance-Gründen keine Nodes mit anderen teilen — etwa wenn ein Team personenbezogene Gesundheitsdaten verarbeitet. Dafür gibt es dedizierte Node-Pools mit Taints, die nur die passenden Workloads per Toleration betreten dürfen, plus nodeSelector oder Node-Affinity auf Tenant-Seite. Das kostet Bin-Packing-Effizienz und damit Geld, ist aber deutlich billiger als ein separater Cluster. PriorityClasses gehören in dieselbe Kategorie: Ohne sie kann ein Batch-Job-Tenant bei Ressourcenknappheit die latenzkritischen Services eines anderen Teams verdrängen.
Die Grenze des Modells — und die Automatisierung
Namespaces isolieren nur, was namespace-scoped ist. CRDs, ClusterRoles, Webhooks, Nodes und deren Konfiguration sind cluster-weit: Ein Tenant, der einen eigenen Operator mit CRDs installieren will, sprengt das Modell, und einen kompromittierten Kernel auf einem geteilten Node fängt keine der vier Schichten. Außerdem teilen sich alle Tenants eine Control Plane — ein Team, das die API mit Requests flutet, trifft alle. Wer Tenants hat, die Cluster-Admin-artige Freiheiten brauchen, oder harte Compliance-Grenzen, landet bei vClusters (eigene virtuelle Control Plane pro Tenant auf geteilter Infrastruktur) oder bei physisch getrennten Clustern. Die Kostenleiter ist dabei klar: Namespaces sind fast gratis, vClusters günstig, dedizierte Cluster teuer in Geld und Betrieb.
Der wichtigste Praxis-Tipp zum Schluss: Diese vier Schichten dürfen kein manueller Prozess sein. Ein vergessenes NetworkPolicy bei Namespace Nummer 73 ist eine Sicherheitslücke, die monatelang niemand bemerkt — Default-Deny gibt schließlich keine Fehlermeldung, wenn es fehlt. Deshalb gehört Namespace-Provisionierung automatisiert: Kyverno-Generate-Policies, die bei jeder Namespace-Erstellung NetworkPolicy, Quota, LimitRange und RoleBindings erzeugen und per synchronize auch wiederherstellen, wenn jemand sie löscht. Alternativ ein Helm-Chart oder Controller fürs Namespace-Setup — Hauptsache, der Standard entsteht ohne Checkliste.
Isolation ist kein binärer Zustand, sondern ein Spektrum von “alles in einem Namespace” bis “jedes Team sein eigener Cluster”. Die richtige Position hängt von Compliance-Anforderungen, Team-Reife und Budget ab — und die starke Interview-Antwort benennt genau diese Abwägung, statt eine Patentlösung zu verkaufen. Die Grundlagen aller vier Schichten findest du im Kubernetes-Lernpfad.