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

关键词:多租户、网络隔离、NetworkPolicy、VXLAN、VPC、Kubernetes多租户、Calico


一、引言

在共享的Kubernetes集群中,多租户网络隔离是确保不同租户(团队、项目、客户)之间网络安全和资源隔离的关键。与虚拟机环境中的VPC隔离类似,容器网络也需要在共享基础设施上实现租户间的逻辑隔离。

本文将探讨容器网络中多租户隔离的技术方案,从Kubernetes原生的NetworkPolicy到基于VXLAN的Overlay隔离,帮助读者构建安全的多租户容器平台。

二、核心概念

2.1 多租户网络隔离需求

需求 说明
Pod隔离 不同租户的Pod无法互相访问
地址隔离 不同租户使用独立的IP地址段
Service隔离 不同租户的Service互不可见
入口隔离 不同租户的外部入口独立
DNS隔离 不同租户的DNS解析独立
策略隔离 不同租户独立配置网络策略

2.2 Kubernetes 多租户模型

模型 说明 隔离级别
命名空间(Namespace) K8s原生逻辑隔离 弱(默认不隔离网络)
多集群 每个租户独立K8s集群 强(物理隔离)
分布式集群 共享控制面, 隔离数据面 中
单集群+NetworkPolicy 单集群, 策略隔离 中
单集群+Overlay 单集群, 网络层隔离 强

2.3 隔离技术对比

隔离技术对比 - 图示

三、技术细节

3.1 NetworkPolicy 实现多租户隔离

默认拒绝所有跨命名空间流量:

# 在租户命名空间中部署默认拒绝策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: tenant-a
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
---
# 允许同一命名空间内通信
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
  namespace: tenant-a
spec:
  podSelector: {}
  ingress:
  - from:
    - podSelector: {}
  policyTypes:
  - Ingress
---
# 允许DNS解析
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: tenant-a
spec:
  podSelector: {}
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
  policyTypes:
  - Egress

3.2 Calico GlobalNetworkPolicy

Calico提供GlobalNetworkPolicy,可以跨命名空间实施全局策略:

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: tenant-isolation
spec:
  selector: has(project)
  types:
  - Ingress
  - Egress
  ingress:
  - action: Allow
    source:
      selector: project == 'tenant-a'
    destination:
      selector: project == 'tenant-a'
  - action: Allow
    source:
      selector: project == 'tenant-b'
    destination:
      selector: project == 'tenant-b'
  egress:
  - action: Allow
    destination:
      selector: has(k8s-app) && k8s-app == 'kube-dns'

3.3 基于 Overlay 的网络隔离

使用VXLAN实现租户级别的Overlay网络隔离:

方案 说明
Multus + VXLAN CNI 每个租户独立的VXLAN网络
Kube-OVN OVN/Vtep实现租户VPC
Cilium VTEP Cilium原生VXLAN VTEP
独立集群 每个租户独立K8s集群和CNI

Kube-OVN租户VPC模型:

apiVersion: kubeovn.io/v1
kind: Vpc
metadata:
  name: tenant-a-vpc
spec:
  staticRoutes:
  - cidr: 0.0.0.0/0
    nextHopFec: 192.168.100.1
---
apiVersion: kubeovn.io/v1
kind: VpcNatGateway
metadata:
  name: tenant-a-nat
spec:
  vpc: tenant-a-vpc
  subnet: tenant-a-subnet
  ldapConfig:
    staticRoutes:
    - cidr: 0.0.0.0/0
      nextHopFec: 192.168.100.1

3.4 子网/IPAM 隔离

方案 IP分配方式 隔离级别
全局IPAM 共享地址池 弱
命名空间IPAM 按命名空间划分 中
独立Overlay 每个租户独立VXLAN 强
独立集群 独立地址空间 最强

3.4 多租户 DNS 隔离

在共享Kubernetes集群中,DNS隔离防止租户间通过DNS进行信息泄露:

DNS隔离方案 说明 实现方式
CoreDNS插件 按命名空间过滤DNS解析 k8s_external插件
独立CoreDNS 每个租户独立的CoreDNS 部署多组CoreDNS
DNS Policy Pod级别的DNS策略 dnsPolicy字段
自定义域名后缀 租户级域名后缀隔离 search字段配置

CoreDNS按命名空间过滤配置:

# Corefile配置
.:53 {
    errors
    health
    kubernetes cluster.local in-addr.arpa ip6.arpa {
      pods insecure
      ttl 30
      fallthrough in-addr.arpa ip6.arpa
    }
    # 按命名空间过滤: 只允许解析kube-system和当前租户命名空间
    namespace-filter {
      allow kube-system
      allow tenant-a
      deny default
    }
    forward . /etc/resolv.conf
    cache 30
    loop
    reload
    loadbalance
}

3.5 多租户资源配额与限制

资源类型 隔离机制 配置方式
CPU/内存 LimitRange + ResourceQuota K8s原生API
Pod数量 ResourceQuota max Pods计数
网络带宽 NetworkPolicy + CNI QoS CNI插件/QoS策略
存储容量 ResourceQuota + StorageClass 存储配额
Service数量 ResourceQuota Service计数限制
Secret/ConfigMap ResourceQuota 资源计数限制

租户资源配额示例:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: tenant-a-quota
  namespace: tenant-a
