Kubernetes のマルチテナント: ネームスペース、リソース クォータ、および HNC
単一チームの単一 Kubernetes クラスターの管理は比較的簡単です。 本当の課題は、10、20、50 のチーム間で同じクラスターを共有する必要があるときに始まります。 それぞれに独自のリソース、セキュリティ、分離要件があります。または Kubernetes-as-a-service を顧客に提供する場合、A チーム B のワークロードを確認したり干渉したりすることはできず、それ以上消費することはできません 予算のリソースを必要とするため、会社のポリシーを無視することはできません。
Kubernetes が提供するのは、 名前空間 基礎断熱ユニットとして、 しかし、それだけでは実際のマルチテナントには十分ではありません。この記事では、 完全なマルチテナント システムを構築する方法: リソースクォータ 名前空間ごとのリソースを制限するには、 制限範囲 設定する コンテナごとのデフォルトと最大値、 ネットワークポリシー トラフィックを分離するため、 e 階層型名前空間コントローラー (HNC) 施設を管理する ポリシー継承を伴う複雑な組織システム。
何を学ぶか
- マルチテナント モデル: テナントごとのネームスペースとテナントごとのクラスター
- ResourceQuota: CPU、メモリ、ストレージ、名前空間ごとのオブジェクト数の制限
- LimitRange: コンテナのデフォルトと最大値、制限のない Pod の防止
- 名前空間間の分離のための NetworkPolicy
- テナント用の RBAC: 各チームは自分の名前空間のみを参照します。
- HNC (階層型名前空間コントローラー): ポリシー、クォータ、RBAC の継承
- Vcluster: 強力な分離のための完全な仮想クラスター
- テナントの自動オンボーディングのパターン
マルチテナントモデル
実装する前に、自分のレベルに基づいて適切なモデルを選択する必要があります 必要な断熱材:
| モデル | 絶縁 | 運用上のオーバーヘッド | 料金 | 使用事例 |
|---|---|---|---|---|
| チームの名前空間 | 論理 (RBAC、共有) | ベース | 最小 | 相互信頼のある社内チーム |
| 顧客ごとの名前空間 (ソフト マルチテナント) | ロジカル+ネットワーク | 中くらい | ベース | 基本分離を備えた SaaS |
| 仮想クラスター (vcluster) | 強力 (別サーバー API) | 高い | 中くらい | エンタープライズ顧客、CI/CD 分離 |
| テナントごとに個別のクラスター | 完了 | とても背が高い | 高い | 規制、機密データ |
ResourceQuota: 名前空間の制限
ResourceQuota は、名前空間内のすべてのリソースの合計制限を定義します。 ネームスペースにクォータがある場合、すべてのリソース作成リクエストが送信されます 利用可能なクォータに対して検証されます。
チームの全リソース割り当て
# 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
サービス クラスごとのリソースクォータ
# 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: コンテナのデフォルトと最大値
ResourceQuota は名前空間レベルで動作しますが、Pod が resource.requests を指定しない場合、 クォータでは使用量を計算できません。 LimitRange はこれを解決します。リクエストと制限を設定します。 各コンテナのデフォルトであり、許可される最小値と最大値を定義します。
# 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
各テナントは、自分の名前空間を確認して変更するだけで済みます。パターンを作成しましょう 新しいチームごとに自動化できる、再現可能な RBAC:
# 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-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
階層型名前空間コントローラー (HNC)
HNC を使用すると、 名前空間の階層 の継承で リソース。複雑な組織構造に最適な「チームアルファ」名前空間 サブ名前空間「team-alpha-dev」、「team-alpha-staging」、「team-alpha-prod」 これらは、親から RBAC、NetworkPolicy、ResourceQuota、および LimitRange を自動的に継承します。
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
チームの名前空間階層
# 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)
リソースの自動伝播
# 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
vcluster を使用した仮想クラスター
より強力な分離のために、vcluster は完全な Kubernetes クラスターを作成します (独自の API サーバー、スケジューラー、コントローラー マネージャー) は名前空間内で実行されます。 ホストクラスターの。テナントは自分の vcluster に完全にアクセスできますが、 ホストクラスター。
# 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
テナントのオンボーディングの自動化
多くのチームが含まれるクラスターでは、手動オンボーディングは拡張できません。よくあるパターンと使い方
専用の Operator (または単純なスクリプト/GitOps)
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
オッズモニタリング
# 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"
マルチテナントのベスト プラクティス
本番マルチテナンシーチェックリスト
- チーム環境ごとに 1 つの名前空間: チーム-アルファ-開発、チーム-アルファ-ステージング、チーム-アルファ-製品。同じ名前空間内で環境が混在することを避ける
- ResourceQuota は常に次のように定義されます。 クォータがない場合、チームはすべてのクラスター リソースを消費し、他のテナントに影響を与える可能性があります。
- デフォルトの LimitRange: リソースリクエストのないポッドで ResourceQuota とクラスターのスケジューリングが役に立たなくなるのを防ぎます
- ネットワークポリシーのデフォルト拒否: 各名前空間には、すべての無許可の名前空間間のトラフィックをブロックするポリシーが必要です
- ポッドセキュリティ標準の制限: 制限レベルをすべてのテナント名前空間に適用します (記事 6 を参照)
- RBAC の最小権限: 開発者はClusterRoleを使用します
edit、 ないadminocluster-admin - アクセス監査: 監査ログを有効にして、各名前空間で誰が何にアクセスしているかを追跡する
- オンボーディングを自動化する: Capsule、カスタム Operator、または GitOps マニフェストを使用して、すべてのテナント オブジェクトを一貫して作成します
マルチテナント Kubernetes の落とし穴
- 名前空間は完全に分離されていません: 一部のクラスター スコープのオブジェクト (ClusterRole、PersistentVolume、Node) はすべてのテナントに表示されます。完全な分離が必要な場合は vcluster を使用してください
- 共有カーネルの脆弱性: すべてのテナントが同じ Linux カーネルを共有します。カーネルの脆弱性を悪用するコンテナは、他のテナントに影響を与える可能性があります。機密データを含むテナントの専用ノードを評価する
- DNS漏洩: デフォルトでは、Pod はサービス名を他の名前空間に解決できます (
service.namespace.svc.cluster.local);必要に応じて、NetworkPolicy を使用して名前空間間の DNS トラフィックもブロックします - LimitRange なしの ResourceQuota: LimitRange がない場合、リソースリクエストのないポッドは ResourceQuota を無視し、クォータは正しくスケーリングされません。
結論と次のステップ
Kubernetes のマルチテナンシーは、運用の簡素化と分離性の間の連続体です 強い。社内チームのほとんどのビジネス ケースでは、ResourceQuota を使用した名前空間、 適切な LimitRange、NetworkPolicy、および RBAC により、十分な分離が提供されます。 運用上のオーバーヘッドは最小限に抑えられます。企業顧客またはコンプライアンス要件のあるシナリオ向け 厳格な vcluster は、利点を維持しながら、より強力なレベルの分離を提供します。 リソース効率の観点から、共有クラスターの最適化を実現します。
HNC は、名前空間階層の管理をスケーラブルなものに変えます。 各サブ名前空間で RBAC と NetworkPolicy を手動で複製する必要があるため、定義されています ポリシーは親名前空間に一度追加され、自動的に伝播されます。プラットフォーム向け 数十のチームでは、これが保守可能なシステムと保守が必要なシステムの違いを生み出します。 名前空間の構成を管理するためだけの専任チーム。
Kubernetes at Scale シリーズの今後の記事
以前の記事
関連シリーズ
- Kubernetesのセキュリティ — RBAC およびポッド セキュリティ標準、マルチテナントの前提条件
- プラットフォームエンジニアリング — 内部開発者プラットフォームの基盤としてのマルチテナンシー
- Kubernetes 向け FinOps — ネームスペースとテナントのコスト管理







