3. 多租户模型设计:租户隔离策略与资源配额管理

在多租户 Kubernetes 集群中,租户隔离是保障安全性与稳定性的核心。本章围绕 Namespace、RBAC、NetworkPolicy 三大隔离支柱,结合资源配额管理,构建一套可落地、可审计的多租户模型。该模型与 Argo CD 的 ApplicationSet 及 Project 配置深度绑定,实现“声明式租户定义”。

3.1 租户隔离的三层模型

我们将租户隔离拆解为三个逻辑层,每一层解决不同维度的隔离问题:

隔离层 核心机制 隔离目标 Argo CD 关联
工作负载隔离 Namespace Pod、Service、ConfigMap 等资源命名空间隔离 Application 的 destination.namespace
权限隔离 RBAC (Role / RoleBinding) 租户管理员/开发者/只读用户的细粒度访问控制 Argo CD Project 的 sourceNamespaces 与 role 绑定
网络隔离 NetworkPolicy Pod 间、Namespace 间、外部流量访问控制 Application 中作为资源清单同步
设计原则: 三层隔离必须同时生效,缺一不可。仅靠 Namespace 无法阻止跨命名空间的网络通信或越权操作;仅靠 RBAC 无法限制 Pod 级别的流量攻击。

3.2 Namespace 策略:租户边界定义

每个租户对应一个或多个 Namespace。我们采用 “一租户一主 Namespace + 可选子 Namespace” 的扁平化结构,避免过深的层级嵌套导致管理复杂度上升。

  • 命名规范: <tenant-name>-<env>,例如 fintech-prod、fintech-staging。
  • 标签注入: 强制为每个 Namespace 打上 tenant: <tenant-name> 和 environment: <env> 标签,用于后续 NetworkPolicy 和 ResourceQuota 的选择器匹配。
  • 生命周期: 通过 Argo CD ApplicationSet 的 generators 自动创建 Namespace,避免手动 kubectl 操作。
apiVersion: v1
kind: Namespace
metadata:
  name: fintech-prod
  labels:
    tenant: fintech
    environment: prod
    managed-by: argocd

3.3 RBAC 权限隔离:最小权限原则

RBAC 配置分为两个维度:集群维度(ClusterRole / ClusterRoleBinding)和 命名空间维度(Role / RoleBinding)。对于多租户场景,我们优先使用命名空间维度的 Role,避免跨租户权限泄露。

典型租户角色定义:

角色 权限范围 典型操作
租户管理员 Namespace 内所有资源 创建/删除 Deployment、Service、ConfigMap、Secret
租户开发者 Namespace 内工作负载资源 更新 Deployment、查看 Pod 日志、滚动升级
租户只读者 Namespace 内查看权限 get/list/watch Pod、Service、Event
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: fintech-prod
  name: tenant-developer
