"Multi-tenancy" verbergt een hoop. De meeste teams die zeggen dat ze een multi-tenant Kubernetes cluster draaien, bedoelen eigenlijk een handjevol interne teams die namespaces delen onder een vertrouwensaanname die nog nooit is opgeschreven. Dat is prima, zolang iedereen dat toch weet. Het wordt pas vervelend als die term wordt aangezien voor een beveiligingsmodel.
De Kubernetes documentatie is er zelf verfrissend direct over. De RBAC Good Practices pagina zegt letterlijk dat "boundaries within a namespace should be considered weak". De Kubernetes Multi-Tenancy Working Group heeft haar belangrijkste repository in stilte in 2023 gearchiveerd. De Hierarchical Namespace Controller, ooit het paradepaardje voor namespace-hiërarchie, werd in april 2025 gearchiveerd. Tegelijkertijd gaf 88% van de organisaties in de CNCF 2024 Annual Survey aan dat ze namespaces gebruiken om applicaties binnen een cluster te scheiden, een sprong van 16 procentpunten ten opzichte van het jaar ervoor. De industrie leunt harder op namespace-gebaseerde multi-tenancy precies op het moment dat het Kubernetes-project zelf afstand neemt van de term.
Dit artikel is het veldboek dat ik zelf graag had gehad toen ik de eerste versie van deze post schreef. Het neemt een positie in. De tactische lagen doen ertoe en ik loop ze stuk voor stuk na. Maar de echte vraag is simpeler dan al die lagen bij elkaar, en de meeste teams slaan haar over.
TL;DR
- "Multi-tenancy" is eigenlijk een vertrouwensmodel in vermomming. De enige vraag die ertoe doet is hoeveel je tenants elkaar vertrouwen.
- Namespaces, RBAC, ResourceQuota en LimitRange geven je clusterhygiëne. Ze doen op zichzelf niks om de ene tenant van de andere te isoleren. De Kubernetes docs noemen namespacegrenzen expliciet "zwak".
- Het noisy-neighbor probleem op de control plane los je op met API Priority and Fairness, stable sinds Kubernetes 1.29. De meeste artikelen slaan dat onderwerp over.
- Voor untrusted tenants grijp je naar gesandboxte runtimes (gVisor, Kata Containers), virtual clusters (vCluster) of losse clusters. Nog meer admission policies dichten het gat gewoon niet.
- CVE-2025-1974 (IngressNightmare) en het aflopen van ingress-nginx in maart 2026 zijn de duidelijkste waarschuwingsschoten tegen het idee dat gedeelde cluster-scoped objecten een tenantgrens zouden zijn.
Inhoudsopgave
- Wat "multi-tenancy" eigenlijk verbergt
- De enige vraag die ertoe doet: hoeveel vertrouwen tenants elkaar?
- Wat namespaces je geven, en wat niet
- Het noisy-neighbor probleem is eigenlijk twee problemen
- Policy-as-code: Kyverno is net gegradueerd, Gatekeeper is er nog
- Network policies: het plafond ligt lager dan veel teams denken
- Drie vormen van isolatietheater
- Kostentoerekening: showback leert, chargeback dwingt af
- Wanneer namespaces niet genoeg zijn
- Belangrijkste punten
Wat "multi-tenancy" eigenlijk verbergt
De Kubernetes documentatie over multi-tenancy waarschuwt je al in de eerste alinea dat de termen "hard" en "soft" multi-tenancy "can often be confusing, as there is no single definition that will apply to all users". Het noemt hardheid een "broad spectrum" en geen categorie. Daarna kantelt de pagina naar een eerlijker invalshoek: de echte as is hoeveel je tenants elkaar vertrouwen.
Die framing vind ik zelf nog te beleefd. Wat ik er graag van maak, is dit.
"Multi-tenancy" in Kubernetes dekt minstens drie heel verschillende situaties:
- Meerdere productteams binnen één bedrijf delen een cluster om op operations te besparen.
- Een SaaS-platform draait één applicatie-instantie per klant, allemaal op hetzelfde cluster.
- Een platform voert willekeurige, untrusted gebruikerscode uit (AI execution environments, CI runners voor open-source repo's, een notebookdienst).
Van een afstandje lijken die drie op elkaar. Iedere tenant krijgt een namespace, iedere namespace krijgt een quotum, ieder team krijgt een RBAC binding. Alleen liggen de dreigingsmodellen niet eens op hetzelfde continent. Scenario één gaat erover dat collega's per ongeluk een pod zonder memory limit deployen. Scenario drie gaat erover dat iemand met opzet uit zijn container probeert te breken om de secrets van een andere tenant uit te lezen.
Precies daarom heeft het Kubernetes-project de Multi-Tenancy Working Group gearchiveerd: er bestaat geen enkele set primitieven die alle drie de gevallen tegelijk afvangt. De werkgroep verklaarde haar eerste charter afgerond, droeg haar referentieprojecten over en trok zich terug. HNC werd twee jaar later zelf ook gearchiveerd. Dat is eerlijke engineering. Namespace-hiërarchie bleek toch niet de abstractie die teams nodig hadden, en zwaardere isolatielagen erbovenop wel.
De operator van nu blijft met een lappendeken achter. Namespaces, RBAC, ResourceQuota, NetworkPolicy, Pod Security Standards, admission webhooks, gesandboxte runtimes, virtual clusters en losse clusters zijn allemaal geldige antwoorden. Ze beantwoorden alleen wel allemaal een andere vraag. Pak je de verkeerde laag voor je vertrouwensmodel, dan krijg je óf onnodige complexiteit (scenario één met gVisor) óf schijnzekerheid (scenario drie met namespaces en één NetworkPolicy).
De rest van dit artikel gaat over de juiste laag voor de juiste vraag kiezen.
De enige vraag die ertoe doet: hoeveel vertrouwen tenants elkaar?
Vóór je één regel YAML schrijft, moet je die vraag beantwoord hebben. Zelf gebruik ik drie ruwe tiers.
Vertrouwde tenants. Interne teams binnen één bedrijf, één beveiligingsbeleid, één on-call rotatie. Je maakt je zorgen over ongelukken: een pod zonder limits, een CI runner die duizend API-connecties opent, een junior die kubectl in de verkeerde context draait. Je maakt je niet serieus zorgen dat het ene team het andere aanvalt. In die wereld is namespace per team met RBAC, ResourceQuota, LimitRange, Pod Security Standards op baseline en een default-deny NetworkPolicy genoeg. Noem het hygiëne-multi-tenancy. De meeste teams die zichzelf "multi-tenant" noemen zitten precies hier.
Semi-vertrouwde tenants. Losse producten onder één dak met verschillende risicoprofielen. Misschien raken sommige workloads gereguleerde data (PCI, patiëntendossiers) en andere niet. Misschien is er één cluster-wide operator geïnstalleerd die aan dezelfde CRD's zit die elke tenant gebruikt. Je hebt alles van tier één nodig, plus dedicated node pools die via policy worden afgedwongen, Pod Security Standards op restricted waar dat kan, en een admission controller die voorkomt dat tenants aan cluster-scoped objecten komen. Het echte werk is opschrijven wat "semi-vertrouwd" voor jouw organisatie betekent. Als het eerlijke antwoord is "weet ik eigenlijk niet", zit je waarschijnlijk al in tier drie.
Untrusted tenants. Willekeurige code van klanten, partners of het internet. Dit is de tier waarop namespace-gebaseerde multi-tenancy breekt. Je kunt geen goede wil aannemen. CVE-2024-21626 (Leaky Vessels) liet in januari 2024 zien hoe een vijandige container image via runc naar het host-filesystem kon uitbreken. CVE-2025-1974 (IngressNightmare) bewees in maart 2025 dat een ongeauthenticeerde aanvaller op het pod-netwerk de ingress-nginx controller kon overnemen en elke Secret in het cluster kon uitlezen. Wiz rapporteerde dat 43% van de cloudomgevingen op het moment van de disclosure kwetsbaar was. Voor een tier-drie cluster is het antwoord gesandboxte runtimes, virtuele control planes of losse clusters. Het antwoord is niet "schrijf betere RBAC".
Hier komt de eerlijke versie: als je niet kunt benoemen welke vertrouwenstier je cluster bedient, draai je een tier-drie cluster met tier-één controls. In dat gat wonen de incidenten.
Wat namespaces je geven, en wat niet
Een namespace is twee dingen. Het is een naam-scope, zodat tien teams allemaal een Deployment api kunnen hebben zonder botsingen. En het is een policy-scope, zodat je Role bindings, quota en Pod Security labels per tenant kunt ophangen. Dat is echte waarde. Elk patroon in dit artikel, van tier één tot tier drie, begint nog steeds bij namespaces.
Wat namespaces niet zijn, staat precies zo in de RBAC Good Practices pagina: een namespace voorkomt per ongeluk API-calls tussen tenants. Het doet op zichzelf niks om te voorkomen dat een gecompromitteerde pod via het pod-netwerk bij de pods van een andere tenant komt, gedeelde node-resources uitput, of via een kernelbug naar de host doorstoot.
De baseline voor elk "namespace-per-tenant" cluster ziet er grofweg zo uit:
# Namespace-scoped hygiëne voor tenant team-alpha.
# Tier één. Dit is de hygiënelaag.
apiVersion: v1
kind: Namespace
metadata:
name: team-alpha
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/warn: restricted
tenant: alpha
cost-center: CC-1001
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: quota
namespace: team-alpha
spec:
hard:
requests.cpu: "50"
requests.memory: 200Gi
limits.memory: 400Gi
pods: "200"
services.loadbalancers: "2"
---
apiVersion: v1
kind: LimitRange
metadata:
name: defaults
namespace: team-alpha
spec:
limits:
- type: Container
default:
memory: 256Mi
defaultRequest:
cpu: 50m
memory: 128Mi
max:
cpu: "4"
memory: 8Gi
Een paar dingen zijn het noemen waard.
Pod Security Standards worden via labels op de namespace toegepast. PSA werd stable in Kubernetes 1.25 en verving PodSecurityPolicy. Het baseline profiel blokkeert de obvious privilege escalations zoals hostNetwork, hostPID en privileged containers voor nul operationele kosten. restricted is een stuk strenger en een zinnige doelstelling voor nieuwe workloads. Als je cluster dit voor een tenantnamespace overslaat, dan accepteer je wat Kubernetes nu eenmaal default is. Noem dat wat je wilt, maar multi-tenancy is het eigenlijk niet.
LimitRange staat er om de ontwikkelaar te vangen die het vergeet. In een namespace met ResourceQuota weigert Kubernetes een pod zonder requests en limits te schedulen, en LimitRange vult die dan in zodat het werk gewoon doorloopt.
pods: "200" is een zekering. Een ontspoorde operator kan duizenden pods per minuut aanmaken. De ResourceQuota zorgt dat dát luid afgaat in plaats van dat er stilletjes een node vastloopt.
Kostenlabels horen op de namespace zelf thuis. Ik kom daar verderop bij de sectie over kostentoerekening op terug.
Het noisy-neighbor probleem is eigenlijk twee problemen
De meeste artikelen over multi-tenant Kubernetes behandelen het noisy-neighbor probleem alsof het één ding is: een pod zonder limits die de CPU van zijn buren op de node opvreet. Dat is de makkelijke. Zet requests en limits, dwing af via LimitRange, klaar.
Het tweede noisy-neighbor probleem is veel lastiger en komt bijna nergens ter sprake: de control plane.
Een tenant kan andere tenants pijn doen zonder één extra byte node-geheugen te gebruiken. Een verkeerd ingeregelde GitOps controller die duizenden objecten per minuut creëert. Een buggy operator die in een strakke loop reconciled. Een CI-pipeline die kubectl get tegen de API server aan het spammen is. Zodra de kube-apiserver requests begint te droppen, loopt leader election vol, vallen de ingebouwde controllers stil, en hangen de deployments van élke tenant. Het symptoom ziet eruit als "Kubernetes ligt eruit", niet als "tenant X is luidruchtig".
Het antwoord is API Priority and Fairness (APF). Het werd stable in Kubernetes 1.29, met de v1 API standaard aan. APF classificeert binnenkomende API-requests via FlowSchema objecten, wijst ze toe aan priority levels en laat ze binnen elk level eerlijk de wachtrij in. De default configuratie beschermt leader election en de ingebouwde controllers al tegen request-floods van tenants. In de woorden van de docs zelf: een "ill-behaved Pod that floods the API server with requests cannot prevent leader election or actions by the built-in controllers from succeeding".
Voor multi-tenant clusters is het operationele patroon simpel: maak per tenant een FlowSchema, rate-limit elke tenant naar zijn eigen PriorityLevelConfiguration, en laat de cluster-control flows op hun defaults staan. Zie het als de control-plane-variant van ResourceQuota en behandel het als verplicht zodra je cluster meer dan een handvol tenants heeft.
Over CPU limits, op één na het meest bediscussieerde onderwerp in Kubernetes (na Helm vs Kustomize): voor latency-gevoelige long-running services binnen een vertrouwde tier is de huidige consensus onder practitioners (Tim Hockin en anderen in SIG Node) om memory limits gelijk te zetten aan memory requests en CPU limits over te slaan, omdat CFS throttling tail-latency problemen veroorzaakt op nodes die verder idle staan. Voor untrusted of batch workloads in een multi-tenant cluster zijn CPU limits nog steeds de juiste keuze. De tier telt zwaarder dan de vuistregel. De open GitHub issue over CFS throttling blijft de canonieke referentie als je de details wilt.
Policy-as-code: Kyverno is net gegradueerd, Gatekeeper is er nog
Op 24 maart 2026 heeft de CNCF Kyverno tot graduated project verheven. Graduation is het signaal van de CNCF dat een project productie-schaal heeft bereikt. LinkedIn rapporteerde bij de graduation 20.000 admission requests per minuut over 230+ clusters. De CEL-based policy engine landde twee maanden eerder als v1 stable in Kyverno 1.17.
Ik heb Kyverno al behandeld voor namespace bootstrapping in mijn eerdere post over NetworkPolicy en LimitRange genereren bij het aanmaken van een namespace, dus dat ga ik hier niet overdoen. Wat er voor multi-tenancy toe doet, is wat een policy engine écht voor je doet.
Drie taken, in volgorde van belang:
- Obvious slechte configuraties blokkeren. Containers die als root draaien in een namespace die
restrictedhoort te zijn. Images zonder vastgepinde digest.hostPathvolumes. Privileged init containers. Je kunt zo 30 regels uit de Kyverno policy library halen en er nooit meer over nadenken. - De hygiënelaag voor je genereren. Als er een nieuwe namespace wordt aangemaakt met label
tenant=foo, dan automatisch zijn default-deny NetworkPolicy, zijn LimitRange en zijn Pod Security labels erbij zetten. Degeneraterules van Kyverno kunnen dat out of the box. Gatekeeper niet. - Muteren voor veilige defaults. Als iemand
runAsNonRootvergeet, zet je het erbij. Als iemand hetteamlabel weglaat, vul je het in vanuit de namespace.
De Kyverno-vs-Gatekeeper vraag komt nog steeds vaak langs. Allebei werken ze. Als je platformteam diepgaande Rego-kennis heeft, is Gatekeeper prima en geeft het je toegang tot OPA's cross-system policy logica. Voor de meeste Kubernetes-native teams is Kyverno makkelijker om mee te beginnen, omdat het Kubernetes-vormige YAML spreekt in plaats van een tweede query-taal, en resource generation en image verification als first-class features meelevert. De CEL-engine in recente Kyverno-versies dicht het meeste van het overgebleven gat met Rego voor pure validatielogica.
Eén ding lost geen van beide tools op zichzelf op: wat er gebeurt als de admission webhook zelf plat ligt. Plan ervoor. Zet failurePolicy: Fail voor security-kritische policies, houd de Kyverno- of Gatekeeper-pods buiten de tenantnamespaces zodat ze niet per ongeluk door een tenant-ResourceQuota worden gekilld, en zorg dat je een break-glass pad hebt als je policy controller het cluster om 03:00 in de greppel rijdt.
Network policies: het plafond ligt lager dan veel teams denken
De standaard Kubernetes NetworkPolicy is L3/L4. Het blijft nuttig, alleen telt de lijst dingen die het niet kan zwaarder dan de lijst dingen die het wel kan.
Het kan niet filteren op hostname. Je kunt geen "allow egress naar api.example.com" in een standaard NetworkPolicy schrijven. Je moet met IP-blokken werken, en de meeste API's die je iets schelen weigeren gewoon om zich aan een stabiele IP-range te committen. Cilium's toFQDNs lost dat op, GKE heeft z'n eigen FQDNNetworkPolicy, en upstream komt er langzaam achteraan.
Het kan niets op L7. Geen HTTP methods, geen path matching, geen headers. Wil je autorisatie op service-niveau, dan heb je een service mesh nodig.
Het versleutelt helemaal niks. Verkeer tussen pods is default plaintext. Als een node gecompromitteerd is, is elk pakketje dat er doorheen gaat dat ook.
Het is stiekem afhankelijk van je CNI. De NetworkPolicy API is alleen de spec. De enforcement leeft in welke network plugin je ook hebt geïnstalleerd. Ondersteunt die plugin geen network policies, dan accepteert Kubernetes je NetworkPolicy objecten vrolijk en doet er vervolgens precies niks mee.
De nieuwe speler op het veld is AdminNetworkPolicy (ANP) en BaselineAdminNetworkPolicy (BANP), cluster-scoped policies die een platformadmin vóór en ná tenant-eigen NetworkPolicy kan afdwingen. Dat is precies wat je voor multi-tenancy wilt: een admin-opgelegde "deny cross-namespace by default" vloer die tenants niet kunnen overschrijven. Per april 2026 is ANP nog v1alpha1, met Calico 3.30+ dat beide soorten ondersteunt. Cilium-gebruikers pakken in de tussentijd CiliumClusterwideNetworkPolicy.
Default-deny, namespace-scoped NetworkPolicy op elke tenantnamespace is het absolute minimum. Zie het als de vloer waar je vanaf vertrekt en bouw door.
Drie vormen van isolatietheater
Deze drie patronen zien eruit als isolatie. Ze zijn het niet. Ze hebben elk al iemand in productie gebrand.
Gedeelde ingress controller met path-based tenant routing. Het patroon waarbij team A /app-a krijgt en team B /app-b, bediend door één ingress-nginx deployment, en iemand in een Slack-call het "multi-tenant" noemt. De ingress controller heeft standaard cluster-brede read-access op elke Secret in het cluster, omdat hij die nodig heeft om TLS-certificaten te laden. Een RCE in de controller leest dus alle Secrets. Dat is precies wat CVE-2025-1974 (IngressNightmare) in maart 2025 aantoonde: ongeauthenticeerde toegang vanuit het pod-netwerk was voldoende om de controller over te nemen. Wiz rapporteerde dat 43% van de cloudomgevingen kwetsbaar was en 6.500 clusters hun admission webhook publiek aan het internet hadden hangen. Het ingress-nginx project is in maart 2026 met pensioen gegaan, dus er komen ook geen security patches meer. Draai je het nog voor iets boven hygiëne-multi-tenancy, dan is de migratie naar Gateway API eigenlijk al over tijd. Ik schreef een stap-voor-stap over die migratie zonder big-bang omzetting precies om deze reden.
Gedeelde CRD's als tenantlaag. Custom Resource Definitions zijn cluster-scoped. Twee tenants kunnen geen twee verschillende versies van dezelfde CRD installeren. Een tenant die CRD's kan aanmaken of wijzigen raakt alle andere tenants. In een namespace-per-tenant cluster mogen tenants doorgaans hun eigen CRD's helemaal niet beheren, wat meteen de meeste operators en een verrassend aantal Helm charts blokkeert. Als je policy zit te schrijven om één tenant "even" een CRD te laten installeren, dan vraag je de namespacegrens iets wat hij gewoon niet kan doen.
Gedeelde admission webhooks. Ook ValidatingWebhookConfiguration en MutatingWebhookConfiguration objecten zijn cluster-scoped. Een malicious of verkeerd ingerichte webhook kan cluster-breed API-verkeer breken of vergiftigen, en CVE-2022-3172 liet zien hoe een aggregated API server credential-dragende requests naar een derde partij kon redirecten. Tenants zouden deze objecten nooit moeten kunnen aanmaken. Dat klinkt obvious tot je even nakijkt wat je default RBAC aggregation eigenlijk toekent.
De rode draad: alles wat cluster-scoped is, is per definitie één gedeelde blast radius. Gebruik je het om tenants te scheiden, dan scheid je geen tenants.
Kostentoerekening: showback leert, chargeback dwingt af
Technische isolatie zonder inzicht in kosten is halve multi-tenancy. Je subsidieert het luidruchtigste team uit het algemene budget en vraagt je dan af waarom de clusterrekening blijft oplopen.
Twee modellen:
- Showback rapporteert kosten per tenant zonder iemand daadwerkelijk te belasten. Het is een leermechanisme. "Team beta heeft vorige maand voor €600 clustercapaciteit gebruikt." Dit werkt het best als het team dat het budget heeft en het team dat de uitgaven maakt dezelfde mensen zijn.
- Chargeback verplaatst echt geld. Je boekt de kosten op de budgetlijn van de tenant. Handig als niemand aan engineering-kant financiële druk voelt om te optimaliseren.
Implementatie in 2026: gebruik OpenCost, sinds oktober 2024 CNCF incubating, als je open allocation engine. Requests-based toewijzing is de verdedigbare standaard omdat die precies matcht met wat de scheduler ook echt reserveert. Label elke namespace met team, cost-center en environment en laat de kostenrapportage van je cloud-provider die labels oppikken. Op EKS kun je inmiddels custom Kubernetes labels direct doorgeven naar het AWS Cost and Usage Report.
Wanneer namespaces niet genoeg zijn
Dit is de "wanneer het geen goede fit is" sectie, en het is de belangrijkste van het hele artikel.
Als je besluit dat je meer dan hygiëne-multi-tenancy nodig hebt, heb je vier escalatiestappen. Pak de laagste stap die aan je dreigingsmodel voldoet en stop daar.
Stap 1: dedicated node pools
Taint een node pool met tenant=foo:NoSchedule, voeg de bijpassende toleration toe aan de pods van de tenant, en dwing via Kyverno of Gatekeeper af dat geen enkele andere namespace die toleration mag toevoegen. Je hebt dan per tenant hardware-isolatie binnen één cluster. GKE beveelt dit patroon expliciet aan in de enterprise multi-tenancy guide. De catch: een container escape op node-niveau compromitteert nog steeds iedereen op die node. Kernel-isolatie is onveranderd. Is het doel "voorkomen dat geheugen-hongerige batch jobs van tenant A tenant B uithongeren", dan zijn dedicated node pools het goedkoopste antwoord. Is het doel "bescherming tegen een kernel-CVE", dan helpt het je niet.
Node pools en de scheduler hebben ook een vervelende relatie. Als de pods van een tenant niet kunnen schedulen omdat hun node ongezond is, moet de failover snel gebeuren. Ik heb een aparte post over hoe je half-ready nodes helemaal buiten de scheduler houdt. Dat soort gedrag wordt alleen maar vervelender naarmate je meer tenants op één pool hebt staan.
Stap 2: gesandboxte container runtimes
gVisor, Kata Containers en Firecracker-gebaseerde runtimes onderscheppen syscalls in user space of draaien elke pod in een lichte VM. Ze blokkeren precies het type exploit dat CVE-2024-21626 gebruikte. GKE Sandbox geeft je gVisor met een node-pool annotatie; AWS Fargate draait op Firecracker micro-VM's. De trade-off is meetbare I/O overhead voor gVisor, iets hogere memory overhead voor Kata, en wat syscall-compatibiliteit edge cases. Dit is de juiste vloer op het moment dat je untrusted code van klanten draait.
Stap 3: virtual clusters
vCluster draait per tenant een volledige Kubernetes control plane (een eigen API server, een eigen controller manager, een eigen etcd of SQLite) binnen een namespace van een host-cluster. Tenants krijgen een eigen API server, hun eigen CRD's, hun eigen cluster-scoped objecten en een eigen kubectl config endpoint. De worker nodes blijven gedeeld. Het is de middenweg die ik het vaakst pak als tenants echt hun eigen cluster-scoped objecten en CRD's nodig hebben, maar de kosten van losse clusters niet te rechtvaardigen zijn. Je wilt er alsnog gesandboxte runtimes onder voor echt untrusted code, want vCluster isoleert de control plane terwijl de kernel gedeeld blijft.
Stap 4: losse clusters
Nog steeds de sterkste grens. De kosten zijn verschoven: EKS en GKE rekenen $0,10 per uur per cluster (ongeveer $73 per maand) voor de standaard control plane, en AKS rekent voor de control plane helemaal niets. Voor 20 tenants op AKS betaal je alleen nog voor nodes. Voor 50 tenants op EKS zit je op $3.650 per maand aan control-plane fees, vóórdat er één pod draait. De economie hangt echt van je cloud af, dus reken het uit voordat je ervan uitgaat dat losse clusters niet haalbaar zijn.
Een hybride is meestal het juiste antwoord. 80% van de tenants zit in één hygiëne-tier cluster, en de 20% met compliance- of vertrouwensvereisten krijgen hun eigen vCluster of een echt eigen cluster. Draai je WordPress op Kubernetes voor veel klantensites, dan maak je deze afweging al. De principes gelden op dezelfde manier.
Belangrijkste punten
- "Multi-tenancy" is een vertrouwensmodel, geen security-eigenschap. Bepaal je tier voordat je één regel YAML schrijft.
- Namespaces, RBAC, ResourceQuota en LimitRange zijn hygiëne. De Kubernetes docs noemen namespacegrenzen zwak, en dat menen ze ook.
- Het control-plane noisy-neighbor probleem is echt en wordt opgelost door API Priority and Fairness, stable sinds Kubernetes 1.29. Configureer per-tenant
FlowSchemazodra je meer dan een handvol tenants hebt. - IngressNightmare en het aflopen van ingress-nginx zijn de duidelijkste waarschuwingsschoten tegen het idee dat gedeelde cluster-scoped resources tenantgrenzen zijn. Audit je gedeelde ingress-, CRD- en webhook-oppervlak daarop.
- Voor untrusted tenants grijp je naar gesandboxte runtimes, vCluster of losse clusters. Nog meer admission policies dichten het gat niet uit zichzelf.