spec:
  hard:
    requests.cpu: "10"
    requests.memory: 20Gi
    limits.cpu: "20"
    limits.memory: 40Gi
    pods: "50"
    services: "20"
    services.loadbalancers: "2"
    services.nodeports: "5"
    configmaps: "100"
    secrets: "100"
    persistentvolumeclaims: "10"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: tenant-a-limits
  namespace: tenant-a
spec:
  limits:
  - default:
      cpu: 500m
      memory: 512Mi
    defaultRequest:
      cpu: 100m
      memory: 128Mi
    type: Container

3.6 自动化策略注入架构

自动化策略注入架构 - 图示

3.7 多租户安全审计

审计维度 审计内容 审计频率 工具
NetworkPolicy合规 策略覆盖率和有效性 每日 kubectl-np-viewer
跨租户流量 是否存在未授权的跨租户通信 实时 Cilium Hubble
资源使用 配额使用率和超用检测 每小时 Prometheus
异常流量 DDoS/扫描/异常连接 实时 IDS/IPS
配置漂移 策略是否被手动修改 每日 GitOps审计

四、实战配置/案例分析

4.1 多租户 NetworkPolicy 自动化部署

# 使用Kubernetes Admission Webhook自动注入NetworkPolicy
# 当租户命名空间创建时, 自动注入默认拒绝策略

# 1. 创建MutatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: network-policy-injector
webhooks:
- name: inject-network-policy.networkpolicy.io
  rules:
  - apiGroups: [""]
    apiVersions: ["v1"]
    operations: ["CREATE"]
    resources: ["namespaces"]
  clientConfig:
    service:
      name: network-policy-injector
      namespace: network-policy-system
    path: /mutate

4.2 故障案例:NetworkPolicy配置错误导致租户间网络泄露

现象:租户A的Pod可以访问租户B的数据库Service,存在严重的安全隔离问题。

排查过程:

# 1. 检查租户A的NetworkPolicy
kubectl get networkpolicy -n tenant-a
# 发现一条egress规则: 允许访问所有TCP 3306端口

# 2. 检查规则详情
kubectl get networkpolicy allow-db -n tenant-a -o yaml
# egress规则:
#   - to: []  (空, 表示所有目的地)
#     ports:
#     - port: 3306
# 这允许租户A访问集群中任何Pod的3306端口!

# 3. 从租户A的Pod测试
kubectl exec -n tenant-a app-pod -- curl tenant-b-db.tenant-b.svc.cluster.local:3306
# 连接成功, 确认网络泄露

根因:租户A的NetworkPolicy中egress规则的to字段为空(未指定目标限制),导致允许访问集群中所有Pod的3306端口,包括租户B的数据库。

解决: 1. 修正egress规则,明确指定目标命名空间或Pod标签:

egress:
- to:
  - namespaceSelector:
      matchLabels:
        tenant: tenant-a
  ports:
  - port: 3306
    protocol: TCP
  1. 部署NetworkPolicy审计工具,定期检查策略有效性
  2. 使用Calico的GlobalNetworkPolicy实施全局租户隔离基线

4.3 故障案例:多租户IP地址冲突

现象:租户B的新Pod无法启动,报错"IP address conflict"。

排查过程:

# 1. 检查CNI IPAM状态
# Calico IPAM查看
calicoctl ipam check

# 发现两个租户的Pod网段重叠:
# 租户A Pod网段: 192.168.1.0/24
# 租户B Pod网段: 192.168.1.0/24 (冲突!)

# 2. 检查BlockAffinity
calicoctl get blockaffinity -o wide
# 同一IP块被两个不同的节点亲和性占用

根因:在多租户环境中,管理员为不同租户配置了重叠的Pod CIDR地址段,导致IP地址冲突。

解决: 1. 重新规划各租户的Pod CIDR,确保不重叠 2. 使用Calico的IPAM块亲和性管理租户地址分配 3. 实施IP地址规划审计,防止地址段冲突

五、总结

隔离方案 隔离级别 部署复杂度 性能影响 适用场景
Namespace(默认) 弱 低 无 内部团队
NetworkPolicy 中 中 低 标准多租户
GlobalNetworkPolicy 中 中 低 Calico环境
Overlay(VXLAN) 强 高 中 严格隔离
多集群 最强 最高 无 高安全要求
最佳实践 说明
默认拒绝 所有租户默认拒绝跨租户流量
最小权限 只开放必要的跨租户通信
地址规划 严格的租户IP地址段规划
策略审计 定期审计NetworkPolicy有效性
资源配额 通过ResourceQuota限制租户资源
DNS隔离 防止租户间通过DNS信息泄露

思考

  1. Kubernetes的Namespace默认不提供网络隔离,为什么Kubernetes不直接将Namespace设计为网络隔离边界?
  2. NetworkPolicy是白名单机制还是黑名单机制?这种设计对多租户安全有什么影响?
  3. 基于Overlay的多租户隔离与基于NetworkPolicy的隔离相比,各有何优劣?
  4. 多租户环境中,如何通过DNS隔离防止租户间的信息泄露?
  5. 自动化策略注入如何确保新租户命名空间创建时自动应用安全基线?

下篇预告:第280篇:云原生网络策略 NetworkPolicy 实现