第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 | 推荐作为跨租户流量的统一出口 |
| 最佳实践 | 默认拒绝 + 显式放行 + 资源配额 |
思考
- K8s Namespace 能提供哪些隔离?哪些不能?
- 为什么 VLAN 不适合大规模多租户容器网络?
- VXLAN VNI 隔离的原理是什么?最多支持多少租户?
- Cilium Security Identity 与 NetworkPolicy 相比有什么优势?
- 如何实现一个租户只能访问自己的 Pod,不能访问其他租户的 Pod?
- API Gateway 在多租户架构中扮演什么角色?
下篇预告:第280篇 - 云原生网络策略 NetworkPolicy 实现,深入 K8s NetworkPolicy 的规则语法、多 CNI 实现差异和 Cilium 增强网络策略。