4. 多租户命名空间设计:命名空间作为租户边界、命名空间命名规范、标签策略

在 Kubernetes 多租户体系中,命名空间(Namespace)是最基础、最直接的租户隔离边界。一个设计良好的命名空间体系,不仅决定了网络策略的生效范围,还直接影响运维效率、审计清晰度和自动化能力。本章将深入剖析如何将命名空间作为租户边界,并给出命名规范与标签策略的最佳实践。

4.1 命名空间作为租户边界

Kubernetes 原生提供的命名空间隔离机制,天然适合作为多租户的“软墙”。每个租户独占一个或多个命名空间,通过 RBAC、ResourceQuota、NetworkPolicy 等机制实现资源与网络的逻辑隔离。

将命名空间作为租户边界,需要遵循以下核心原则:

  • 独占性:每个租户至少拥有一个独立的命名空间,不允许跨租户共享命名空间。
  • 不可穿透性:默认情况下,不同命名空间的 Pod 无法直接通信;如需跨租户通信,必须显式通过 NetworkPolicy 放行。
  • 资源配额绑定:每个租户命名空间绑定独立的 ResourceQuota 和 LimitRange,防止资源争抢。
  • 审计边界:所有审计日志、监控指标、成本核算均以命名空间为粒度进行聚合。
设计建议:对于大型租户(如企业级客户),可为其分配多个命名空间(如 dev、staging、prod),但所有命名空间必须通过统一的标签体系关联到该租户,便于策略继承和资源统计。

下图展示了以命名空间为租户边界的典型架构:

命名空间作为租户边界架构图 命名空间作为租户边界架构 租户 A(tenant-a) ns-a-dev Pod / Service NetworkPolicy ns-a-prod Pod / Service NetworkPolicy 标签: tenant=tenant-a, env=dev|prod ResourceQuota: CPU 8核 / 内存 16Gi 租户 B(tenant-b) ns-b-dev Pod / Service NetworkPolicy ns-b-prod Pod / Service NetworkPolicy 标签: tenant=tenant-b, env=dev|prod ResourceQuota: CPU 4核 / 内存 8Gi 隔离

4.2 命名空间命名规范

统一的命名规范是自动化运维和策略继承的基础。混乱的命名会导致 NetworkPolicy 选择器失效、监控数据难以聚合、审计日志无法追溯。推荐采用以下分层命名模式:

<租户标识>-<环境>-<区域/模块>

各字段说明如下表:

字段 说明 示例值 约束
租户标识 租户的唯一缩写,建议 3-8 位小写字母 fin、ecom、aipl 全局唯一,不可变更
环境 部署环境类型 dev、stg、prod 固定枚举值
区域/模块 可选字段,用于大型租户的子模块划分 core、pay、user 非必填,建议不超过 2 级

命名规范示例:

  • fin-prod —— 金融租户生产环境
  • ecom-stg-pay —— 电商租户预发布环境的支付模块
  • aipl-dev-core —— AI 平台租户开发环境的核心模块
避坑指南:禁止在命名空间名称中使用下划线(_)、大写字母或特殊字符。Kubernetes 命名空间名称必须符合 DNS-1123 标签规范(小写字母、数字、连字符),且长度不超过 63 个字符。建议统一使用连字符(-)作为分隔符。

4.3 标签策略

标签(Label)是 Kubernetes 中实现灵活选择与策略绑定的核心机制。在多租户场景下,标签策略决定了 NetworkPolicy 能否精准匹配目标 Pod,以及运维工具能否高效聚合资源。

4.3.1 强制标签体系

每个命名空间及其下的所有资源,必须携带以下强制标签:

标签键 标签值示例 作用
tenant fin、ecom 标识所属租户,用于 NetworkPolicy 的 namespaceSelector
environment dev、stg、prod 标识环境,用于环境级策略隔离
tier frontend、backend、data 标识服务层级,用于东西向流量策略
team platform、payment 标识负责团队,用于审计与成本分摊

4.3.2 标签在 NetworkPolicy 中的应用

通过标签选择器,可以实现精细化的跨租户或跨环境策略控制。以下是一个基于标签的 NetworkPolicy 示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-fin-prod
  namespace: ecom-prod
spec:
  podSelector:
    matchLabels:
      tier: frontend
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          tenant: fin
          environment: prod
    - podSelector:
        matchLabels:
          tier: backend

该策略允许来自 fin-prod 命名空间的所有 Pod,以及本命名空间中带有 tier: backend 标签的 Pod,访问 ecom-prod 命名空间中带有 tier: frontend 标签的 Pod。

4.3.3 标签自动化校验

为确保标签策略被严格执行,建议使用 准入控制器(Admission Controller) 或 OPA/Gatekeeper 进行强制校验。以下是一个 Gatekeeper 约束模板示例:

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels
        violation[{"msg": msg}] {
          provided := {label | input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("Missing required labels: %v", [missing])
        }
最佳实践:将标签校验与 CI/CD 流水线集成,在资源创建或更新前自动检查标签完整性。对于不合规的资源,直接拒绝部署并返回明确错误信息,避免“带病上线”。

下图展示了标签策略在 NetworkPolicy 选择器中的匹配流程:

标签策略匹配流程 标签策略在 NetworkPolicy 中的匹配流程 NetworkPolicy namespaceSelector 目标命名空间 tenant=fin, env=prod 目标 Pod tier=frontend 匹配逻辑:namespaceSelector 先筛选命名空间,podSelector 再筛选 Pod,两者取交集 标签不匹配 → 策略不生效 → 流量被拒绝 标签匹配 → 策略生效 → 流量被放行

4.4 命名空间设计清单

在实施多租户命名空间设计时,建议对照以下清单逐项检查:

  1. 命名规范已定义:是否形成了团队统一的命名模板?是否通过自动化工具(如脚手架)生成命名空间?
  2. 强制标签已绑定:每个命名空间是否都携带了 tenant、environment、tier 等核心标签?
  3. 标签校验已启用:是否部署了 OPA/Gatekeeper 或类似工具,在资源创建时强制校验标签完整性?
  4. NetworkPolicy 基线已配置:是否为每个命名空间配置了默认拒绝入站/出站的基线策略?
  5. 资源配额已设置:每个命名空间是否绑定了 ResourceQuota 和 LimitRange?
  6. 审计与监控已对接:日志和监控系统是否以命名空间为粒度进行数据聚合?
快速验证命令:使用以下命令检查集群中所有命名空间的标签合规性:
kubectl get ns --show-labels | grep -E "tenant|environment"
如果输出中缺少关键标签,说明命名空间设计存在遗漏,需要立即补充。