3. 租户边界定义:Kubernetes多租户模型与RBAC设计

在多集群与Helm结合的场景下,租户边界是配额校准的基石。本章定义Kubernetes原生多租户模型、资源隔离策略以及身份与RBAC设计,确保每个租户在集群内拥有清晰、安全且可审计的操作边界。

3.1 Kubernetes多租户模型:Namespace与ClusterScope

Kubernetes本身不提供“租户”原生对象,而是通过Namespace和ClusterScope资源组合实现多租户隔离。下表对比两种作用域的核心差异:

维度 Namespace(命名空间级) ClusterScope(集群级)
资源范围 Pod、Service、ConfigMap、Secret、Deployment等 Node、PersistentVolume、ClusterRole、Namespace本身
隔离粒度 逻辑隔离,网络策略可跨Namespace 全局可见,需谨慎授权
配额控制 ResourceQuota + LimitRange 无原生配额,需通过准入控制或外部策略引擎
租户归属 每个租户独占一个或多个Namespace 集群管理员或平台服务使用
Helm部署影响 Release作用域默认绑定Namespace ClusterRole/ClusterRoleBinding需手动管理
实践建议:在多租户Helm部署中,每个租户至少分配一个专属Namespace,并将所有工作负载Release限定在该Namespace内。集群级资源(如StorageClass、ClusterRole)由平台团队统一管理,不归属任何租户。

3.2 租户资源隔离策略

资源隔离是多租户安全的核心。以下策略按隔离强度从低到高排列,适用于不同合规等级:

  1. Namespace隔离(基础):每个租户使用独立Namespace,通过ResourceQuota限制CPU/内存/PVC总量,通过LimitRange设置容器默认资源请求。
  2. 网络隔离(中等):部署NetworkPolicy,默认拒绝所有跨Namespace流量,仅允许租户内部通信及必要的监控/日志出口。
  3. 节点隔离(严格):使用NodeSelector + Taint/Toleration将租户Pod调度到专属节点池,避免资源争抢。
  4. 存储隔离(数据安全):为每个租户创建独立StorageClass或PVC命名前缀,配合RBAC限制PersistentVolume的创建与挂载。
Helm集成要点:在Chart的values.yaml中暴露tenantId参数,模板中自动注入Namespace标签、NetworkPolicy选择器以及ResourceQuota名称,实现租户级配置模板化。
租户资源隔离层次架构 租户A Namespace: tenant-a ResourceQuota LimitRange NetworkPolicy Namespace: tenant-a-dev ResourceQuota LimitRange NetworkPolicy 节点池: node-pool-tenant-a Taint: tenant=a:NoSchedule 存储类: sc-tenant-a PVC前缀: pvc-tenant-a-* 租户B Namespace: tenant-b ResourceQuota LimitRange NetworkPolicy Namespace: tenant-b-staging ResourceQuota LimitRange NetworkPolicy 节点池: node-pool-tenant-b Taint: tenant=b:NoSchedule 存储类: sc-tenant-b PVC前缀: pvc-tenant-b-* 每个租户拥有独立Namespace组、节点池、存储类,实现计算与存储的物理/逻辑双重隔离

3.3 租户身份与RBAC设计

租户身份通常映射为Kubernetes中的ServiceAccount或User,通过RBAC绑定控制权限。设计原则遵循最小权限与租户边界自包含:

  • 租户管理员角色(TenantAdmin):可在租户Namespace内创建/删除Deployment、Service、ConfigMap等资源,但无权操作集群级资源或其他租户Namespace。
  • 租户开发者角色(TenantDeveloper):仅能查看和更新已有工作负载,不能创建或删除Namespace。
  • 租户只读角色(TenantViewer):仅具备Namespace内资源的get/list/watch权限。
注意:Helm安装Release时,Tiller(或Helm 3的SDK)使用当前kubeconfig的权限。若租户管理员通过Helm部署Chart,必须确保其ServiceAccount具备在目标Namespace创建资源的权限,且不能越权修改集群级ClusterRole。

3.4 RBAC绑定与Helm模板化

以下是一个典型的租户RBAC模板片段,在Helm Chart中通过tenantId动态生成:

# templates/rbac.yaml
{{- range .Values.tenants }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: {{ .name }}-admin
  namespace: {{ .namespace }}
rules:
- apiGroups: [""]
  resources: ["pods", "services", "configmaps", "secrets"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
  resources: ["deployments", "statefulsets"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: {{ .name }}-admin-binding
  namespace: {{ .namespace }}
subjects:
- kind: ServiceAccount
  name: {{ .name }}-sa
  namespace: {{ .namespace }}
roleRef:
  kind: Role
  name: {{ .name }}-admin
  apiGroup: rbac.authorization.k8s.io
{{- end }}
关键设计:每个租户的ServiceAccount、Role、RoleBinding全部限定在租户专属Namespace内,不创建任何ClusterRole/ClusterRoleBinding。这确保了即使某个租户的凭证泄露,攻击者也无法影响其他租户或集群全局资源。
租户RBAC权限模型 租户A Namespace: tenant-a ServiceAccount tenant-a-sa Role tenant-a-admin 绑定 权限规则 pods, services, deployments: CRUD 资源范围 仅限 tenant-a Namespace 内资源 无权访问 tenant-b 或集群级资源 租户B Namespace: tenant-b ServiceAccount tenant-b-sa Role tenant-b-developer 绑定 权限规则 pods, services: get/list/watch/update 资源范围 仅限 tenant-b Namespace 内资源 无权创建/删除资源 每个租户的ServiceAccount仅绑定到本Namespace的Role,实现租户间权限完全隔离

3.5 租户边界设计清单

在Helm接入多集群拓扑前,请逐项确认以下设计要点:

检查项 描述 Helm集成方式
Namespace分配 每个租户至少一个专属Namespace values.yaml中定义tenants[].namespace
ResourceQuota 限制CPU/内存/PVC数量 模板中根据tenantId生成Quota对象
NetworkPolicy 默认拒绝跨Namespace流量 模板中生成隔离策略,允许监控出口
ServiceAccount 每个租户独立SA,不共享 模板中创建{{ .name }}-sa
Role/RoleBinding 仅限Namespace内权限,无ClusterRole 模板中生成Role并绑定SA
节点亲和性 可选:将租户绑定到专属节点池 模板中注入nodeSelector与tolerations
存储隔离 PVC命名前缀或独立StorageClass 模板中拼接pvc-{{ .name }}-前缀
下一步准备:完成租户边界定义后,即可进入第4章“多集群拓扑与Helm Release映射”,将本章定义的租户模型映射到实际的多集群部署拓扑中。