Multi-Tenancy v Kubernetes: jmenný prostor, kvóta zdrojů a HNC
Správa jednoho clusteru Kubernetes pro jeden tým je poměrně jednoduchá. Skutečná výzva začíná, když musíte sdílet stejný shluk mezi 10, 20, 50 týmy různé, každý s vlastními požadavky na zdroje, zabezpečení a izolaci. Nebo když svým zákazníkům nabízíte Kubernetes-as-a-service a potřebujete zajistit, aby A nemůže vidět nebo zasahovat do pracovní zátěže týmu B, nemůže dále spotřebovávat zdrojů svého rozpočtu a nemůže obejít zásady společnosti.
Kubernetes nabízí jmenný prostor jako základní izolační jednotka, ale to samo o sobě nestačí pro skutečný multi-nájem. V tomto článku uvidíme Jak vybudovat kompletní multi-nájemní systém: ResourceQuota omezit zdroje na jmenný prostor, LimitRange nastavit výchozí a maximální hodnoty na kontejner, NetworkPolicy izolovat provoz, e Řadič hierarchického jmenného prostoru (HNC) spravovat zařízení komplexní organizační systémy s dědičností politik.
Co se naučíte
- Multi-tenancy modely: jmenný prostor-na-tenanta vs cluster-na-tenanta
- ResourceQuota: Omezení CPU, paměti, úložiště a počtu objektů na jmenný prostor
- LimitRange: výchozí a maximální hodnoty pro kontejnery, prevence podů bez omezení
- NetworkPolicy pro izolaci mezi jmennými prostory
- RBAC pro nájemce: každý tým vidí pouze svůj vlastní jmenný prostor
- HNC (Hierarchical Namespace Controller): dědičnost politiky, kvóty a RBAC
- Vcluster: kompletní virtuální clustery pro silnou izolaci
- Vzor pro automatizované přihlášení tenanta
Modely s více nájmy
Před implementací si musíte vybrat správný model na základě vaší úrovně nutná izolace:
| Model | Izolace | Provozní režie | Náklady | Use Case |
|---|---|---|---|---|
| Jmenný prostor pro tým | Logické (RBAC, Share) | Bas | Minimální | Interní týmy se vzájemnou důvěrou |
| Jmenný prostor na zákazníka (soft multi-tenancy) | Logické + síť | Střední | Bas | SaaS se základní izolací |
| Virtuální cluster (vcluster) | Silné (samostatné serverové API) | Vysoký | Střední | Podnikoví zákazníci, izolace CI/CD |
| Samostatný cluster na tenanta | Kompletní | Velmi vysoký | Vysoký | Regulace, citlivá data |
ResourceQuota: Omezení pro jmenné prostory
ResourceQuota definuje souhrnné limity pro všechny zdroje v oboru názvů. Když má jmenný prostor kvótu, přichází každý požadavek na vytvoření zdroje ověřeno podle dostupné kvóty.
Úplná kvóta zdrojů pro tým
# resource-quota-team-alpha.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-alpha-quota
namespace: team-alpha
spec:
hard:
# Risorse compute
requests.cpu: "20" # max 20 vCPU richieste nel namespace
limits.cpu: "40" # max 40 vCPU limits
requests.memory: "40Gi" # max 40 GB RAM richiesta
limits.memory: "80Gi" # max 80 GB RAM limits
# Storage
requests.storage: "500Gi" # max 500 GB storage totale
persistentvolumeclaims: "20" # max 20 PVC
# Per StorageClass specifica
standard.storageclass.storage.k8s.io/requests.storage: "200Gi"
ssd.storageclass.storage.k8s.io/requests.storage: "100Gi"
# Oggetti Kubernetes
pods: "100" # max 100 Pod
services: "20"
secrets: "50"
configmaps: "50"
replicationcontrollers: "20"
services.nodeports: "0" # nessun NodePort (usiamo Ingress)
services.loadbalancers: "2" # max 2 LoadBalancer
# GPU (se applicabile)
requests.nvidia.com/gpu: "4" # max 4 GPU
# Verifica utilizzo quota
kubectl describe resourcequota team-alpha-quota -n team-alpha
# Output:
# Name: team-alpha-quota
# Resource Used Hard
# -------- --- ---
# limits.cpu 8500m 40
# limits.memory 12Gi 80Gi
# pods 35 100
# requests.cpu 4200m 20
ResourceQuota na třídu služby
# resource-quota-by-priority.yaml
# Separa le quote per classe di priorita
# Usa PriorityClass per fare QoS
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000
globalDefault: false
description: "Workload critici, non soggetti a eviction"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority
value: 100
globalDefault: true
description: "Workload batch, possono essere evicted"
---
# Quota separata per workload ad alta priorita
apiVersion: v1
kind: ResourceQuota
metadata:
name: high-priority-quota
namespace: team-alpha
spec:
hard:
pods: "10"
requests.cpu: "8"
requests.memory: "16Gi"
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values: ["high-priority"]
LimitRange: Výchozí a maximální hodnoty pro kontejnery
ResourceQuota funguje na úrovni jmenného prostoru, ale pokud Pod neurčuje resources.requests, kvóta nemůže vypočítat využití. LimitRange to řeší: nastavuje požadavek a limit výchozí pro každý kontejner a definuje minimální a maximální povolené hodnoty.
# limitrange-team-alpha.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: team-alpha-limits
namespace: team-alpha
spec:
limits:
# Valori di default per container (applicati se non specificati)
- type: Container
default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
# Massimi e minimi consentiti
max:
cpu: "4"
memory: "8Gi"
min:
cpu: "10m"
memory: "32Mi"
# Ratio max/request per prevenire burst eccessivi
maxLimitRequestRatio:
cpu: "10" # limit max 10x il request
memory: "4" # limit max 4x il request
# Per i Pod (somma di tutti i container)
- type: Pod
max:
cpu: "8"
memory: "16Gi"
# Per i PVC
- type: PersistentVolumeClaim
max:
storage: "50Gi"
min:
storage: "1Gi"
RBAC pro vícenájem
Každý tenant potřebuje pouze vidět a změnit svůj vlastní jmenný prostor. Vytvoříme vzor reprodukovatelné RBAC, které lze automatizovat pro každý nový tým:
# onboarding-team-alpha.yaml
# Script di onboarding: crea namespace + quota + limitrange + RBAC
apiVersion: v1
kind: Namespace
metadata:
name: team-alpha
labels:
team: alpha
env: production
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
---
# Gruppo di utenti: tutti i developer del team alpha
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-alpha-developers
namespace: team-alpha
subjects:
- kind: Group
name: "team-alpha"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit # ClusterRole built-in: edit permette tutto tranne RBAC e quota
apiGroup: rbac.authorization.k8s.io
---
# Tech Lead: puo anche gestire i quota (ma non cluster-admin)
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-alpha-lead
namespace: team-alpha
subjects:
- kind: User
name: "alice@company.com"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: admin # ClusterRole built-in: admin = edit + gestione RBAC nel namespace
apiGroup: rbac.authorization.k8s.io
# Verifica che il team non possa accedere ad altri namespace
kubectl auth can-i get pods --as-group=team-alpha --as=developer -n team-beta
# No
kubectl auth can-i get pods --as-group=team-alpha --as=developer -n team-alpha
# Yes
NetworkPolicy pro izolaci mezi jmennými prostory
# networkpolicy-tenant-isolation.yaml
# Isola completamente il namespace del tenant
# Permette solo traffico interno al namespace + DNS + monitoring
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tenant-isolation
namespace: team-alpha
spec:
podSelector: {} # tutti i Pod nel namespace
policyTypes:
- Ingress
- Egress
ingress:
# Traffico solo da Pod nello stesso namespace
- from:
- podSelector: {}
# Permetti dall'ingress controller (namespace ingress-nginx)
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
egress:
# Traffico solo verso Pod nello stesso namespace
- to:
- podSelector: {}
# DNS
- ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# Monitoring: permetti scrape da namespace monitoring
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
# Accesso a servizi comuni (es. database condiviso, internal APIs)
- to:
- namespaceSelector:
matchLabels:
shared-service: "true"
ports:
- protocol: TCP
port: 5432 # PostgreSQL condiviso
- protocol: TCP
port: 6379 # Redis condiviso
Řadič hierarchického jmenného prostoru (HNC)
HNC umožňuje tvořit hierarchie jmenného prostoru s dědictvím zdrojů. A ideální pro složité organizační struktury: jmenný prostor „týmu-alfa“. s podjmennými prostory "team-alpha-dev", "team-alpha-staging", "team-alpha-prod", které automaticky zdědí RBAC, NetworkPolicy, ResourceQuota a LimitRange od rodiče.
Instalace HNC
# Installa HNC con kubectl
kubectl apply -f https://github.com/kubernetes-sigs/hierarchical-namespaces/releases/download/v1.1.0/default.yaml
# Oppure con Helm
helm repo add hnc https://kubernetes-sigs.github.io/hierarchical-namespaces/
helm install hnc hnc/hnc \
--namespace hnc-system \
--create-namespace \
--version 1.1.0
# Installa il plugin kubectl per HNC
curl -L https://github.com/kubernetes-sigs/hierarchical-namespaces/releases/download/v1.1.0/kubectl-hns_linux_amd64 \
-o /usr/local/bin/kubectl-hns
chmod +x /usr/local/bin/kubectl-hns
# Verifica
kubectl hns version
Hierarchie jmenného prostoru pro tým
# Crea la gerarchia: team-alpha e il namespace root
# team-alpha-dev e team-alpha-prod sono subnamespace
# Crea il namespace root
kubectl create namespace team-alpha
# Crea i subnamespace (HNC li gestisce)
kubectl hns create team-alpha-dev -n team-alpha
kubectl hns create team-alpha-staging -n team-alpha
kubectl hns create team-alpha-prod -n team-alpha
# Visualizza la gerarchia
kubectl hns tree team-alpha
# Output:
# team-alpha
# ├── team-alpha-dev
# ├── team-alpha-staging
# └── team-alpha-prod
# Configura cosa viene propagato dai parent ai children
kubectl hns config set-resource networkpolicies --mode Propagate
kubectl hns config set-resource rolebindings --mode Propagate
kubectl hns config set-resource limitranges --mode Propagate
# ResourceQuota NON viene propagata (ogni sub-namespace ha la sua)
Automatické šíření zdrojů
# Nel namespace parent team-alpha:
# Un RoleBinding qui viene propagato automaticamente a tutti i subnamespace
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-alpha-developers
namespace: team-alpha # propagato automaticamente a tutti i children
annotations:
propagate.hnc.x-k8s.io/select: "true"
subjects:
- kind: Group
name: "team-alpha-devs"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: view # view in tutti i subnamespace
apiGroup: rbac.authorization.k8s.io
# RoleBinding specifico per prod: solo il tech lead
# Non si propaga ai children perche e in team-alpha-prod
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: prod-admin
namespace: team-alpha-prod
subjects:
- kind: User
name: "alice@company.com"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io
# Verifica propagazione
kubectl get rolebindings -n team-alpha-dev | grep team-alpha-developers
# Il RoleBinding e apparso nel subnamespace per propagazione
Virtuální cluster s vclusterem
Pro silnější izolaci vytváří vcluster plné clustery Kubernetes (s vlastním API server, plánovač a správce řadiče), které běží v rámci jmenného prostoru hostitelského clusteru. Nájemník má plný přístup ke svému vclusteru, ale nevidí hostitelský cluster.
# Installa vcluster CLI
curl -L -o vcluster "https://github.com/loft-sh/vcluster/releases/latest/download/vcluster-linux-amd64"
chmod +x vcluster
sudo mv vcluster /usr/local/bin
# Crea un virtual cluster per il team-beta
vcluster create team-beta-cluster \
--namespace vcluster-team-beta \
--connect=false \
--helm-values vcluster-values.yaml
# vcluster-values.yaml
# vcluster:
# image: ghcr.io/loft-sh/vcluster-k8s:1.30
# sync:
# nodes:
# enabled: true
# syncAllNodes: false # sync solo i nodi dove girano i Pod del vcluster
# resources:
# limits:
# cpu: "2"
# memory: "2Gi"
# Connettiti al vcluster
vcluster connect team-beta-cluster --namespace vcluster-team-beta -- kubectl get nodes
Automatizace nástupu nájemců
V klastrech s mnoha týmy se manuální zařazování neškáluje. Společný vzor a použití
vyhrazený operátor (nebo jednoduchý skript/GitOps), který automaticky vytvoří všechny
zdroje potřebné pro nového nájemce počínaje CRD Tenant:
# tenant-crd.yaml - esempio con Capsule (operator per multi-tenancy)
# Capsule e un operator CNCF che automatizza la creazione di tenant
helm repo add clastix https://clastix.github.io/charts
helm install capsule clastix/capsule \
--namespace capsule-system \
--create-namespace
---
# tenant.yaml - definisci un tenant con Capsule
apiVersion: capsule.clastix.io/v1beta2
kind: Tenant
metadata:
name: team-alpha
spec:
owners:
- name: alice@company.com
kind: User
- name: team-alpha-admins
kind: Group
namespaceOptions:
quota: 10 # max 10 namespace per questo tenant
forbiddenLabels:
denied: ["environment=production"] # il tenant non puo creare ns con certi label
resourceQuotas:
scope: Tenant # quota aggregata su tutti i namespace del tenant
items:
- hard:
requests.cpu: "50"
requests.memory: "100Gi"
requests.storage: "1Ti"
limitRanges:
items:
- limits:
- type: Container
default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
networkPolicies:
items:
- podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector: {}
nodeSelector:
kubernetes.io/os: linux
# Possibile restringere il tenant a nodi specifici:
# tenant: team-alpha
Sledování šancí
# Vedi utilizzo quota di tutti i namespace
kubectl get resourcequota -A -o custom-columns=\
"NAMESPACE:.metadata.namespace,NAME:.metadata.name,\
CPU-REQ:.status.used.requests\.cpu,CPU-LIM:.status.used.limits\.cpu,\
MEM-REQ:.status.used.requests\.memory"
# Alert Prometheus per quota vicina al limite
# Aggiungi questa regola PrometheusRule:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: namespace-quota-alerts
namespace: monitoring
spec:
groups:
- name: quota
rules:
- alert: NamespaceCPUQuotaExceeding80Percent
expr: |
kube_resourcequota{resource="requests.cpu",type="used"} /
kube_resourcequota{resource="requests.cpu",type="hard"} > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "Namespace {{ $labels.namespace }} al {{ $value | humanizePercentage }} della quota CPU"
- alert: NamespaceMemoryQuotaExceeding90Percent
expr: |
kube_resourcequota{resource="requests.memory",type="used"} /
kube_resourcequota{resource="requests.memory",type="hard"} > 0.9
for: 5m
labels:
severity: critical
annotations:
summary: "Namespace {{ $labels.namespace }} al 90% della quota memoria"
Nejlepší postupy pro vícenájem
Kontrolní seznam pro více nájemců výroby
- Jeden jmenný prostor na týmové prostředí: team-alpha-dev, team-alpha-staging, team-alpha-prod; vyhněte se míchání prostředí ve stejném jmenném prostoru
- ResourceQuota vždy definována: bez kvóty může tým spotřebovat všechny prostředky clusteru a ovlivnit ostatní nájemce
- LimitRange pro výchozí hodnoty: Zabraňuje tomu, aby moduly Pods bez požadavků na prostředky vykreslovaly kvóty zdrojů a plánování clusteru k ničemu
- NetworkPolicy default-deny: každý jmenný prostor musí mít politiku, která blokuje veškerý neautorizovaný provoz napříč jmennými prostory
- Omezené bezpečnostní standardy pod: použije omezenou úroveň na všechny jmenné prostory tenanta (viz článek 6)
- Minimální oprávnění RBAC: vývojáři používají ClusterRole
edit, Neadminocluster-admin - Audit přístupu: povolit protokol auditu ke sledování toho, kdo k čemu v každém jmenném prostoru přistupuje
- Automatizace registrace: použijte Capsule, vlastního operátora nebo manifest GitOps k vytvoření všech objektů tenanta konzistentně
Úskalí Multi-Tenancy Kubernetes
- Jmenný prostor není úplná izolace: některé objekty s rozsahem clusteru (ClusterRole, PersistentVolume, Node) jsou viditelné pro všechny klienty; Pokud potřebujete úplnou izolaci, použijte vcluster
- Chyby zabezpečení sdíleného jádra: všichni nájemci sdílejí stejné linuxové jádro; kontejner, který využívá zranitelnost jádra, může ovlivnit ostatní nájemce; Vyhodnoťte vyhrazené uzly pro nájemce s citlivými daty
- Únik DNS: Ve výchozím nastavení mohou moduly překládat názvy služeb na jiné jmenné prostory (
service.namespace.svc.cluster.local); v případě potřeby použijte NetworkPolicy k blokování provozu DNS napříč obory názvů - ResourceQuota bez LimitRange: pokud neexistuje LimitRange, pody bez požadavků na zdroje ignorují ResourceQuota a kvóta není správně škálována
Závěry a další kroky
Multi-tenancy v Kubernetes je kontinuum mezi provozní jednoduchostí a izolací silný. Pro většinu obchodních případů s interními týmy, jmenné prostory s ResourceQuota, Vhodné limity limitů, NetworkPolicy a RBAC poskytují dostatečnou izolaci minimální provozní režie. Pro podnikové zákazníky nebo scénáře s požadavky na shodu přísný, vcluster nabízí mnohem silnější úroveň izolace při zachování výhod sdíleného klastru z hlediska účinnosti zdrojů.
HNC mění správu hierarchií jmenných prostorů v něco škálovatelného: místo toho RBAC a NetworkPolicy v každém dílčím jmenném prostoru jsou definovány politiky jednou v nadřazeném jmenném prostoru a šíří se automaticky. Pro platformy s desítkami týmů to dělá rozdíl mezi udržovatelným systémem a systémem, který vyžaduje specializovaný tým pouze pro správu konfigurace jmenného prostoru.
Připravované články v sérii Kubernetes at Scale
Předchozí články
Související série
- Zabezpečení Kubernetes — Bezpečnostní standardy RBAC a Pod, předpoklady pro vícenásobný pronájem
- Platform Engineering — multi-tenancy jako základ interních vývojářských platforem
- FinOps pro Kubernetes — řízení nákladů pro jmenné prostory a nájemce







