
K8s 多租户隔离Namespace 够不够什么时候该上虚拟集群一、你把 15 个团队塞进同一个集群的 Namespace结果一个 OOM 全挂了用 Namespace 做多租户隔离是 K8s 入门的标准做法——简单、免费、开箱即用。但团队数从 3 个涨到 15 个以后问题逐个浮现某个 Pod 的 memory leak 导致节点 OOM连带干掉同节点的另外 4 个团队的 Pod。某个 Tenant 把 LoadBalancer 配额吃满后面的 Tenant 创建 Service 报错。某个 Tenant 的 Pod 通过 Service DNS 发现了另一个 Namespace 的服务并直接调用。Namespace 隔离的是 RBAC 和网络策略层面的权限但它不隔离内核资源CPU、内存、网络带宽和节点故障域。15 个团队如果在同一个集群的不同 Namespace它们共享同一个控制平面apiserver、etcd共享同一个节点池。任何一个 Tenant 的行为异常都可能造成全集群的影响。那什么时候该升级到虚拟集群vCluster、Cluster API或物理集群判断标准不是团队数量而是三件事是否有硬性资源隔离需求、是否有独立的控制平面配置需求、是否有安全合规的强隔离需求。二、底层机制与原理剖析Namespace 和虚拟集群的隔离层级差异可以清晰地对照出来flowchart TD subgraph Namespace级别隔离 A[Cluster] -- B[Namespace A] A -- C[Namespace B] B -- B1[Pod A1] B -- B2[Pod A2] C -- C1[Pod B1] B1 -.- D[共享内核] C1 -.- D B1 -.- E[共享 apiserver] C1 -.- E end subgraph 虚拟集群级别隔离 F[Host Cluster] -- G[vCluster A] F -- H[vCluster B] G -- G1[独立 apiserver] G -- G2[独立 etcd/存储] G1 -- G3[Pod A1] G -- G4[Pod A2] H -- H1[独立 apiserver] H -- H2[独立 etcd/存储] H1 -- H3[Pod B1] G3 -.- I[共享内核 节点池] H3 -.- I end subgraph 物理集群级别隔离 J[Cluster A] -- K[独立节点池] L[Cluster B] -- M[独立节点池] K -.- N[完全物理隔离] M -.- N end三层隔离的对比隔离维度Namespace虚拟集群物理集群控制平面共享单 apiserver每个 vCluster 独立 apiserver完全独立CPU/内存依赖 ResourceQuota依赖 ResourceQuota 节点亲和物理隔离CRD 管理共享 CRD 定义独立 CRD独立 CRD成本几乎零低每个 vCluster 额外 ~100MB 内存高独立控制平面运维复杂度低中高三、生产级代码实现Namespace 级别的多租户资源隔离配置ResourceQuota LimitRange NetworkPolicy# 1. ResourceQuota命名空间级硬限制 apiVersion: v1 kind: ResourceQuota metadata: name: tenant-a-quota namespace: tenant-a spec: hard: # CPU 和内存总量限制 requests.cpu: 50 requests.memory: 100Gi limits.cpu: 100 limits.memory: 200Gi # 防止单个 Tenant 创建过多对象 pods: 200 services: 50 services.loadbalancers: 5 persistentvolumeclaims: 20 configmaps: 100 secrets: 100 # 防止单个 Tenant 耗尽集群 PVC 总存储 requests.storage: 1Ti --- # 2. LimitRangePod 级默认限制防止未设 limit 的 Pod 恶意占用 apiVersion: v1 kind: LimitRange metadata: name: tenant-a-limits namespace: tenant-a spec: limits: - type: Container default: # 默认 limit没有指定资源限制的容器强制使用此值 cpu: 500m memory: 512Mi defaultRequest: # 默认 request cpu: 100m memory: 128Mi max: # 单个容器最大资源限制——防止超大吃掉节点 cpu: 8 memory: 16Gi min: cpu: 10m memory: 32Mi --- # 3. NetworkPolicy禁止跨 Namespace 的入站流量 # 设计决策默认拒绝 白名单放行 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-cross-namespace namespace: tenant-a spec: podSelector: {} policyTypes: - Ingress ingress: # 只允许同 Namespace 内的 Pod 互相访问 - from: - podSelector: {} # 允许 ingress controller 的流量从 ingress-nginx namespace 来 - from: - namespaceSelector: matchLabels: name: ingress-nginx升级到虚拟集群vCluster的配置# vcluster.yaml — 虚拟集群定义 # 使用 vCluster CLI 或 Helm chart 创建 # 设计决策虚拟集群继承了宿主机群的网络CNI、存储CSI和节点池 # 但提供了独立的 apiserver、scheduler、controller-manager可选 apiVersion: v1 kind: Namespace metadata: name: vcluster-tenant-a --- # vCluster 配置通过 Helm values sync: nodes: enabled: true # 同步节点信息到虚拟集群让 Tenant 感知到真实的节点拓扑 persistentvolumes: enabled: true storageclasses: enabled: true ingresses: enabled: true # 虚拟集群内资源的限制防止 Tenant 在 vCluster 内创建过多资源 policy: centralAdmission: validatingWebhooks: - name: resource-limits.kyverno.io # 资源使用控制 resources: limits: # vCluster 控制平面本身的资源 coredns: requests: cpu: 100m memory: 64Mi limits: cpu: 200m memory: 128Mi判断何时升级的决策函数Go 伪代码package isolation // IsolationLevel 多租户隔离级别 type IsolationLevel int const ( NamespaceOnly IsolationLevel iota // 仅 Namespace VirtualCluster // 虚拟集群 PhysicalCluster // 物理集群 ) // TenantProfile 租户画像 type TenantProfile struct { Name string TeamSize int // 团队人数 PodCount int // 当前 Pod 数 AvgCPUUsage float64 // 平均 CPU 使用率(核) RequiresCustomCRD bool // 是否需要安装自定义 CRD ComplianceLevel string // 合规要求: low/medium/high CanShareNode bool // 能否与其他 Tenant 共享节点 } // RecommendIsolation 推荐隔离级别 func RecommendIsolation(tenant TenantProfile) IsolationLevel { // 规则 1合规要求高 - 物理集群 if tenant.ComplianceLevel high { return PhysicalCluster } // 规则 2需要独立 CRD - 至少虚拟集群 if tenant.RequiresCustomCRD { return VirtualCluster } // 规则 3资源占用大且不能共享节点 - 至少虚拟集群 if tenant.AvgCPUUsage 20 !tenant.CanShareNode { return VirtualCluster } // 规则 4大规模 Pod - 至少虚拟集群 // 共享 apiserver 对大量 Pod 创建/更新事件敏感 if tenant.PodCount 500 { return VirtualCluster } // 默认Namespace 足够 return NamespaceOnly }四、边界分析与架构权衡Namespace 隔离的不足核心问题是不隔离控制平面故障域。一个 Tenant 的大量 Pod 创建/删除操作可能拖慢全集群的 apiserver 响应。CRD 是集群级资源任何 Tenant 安装的 CRD 对所有 Namespace 生效。ResourceQuota 只能限制总量不限制突发行为——一个 Tenant 可能在 1 秒内创建 200 个 Pod 并瞬间释放虽然总量没超但对 apiserver 的冲击是真实的。虚拟集群的缺点每个虚拟集群额外消耗 ~100MB 内存和少量 CPU 用于控制平面15 个虚拟集群就是 1.5GB 的额外开销。vCluster 的生命周期管理引入了新的运维负担——升级、备份、故障恢复。另外虚拟集群的网络模型依赖宿主集群的 CNI某些 CNI 插件的 NetworkPolicy 在 vCluster 场景下可能表现异常。适用边界Namespace 适合 10 人以下、无独立 CRD 需求、无强合规要求的团队。虚拟集群适合需要独立 apiserver、需要自定义 CRD 或准入控制器、租户规模在 100-500 Pod 的场景。物理集群适合合规强制隔离的场景。禁用场景不要为了技术先进性盲目升级到虚拟集群。如果 3 个团队、每个团队 20 个 PodNamespace ResourceQuota 完全够用。也不要在 CNI 不成熟的集群上用虚拟集群网络策略失效会导致跨租户数据泄漏。五、总结多租户隔离是逐级递进的Namespace → 虚拟集群 → 物理集群每一步增加成本和运维复杂度但也解决上一层解决不了的问题。核心决策依据是否需要独立的 apiserver决定是否上虚拟集群、是否必须物理隔离决定是否上物理集群。大多数场景下Namespace ResourceQuota NetworkPolicy 已经足够不要过早优化。