第279篇:容器网络的多租户隔离方案

关键词

多租户隔离、容器网络、K8s Namespace、网络策略、Tenant、VLAN/VXLAN 隔离、租户虚拟网络、Cilium NetworkPolicy


一、多租户隔离的挑战

1.1 什么是多租户

多租户(Multi-Tenancy)指一个集群同时服务多个团队/项目/客户,各租户之间网络、计算、存储完全隔离:

K8s 多租户场景:

K8s 集群 ┌─────────┐ ┌─────────┐ ┌─────────┐ └─────────┘ └─────────┘ └─────────┘ └────────────┴────────────┘ 隔离需求: ┌─ A 不能访问 B 的 Pod ├─ B 不能看到 C 的 Service └─ C 有自己的 IP 段和策略 租户 A (电商) Pod-A1 Pod-A2 Pod-A3 租户 B (支付) Pod-B1 Pod-B2 Pod-B3 租户 C (AI) Pod-C1 Pod-C2 Pod-C3

1.2 隔离的挑战

容器网络多租户面临的问题:

挑战 1:K8s Namespace 的局限
  ┌─ K8s Namespace 是软隔离
  ├─ Pod 跨 Namespace 默认可达
  ├─ 无内置资源隔离(可配置 ResourceQuota)
  └─ 网络层面需额外机制(NetworkPolicy)

挑战 2:IP 地址的重叠
  ┌─ 不同租户可能使用相同 IP 段(10.0.0.0/24)
  ├─ 直接通信会导致路由冲突
  └─ 需要 Overlay 网络为每个租户建 VNI

挑战 3:策略的复杂度
  ┌─ 需要同时控制东西向(Pod-Pod)和南北向
  ├─ 策略数随租户数线性增长(100 租户 → 可上千条)
  └─ 策略冲突排查困难

挑战 4:性能与安全的平衡
  ┌─ 隔离越严格,数据面处理越多
  ├─ Overlay 封装增加 overhead
  └─ 策略匹配影响转发性能

二、K8s Namespace 级别的隔离

2.1 基于 Namespace 的逻辑隔离

Namespace 隔离模型:

  ┌──────────────────────────────────────────┐
  │  kube-system                                │
  │  (系统组件)                                 │
  └──────────────────────────────────────────┘

  ┌──────────────────────────────────────────┐
  │  tenant-a                                  │
  │  Pods: app-a-xxx, db-a-xxx                │
  │  Services: app-a-svc, db-a-svc            │
  │  NetworkPolicy: deny-all + allow-a-in     │
  └──────────────────────────────────────────┘

  ┌──────────────────────────────────────────┐
  │  tenant-b                                  │
  │  Pods: app-b-xxx, db-b-xxx                │
  │  Services: app-b-svc, db-b-svc            │
  │  NetworkPolicy: deny-all + allow-b-in     │
  └──────────────────────────────────────────┘

Namespace 提供的隔离:
  ┌─ 资源配额隔离:ResourceQuota 限制 CPU/内存
  ├─ 对象命名隔离:同名 Service 不同 Namespace
  ├─ RBAC 隔离:不同角色权限
  └─ 网络隔离:需配合 NetworkPolicy

2.2 默认拒绝策略

默认拒绝所有入站流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: tenant-a
spec:
  podSelector: {}          # 匹配所有 Pod
  policyTypes:
    - Ingress              # 拒绝所有入站
---
默认拒绝所有出站流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  namespace: tenant-a
spec:
  podSelector: {}
  policyTypes:
    - Egress               # 拒绝所有出站

三、多租户网络方案

3.1 基于 VLAN 的隔离(传统方式)

VLAN 隔离方案:

  租户 A ──► Pod-A(10.1.0.0/16)──► VLAN 100
  租户 B ──► Pod-B(10.2.0.0/16)──► VLAN 200
  租户 C ──► Pod-C(10.3.0.0/16)──► VLAN 300

  原理:
    ┌─ 每个租户分配不同 VLAN
    ├─ 节点上虚拟网桥绑定对应 VLAN
    ├─ 租户间靠 VLAN ACL 隔离
    └─ 需要物理交换机支持 VLAN

  缺点:
    ┌─ VLAN 数量有限(4094)
    ├─ Pod 迁移受限(需同 VLAN 可达)
    └─ 配置复杂,不灵活

3.2 基于 VXLAN/VNI 的 Overlay 隔离

VXLAN 方案(推荐):

  租户 A ──► VNI 10001 ──► Overlay 网络 A
  租户 B ──► VNI 10002 ──► Overlay 网络 B
  租户 C ──► VNI 10003 ──► Overlay 网络 C

  Calico VXLAN 多租户示例:

  apiVersion: projectcalico.org/v3
  kind: IPPool
  metadata:
    name: tenant-a-pool
  spec:
    cidr: 10.100.0.0/16
    natOutgoing: true
    vxlanMode: Always
  ---
  apiVersion: projectcalico.org/v3
  kind: IPPool
  metadata:
    name: tenant-b-pool
  spec:
    cidr: 10.200.0.0/16
    natOutgoing: true
    vxlanMode: Always

  每个租户独立 IP 段 + 独立 VNI
  租户间默认二层隔离(不同 VNI 不通)
  可配置跨租户路由(需开启 VXLAN 路由)

