3、基于命名空间的软隔离:命名空间(Namespace)作为租户边界、ResourceQuota与LimitRange配合网络隔离
在多租户 Kubernetes 集群中,命名空间(Namespace)是最基础、最轻量的隔离单元。它不提供硬性的安全边界(如虚拟化或 CVE 级别的隔离),但通过逻辑分组、资源配额与网络策略的组合,能够实现面向租户的软隔离。本章聚焦于如何以 Namespace 为租户边界,配合 ResourceQuota、LimitRange 以及网络策略,构建一套可落地、可审计的多租户隔离方案。
3.1 命名空间作为租户边界的核心模型
每个租户对应一个独立的 Namespace,所有属于该租户的工作负载、配置、服务都部署在该 Namespace 内。这种模型的核心优势在于:
- 资源命名隔离:不同 Namespace 中的资源可以同名,互不冲突。
- 权限控制锚点:RBAC 规则可以精确绑定到 Namespace 级别,实现租户管理员自治。
- 网络策略作用域:NetworkPolicy 默认作用于 Namespace 内的 Pod,天然支持租户间流量阻断。
- 资源配额挂载点:ResourceQuota 和 LimitRange 直接挂载在 Namespace 上,限制租户的资源消耗上限。
tenant-a-prod),一个用于开发/测试(如 tenant-a-dev)。这有助于在租户内部进一步隔离环境,同时保持配额管理的灵活性。
3.2 ResourceQuota:租户资源上限的硬约束
ResourceQuota 是 Kubernetes 内置的准入控制机制,用于限制一个 Namespace 内所有 Pod 的资源总和上限。它防止单个租户过度消耗集群资源,保障其他租户的服务质量。
3.2.1 核心配额维度
| 配额维度 | 描述 | 示例值 |
|---|---|---|
requests.cpu |
所有 Pod CPU 请求总和上限 | 8 |
requests.memory |
所有 Pod 内存请求总和上限 | 32Gi |
limits.cpu |
所有 Pod CPU 限制总和上限 | 16 |
limits.memory |
所有 Pod 内存限制总和上限 | 64Gi |
pods |
Namespace 中允许的最大 Pod 数量 | 20 |
services |
Namespace 中允许的最大 Service 数量 | 10 |
persistentvolumeclaims |
Namespace 中允许的最大 PVC 数量 | 5 |
3.2.2 典型 ResourceQuota 配置示例
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-a-quota
namespace: tenant-a
spec:
hard:
requests.cpu: "8"
requests.memory: "32Gi"
limits.cpu: "16"
limits.memory: "64Gi"
pods: "20"
services: "10"
persistentvolumeclaims: "5"
configmaps: "10"
secrets: "10"
3.3 LimitRange:单个 Pod 的资源规格约束
LimitRange 在 Namespace 级别设置 Pod 和容器的默认资源请求/限制,以及最小/最大规格。它弥补了 ResourceQuota 无法约束单个 Pod 的缺陷,确保每个 Pod 的资源声明在合理范围内。
3.3.1 LimitRange 的核心能力
- 默认值注入:如果 Pod 未显式设置资源 request/limit,LimitRange 会自动注入默认值。
- 最小/最大约束:限制单个 Pod 或容器的资源规格不能低于最小值或超过最大值。
- 比例约束:强制 limit/request 的比例,防止过度超卖。
3.3.2 典型 LimitRange 配置示例
apiVersion: v1
kind: LimitRange
metadata:
name: tenant-a-limits
namespace: tenant-a
spec:
limits:
- max:
cpu: "2"
memory: "4Gi"
min:
cpu: "100m"
memory: "128Mi"
default:
cpu: "500m"
memory: "1Gi"
defaultRequest:
cpu: "200m"
memory: "512Mi"
type: Container
3.3.3 ResourceQuota 与 LimitRange 的配合关系
| 维度 | ResourceQuota 作用 | LimitRange 作用 | 配合效果 |
|---|---|---|---|
| 资源总量 | 限制 Namespace 内所有 Pod 的资源总和 | 不涉及 | 防止租户整体资源超限 |
| 单 Pod 规格 | 不涉及 | 限制单个 Pod 的最小/最大资源 | 防止单个 Pod 规格过大或过小 |
| 默认值 | 不涉及 | 为未显式声明的 Pod 注入默认值 | 确保所有 Pod 都有资源声明,配额计算准确 |
| 超卖控制 | 限制 limits 总和 | 限制 limit/request 比例 | 双重保障,避免资源争抢 |
3.4 网络隔离策略的配合
仅靠 Namespace 逻辑分组无法实现网络层面的隔离。默认情况下,不同 Namespace 中的 Pod 可以互相通信。要实现租户间的网络隔离,必须显式部署 NetworkPolicy。
3.4.1 默认拒绝所有入站流量
在每个租户 Namespace 中部署一条默认拒绝入站的 NetworkPolicy,确保外部流量无法直接访问该 Namespace 内的 Pod。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: tenant-a
spec:
podSelector: {}
policyTypes:
- Ingress
3.4.2 允许同 Namespace 内部通信
在默认拒绝的基础上,显式允许同 Namespace 内的 Pod 互相通信,保障租户内部服务正常调用。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: tenant-a
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: tenant-a
policyTypes:
- Ingress
3.4.3 跨租户通信的白名单机制
如果某些场景需要跨租户通信(如共享监控服务),必须通过显式的 NetworkPolicy 白名单开放。这要求运维团队建立严格的审批流程。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring-from-tenant-b
namespace: tenant-a
spec:
podSelector:
matchLabels:
app: metrics-exporter
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: tenant-b
podSelector:
matchLabels:
app: prometheus
policyTypes:
- Ingress
3.5 软隔离方案的局限性
基于 Namespace 的软隔离方案虽然轻量、易管理,但存在以下局限性,需要在架构设计时充分考虑:
| 局限性 | 说明 | 缓解措施 |
|---|---|---|
| 共享内核 | 所有 Pod 共享同一宿主机内核,存在内核级逃逸风险 | 结合 Pod Security Admission 或使用 gVisor/Kata Containers |
| 网络策略覆盖范围 | NetworkPolicy 仅控制 L3/L4 流量,无法管控 L7 应用层 | 引入 Service Mesh(如 Istio)实现 L7 策略 |
| CNI 插件依赖 | NetworkPolicy 需要 CNI 插件支持(如 Calico、Cilium) | 选择支持 NetworkPolicy 的 CNI 插件,并验证其行为 |
| 资源配额粒度 | ResourceQuota 无法区分不同优先级的工作负载 | 结合 PriorityClass 和资源预留机制 |
| 运维复杂度 | 租户数量增多时,Namespace 和策略管理成本上升 | 使用 GitOps 和策略即代码(如 Kyverno)自动化管理 |