3. 租户隔离模型设计:基于命名空间的租户隔离、基于标签的租户路由、多租户数据面隔离策略

在 API 弃用场景的蓝绿部署中,租户隔离是保障升级安全与故障隔离的核心前提。本章聚焦三种互补的隔离模型:命名空间级隔离提供物理/逻辑边界,标签路由实现细粒度流量调度,数据面隔离确保存储与网络互不干扰。三者组合形成“边界 + 路由 + 数据”的立体隔离架构。

3.1 基于命名空间的租户隔离

Kubernetes 命名空间(Namespace)是租户隔离的第一道防线。每个租户拥有独立的命名空间,资源配额、网络策略、RBAC 权限均以命名空间为粒度生效。

隔离维度 实现方式 API 弃用场景作用
资源边界 每个租户独占 Namespace,ResourceQuota 限制总量 防止某租户蓝绿升级时抢占其他租户资源
网络边界 NetworkPolicy 控制跨 Namespace 流量 蓝绿两套服务仅在租户内部可达
权限边界 RBAC RoleBinding 限定到 Namespace 租户管理员只能操作本租户的旧版/新版 API
观测边界 Metrics/Logs 按 Namespace 打标 故障排查时快速定位到具体租户
实践建议:命名空间命名采用 {tenant}-{env} 格式,例如 acmecorp-prod、acmecorp-staging。蓝绿部署时,旧版 API 部署在 acmecorp-prod,新版 API 部署在 acmecorp-prod-green,通过标签路由切换流量。

3.2 基于标签的租户路由

命名空间提供静态边界,而标签(Label)与选择器(Selector)实现动态路由。在 API 弃用场景中,通过为每个租户的 Pod 打上 tenant-id 和 api-version 标签,Ingress/Service Mesh 可根据请求中的租户标识将流量精确导向目标版本。

# 租户 Pod 标签示例
apiVersion: v1
kind: Pod
metadata:
  name: api-v2-pod-tenant-001
  namespace: acmecorp-prod-green
  labels:
    tenant-id: "tenant-001"
    api-version: "v2"
    app: "customer-api"
spec:
  containers:
  - name: api
    image: registry.example.com/customer-api:v2.0.0
    ports:
    - containerPort: 8080

路由规则示例(基于 Istio VirtualService):

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: customer-api-routing
  namespace: acmecorp-prod
spec:
  hosts:
  - api.acmecorp.com
  http:
  - match:
    - headers:
        x-tenant-id:
          exact: "tenant-001"
    route:
    - destination:
        host: customer-api-v2
        port:
          number: 8080
      weight: 100
  - route:
    - destination:
        host: customer-api-v1
        port:
          number: 8080
      weight: 100
关键指标:标签路由的切换延迟应 < 500ms,避免租户在蓝绿切换期间出现超时。建议配合 Readiness Probe 确保新版 Pod 就绪后再更新路由权重。

3.3 多租户数据面隔离策略

数据面隔离涵盖存储、网络、配置三个层面。在 API 弃用蓝绿部署中,新旧两版 API 可能访问不同的数据库 schema 或缓存实例,必须确保租户数据不交叉污染。

3.3.1 存储隔离

  • Schema 版本隔离:旧版 API 使用 v1_ 前缀表,新版使用 v2_ 前缀表,通过数据库迁移工具逐步同步。
  • 连接池隔离:每个租户独立配置数据库连接池最大连接数,防止某租户的蓝绿升级耗尽连接。
  • 缓存隔离:Redis 使用 {tenant}:{version}: 键前缀,或为每个租户分配独立 Redis DB 编号。

3.3.2 网络隔离

  • Service 隔离:每个租户的旧版/新版 API 分别创建独立的 Kubernetes Service,名称包含 -v1 和 -v2 后缀。
  • mTLS 隔离:启用 Istio 双向 TLS,仅允许同一租户命名空间内的服务互相调用。
  • 出口流量隔离:通过 Egress Gateway 控制租户对外部 API 的访问,避免弃用期间误调用已下线的外部依赖。

3.3.3 配置隔离

  • 使用 ConfigMap 和 Secret 按命名空间隔离,每个租户的 API 版本拥有独立的配置副本。
  • 配置变更通过 GitOps 流程审批,避免某租户误修改全局配置影响其他租户。
常见陷阱:共享中间件(如消息队列、日志收集器)可能成为隔离盲区。务必为每个租户配置独立的 Topic/Index,或在消息体中携带 tenant_id 和 api_version 字段,由消费端做二次过滤。

3.4 隔离模型架构总览

下图展示三种隔离模型在蓝绿部署中的协同关系:命名空间提供租户边界,标签路由实现流量调度,数据面隔离保障存储与网络互不干扰。

租户隔离模型架构(蓝绿部署场景) 租户 A 命名空间 (acmecorp-prod) 租户 B 命名空间 (beta-prod) 旧版 API v1 Pod 标签: tenant-id: tenant-A api-version: v1 新版 API v2 Pod 标签: tenant-id: tenant-A api-version: v2 数据面隔离(租户 A) • 数据库: v1_orders / v2_orders 表 • Redis: tenant-A:v1: / tenant-A:v2: 键前缀 • Service: customer-api-v1 / customer-api-v2 • NetworkPolicy: 仅允许本命名空间内流量 旧版 API v1 Pod 标签: tenant-id: tenant-B api-version: v1 新版 API v2 Pod 标签: tenant-id: tenant-B api-version: v2 数据面隔离(租户 B) • 数据库: v1_orders / v2_orders 表 • Redis: tenant-B:v1: / tenant-B:v2: 键前缀 • Service: customer-api-v1 / customer-api-v2 • NetworkPolicy: 仅允许本命名空间内流量 标签路由层(Ingress / Service Mesh) 根据请求头 x-tenant-id 匹配租户,根据 api-version 标签路由到旧版或新版 租户 A 流量 → tenant-A 命名空间 → 按权重分发至 v1/v2

3.5 隔离策略选择矩阵

根据租户规模和 API 弃用阶段,推荐以下组合策略:

场景 命名空间隔离 标签路由 数据面隔离 适用阶段
小规模(<10 租户) ✅ 每个租户独立 Namespace ✅ 基于 tenant-id 标签 ✅ Schema 前缀 + 独立 Service 弃用初期,灰度验证
中规模(10-100 租户) ✅ 每个租户独立 Namespace ✅ 基于 tenant-id + api-version 组合标签 ✅ 独立 DB 连接池 + Redis DB 弃用中期,批量迁移
大规模(>100 租户) ✅ 按业务域聚合 Namespace ✅ 基于标签 + 权重路由 ✅ 独立数据库实例 + 缓存集群 弃用后期,全量切换
故障排查要点:当某租户在蓝绿切换后出现数据异常时,优先检查:① 该租户的 Pod 标签是否与路由规则匹配;② 数据库连接是否指向正确的 schema 版本;③ NetworkPolicy 是否误拦截了新版 API 的健康检查流量。