3.3 基于 Cilium 的安全身份隔离

Cilium Security Identity 隔离:

Cilium 为每个 Pod 分配安全身份(24-bit Identity) 身份基于标签组合,不依赖 IP

Pod 标签 → 身份标识 Pod-A: tenant=a, app=web → Identity: 10001 Pod-B: tenant=a, app=db → Identity: 10002 Pod-C: tenant=b, app=web → Identity: 20001 隔离规则: 10001 → 10002 ✅(同租户) 10001 → 20001 ❌(跨租户默认拒绝)

Cilium 多租户策略:

apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: tenant-isolation namespace: tenant-a spec: endpointSelector: matchLabels: "k8s:io.kubernetes.pod.namespace": tenant-a ingress: - fromEndpoints: - matchLabels: "k8s:io.kubernetes.pod.namespace": tenant-a egress: - toEndpoints: - matchLabels: "k8s:io.kubernetes.pod.namespace": tenant-a - toCIDR: - 0.0.0.0/0 # 允许出站外网(可选)


四、多租户的 Service 隔离

4.1 Service 暴露限制

不同租户的 Service 暴露方案:

方案 1:ClusterIP ┌─ 仅在租户 Namespace 内部可见 ├─ 跨 Namespace 默认不可访问 └─ 通过 DNS: service.namespace.svc.cluster.local

方案 2:ExternalName ┌─ 通过 CNAME 指向外部地址 └─ 用于暴露给其他租户

方案 3:跨租户 Service 互通 ┌─ 必须显式创建 NetworkPolicy 放行 ├─ 示例:放行 tenant-b 访问 tenant-a 的 api-svc └─ 建议通过 API Gateway 集中暴露出租户

推荐:API Gateway 集中暴露 | 租户 A: Pod ←→ ClusterIP 租户 B: Pod ←→ ClusterIP ┌─────┴──────┐ | API Gateway (tenants) | ← Ingress ← 外部流量 | | --- | --- | --- |

4.2 租户 DNS 隔离

租户 DNS 隔离方案:

  ┌─ 方案 1:CoreDNS 按 Namespace 隔离
  │  每个租户 Namespace 独立 DNS 解析域
  │  使用 coredns 插件限制跨 Namespace 查询
  │
  ├─ 方案 2:配置 CoreDNS rewrite
  │  rewrite name exact app-a-svc.default
  │           to app-a-svc.tenant-a.svc.cluster.local
  │
  └─ 方案 3:多 CoreDNS 实例(每个租户一个)
     每个租户独立 CoreDNS,完全隔离
     资源消耗较大

五、多租户网络方案对比

方案 隔离粒度 性能开销 扩展性 适用场景
VLAN 隔离 粗(VLAN 级) 低(硬件转发) 差(4094 上限) 小规模,传统环境
VXLAN/VNI 隔离 中(VNI 级) 中(~5% 封装) 优(1600 万 VNI) 中小规模多租户
NetworkPolicy 细(Pod 级) 中(策略匹配) 优(策略任意组合) 云原生多租户
Cilium Identity 细(身份级) 低(eBPF 匹配) 优(24-bit 身份) 大规模高性能
虚拟网络 CRD 灵活(租户级) 中-高 电信/金融行业

六、最佳实践

生产环境多租户隔离建议:

1. 命名规划
   ┌─ 每个租户一个独立的 K8s Namespace
   ├─ 命名规则:<tenant>-<env>(如:ecom-prod)
   └─ 统一标签:tenant: xxx, env: xxx

2. 网络策略
   ┌─ 每个 Namespace 应用默认拒绝策略
   ├─ 显式放行本租户内部流量
   ├─ 跨租户流量走 API Gateway
   └─ 出口流量按需放行(仅允许必要外网地址)

3. 资源隔离
   ┌─ ResourceQuota 限制每个租户的资源
   ├─ LimitRange 设置默认资源限制
   ├─ PriorityClass 区分租户优先级
   └─ NetworkPolicy 配合资源配额使用

4. 监控与审计
   ┌─ 每个租户独立监控面板
   ├─ 流量日志按租户打标签
   ├─ 异常流量跨租户告警
   └─ 定期审计策略合规性

总结

关键点 说明
多租户隔离挑战 IP 重叠、策略复杂度、性能平衡
K8s Namespace 提供基础逻辑隔离,需配合 NetworkPolicy
VLAN/VXLAN VXLAN 的 1600 万 VNI 远超 VLAN 的 4094
Cilium Identity 基于标签的安全身份,eBPF 高效匹配
API Gateway 推荐作为跨租户流量的统一出口
最佳实践 默认拒绝 + 显式放行 + 资源配额

思考

  1. K8s Namespace 能提供哪些隔离?哪些不能?
  2. 为什么 VLAN 不适合大规模多租户容器网络?
  3. VXLAN VNI 隔离的原理是什么?最多支持多少租户?
  4. Cilium Security Identity 与 NetworkPolicy 相比有什么优势?
  5. 如何实现一个租户只能访问自己的 Pod,不能访问其他租户的 Pod?
  6. API Gateway 在多租户架构中扮演什么角色?

下篇预告:第280篇 - 云原生网络策略 NetworkPolicy 实现,深入 K8s NetworkPolicy 的规则语法、多 CNI 实现差异和 Cilium 增强网络策略。