rules:
- apiGroups: ["apps", "extensions"]
  resources: ["deployments", "statefulsets"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
  resources: ["pods", "pods/log", "services"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: fintech-prod
  name: fintech-developer-binding
subjects:
- kind: User
  name: "alice@fintech.com"
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: tenant-developer
  apiGroup: rbac.authorization.k8s.io
避坑提示: 不要将 ClusterRoleBinding 直接绑定给租户用户,除非该租户需要跨 Namespace 操作。始终优先使用 RoleBinding + Role,将权限锁定在租户自己的 Namespace 内。

3.4 NetworkPolicy 网络隔离:默认拒绝 + 显式放行

Kubernetes 默认的“全通”网络模型在多租户环境下是安全风险。我们采用 “默认拒绝所有入站/出站流量,仅显式放行业务所需流量” 的策略。

以下是一个典型租户的 NetworkPolicy 配置,实现三层隔离:

  1. 隔离层 1: 拒绝所有非本 Namespace 的入站流量。
  2. 隔离层 2: 允许同 Namespace 内所有 Pod 通信。
  3. 隔离层 3: 显式放行来自监控系统(如 Prometheus)和 Ingress Controller 的流量。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: fintech-prod
spec:
  podSelector: {}
  policyTypes:
  - Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
  namespace: fintech-prod
spec:
  podSelector: {}
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          tenant: fintech
          environment: prod
  policyTypes:
  - Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-monitoring
  namespace: fintech-prod
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
      podSelector:
        matchLabels:
          app: prometheus
    ports:
    - port: 8080
      protocol: TCP
  policyTypes:
  - Ingress
性能考量: NetworkPolicy 规则数量过多(超过 1000 条)会显著增加 kube-proxy 或 CNI 组件的规则计算延迟。建议每个租户的 NetworkPolicy 规则控制在 20 条以内,并通过标签选择器聚合规则。

3.5 资源配额管理:防止“吵闹邻居”

资源配额(ResourceQuota)和限制范围(LimitRange)是防止单个租户耗尽集群资源的最后防线。我们为每个租户的 Namespace 设置以下配额:

配额类型 示例值 说明
requests.cpu 8 CPU 请求总量上限(单位:核)
requests.memory 16Gi 内存请求总量上限
limits.cpu 16 CPU 限制总量上限
limits.memory 32Gi 内存限制总量上限
count/deployments.apps 20 Deployment 数量上限
count/services 30 Service 数量上限
count/secrets 50 Secret 数量上限
apiVersion: v1
kind: ResourceQuota
metadata:
  name: tenant-quota
  namespace: fintech-prod
spec:
  hard:
    requests.cpu: "8"
    requests.memory: "16Gi"
    limits.cpu: "16"
    limits.memory: "32Gi"
    count/deployments.apps: "20"
    count/services: "30"
    count/secrets: "50"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: tenant-limits
  namespace: fintech-prod
spec:
  limits:
  - max:
      cpu: "4"
      memory: "8Gi"
    min:
      cpu: "100m"
      memory: "128Mi"
    default:
      cpu: "500m"
      memory: "1Gi"
    defaultRequest:
      cpu: "200m"
      memory: "512Mi"
    type: Container

3.6 多租户隔离架构总览

下图展示了单个租户(fintech)在集群内的完整隔离架构,包含 Namespace 边界、RBAC 角色绑定、NetworkPolicy 规则以及 ResourceQuota 的协同工作关系。

多租户隔离架构(单租户视图) Namespace: fintech-prod RBAC 权限隔离 Role: tenant-admin Role: tenant-developer Role: tenant-reader User → RoleBinding → Role NetworkPolicy 网络隔离 default-deny-ingress allow-same-namespace allow-monitoring PodSelector + NamespaceSelector ResourceQuota CPU: 8/16 核 Memory: 16/32 Gi Deploy: 20 个 LimitRange 约束 工作负载(Pod / Service / ConfigMap) Pod: web-v1 Pod: api-v2 Service: web-svc ConfigMap 三层隔离协同:RBAC 控制“谁能操作”,NetworkPolicy 控制“谁能访问”,ResourceQuota 控制“能用多少”

3.7 租户配置的 GitOps 化

所有上述隔离策略(Namespace、RBAC、NetworkPolicy、ResourceQuota)都应作为 Kubernetes 清单存储在 Git 仓库中,并通过 Argo CD ApplicationSet 自动同步到目标集群。每个租户对应一个独立的 Application,其 spec.source.path 指向租户专属的配置目录。

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: tenant-applications
spec:
  generators:
  - list:
      elements:
      - tenant: fintech
        env: prod
      - tenant: fintech
        env: staging
      - tenant: retail
        env: prod
  template:
    metadata:
      name: '{{tenant}}-{{env}}'
    spec:
      project: default
      source:
        repoURL: https://git.company.com/tenants/{{tenant}}.git
        targetRevision: main
        path: '{{env}}/overlays'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{tenant}}-{{env}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
最佳实践: 将 ResourceQuota 和 LimitRange 放在 overlays/base 目录中,作为所有环境的公共配置;将 NetworkPolicy 放在 overlays/{{env}} 中,按环境差异化调整。RBAC 的 Role 和 RoleBinding 建议与租户的团队 Git 仓库绑定,通过 CI/CD 流水线自动生成。