4、基于网络策略的租户隔离实现

在 Kubernetes 多租户环境中,NetworkPolicy 是实现租户间网络隔离的核心原语。本章将深入讲解如何通过 NetworkPolicy 为不同租户创建独立的网络边界,实现租户间流量阻断,并建立白名单通信机制。

4.1 租户隔离的 NetworkPolicy 设计原则

NetworkPolicy 是 Kubernetes 中用于控制 Pod 间网络流量的资源对象。在多租户场景下,其设计遵循以下原则:

  • 默认拒绝(Default Deny):每个租户的命名空间默认拒绝所有入站和出站流量。
  • 最小权限(Least Privilege):仅允许租户内部必要的通信,以及跨租户白名单流量。
  • 标签驱动(Label-Driven):通过 Pod 标签和命名空间标签来定义策略的匹配范围。
  • 非重叠 CIDR:确保不同租户的 Service CIDR 和 Pod CIDR 不重叠,避免路由冲突。
最佳实践: 建议为每个租户创建独立的命名空间,并在命名空间级别应用默认拒绝策略,然后再添加白名单规则。

4.2 为不同租户创建独立 NetworkPolicy

以下示例展示如何为两个租户(Tenant-A 和 Tenant-B)创建独立的 NetworkPolicy。每个租户拥有自己的命名空间和标签体系。

4.2.1 租户 A 的 NetworkPolicy 配置

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tenant-a-default-deny
  namespace: tenant-a
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tenant-a-allow-internal
  namespace: tenant-a
spec:
  podSelector:
    matchLabels:
      tenant: a
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tenant: a
  egress:
  - to:
    - podSelector:
        matchLabels:
          tenant: a

4.2.2 租户 B 的 NetworkPolicy 配置

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tenant-b-default-deny
  namespace: tenant-b
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tenant-b-allow-internal
  namespace: tenant-b
spec:
  podSelector:
    matchLabels:
      tenant: b
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tenant: b
  egress:
  - to:
    - podSelector:
        matchLabels:
          tenant: b
关键点: 每个租户的命名空间内,先部署一个 default-deny 策略拒绝所有流量,再部署一个 allow-internal 策略允许同标签 Pod 间通信。这种“先拒绝后放行”的模式是隔离的基础。

4.3 租户间流量阻断

在默认拒绝策略生效后,不同租户命名空间之间的流量会被自动阻断。但为了确保安全,可以显式添加阻断策略,防止因命名空间标签误匹配导致的意外放行。

阻断方式 实现方法 适用场景
命名空间隔离 在全局默认拒绝策略中,不添加跨命名空间的 from 或 to 规则 所有多租户环境
显式阻断策略 使用 namespaceSelector 匹配非本租户的命名空间,并设置 deny 规则 需要额外安全加固的场景
网络插件级隔离 在 CNI 插件(如 Calico、Cilium)中配置全局网络策略 大规模集群或需要细粒度控制
注意: 显式阻断策略可能会增加运维复杂度。建议优先使用命名空间级别的默认拒绝策略,仅在需要严格合规的场景下才添加显式阻断。

4.4 白名单通信实现

在某些场景下,租户之间需要有限制的通信,例如:共享数据库服务、日志收集、监控探针等。此时需要配置白名单策略,允许特定 Pod 或命名空间之间的流量。

4.4.1 基于命名空间的白名单

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-monitoring
  namespace: tenant-a
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          purpose: monitoring
      podSelector:
        matchLabels:
          app: prometheus

4.4.2 基于 IP 段的白名单(适用于非 Kubernetes 原生场景)

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-external-cidr
  namespace: tenant-b
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
  - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 10.0.0.0/16
        except:
        - 10.0.1.0/24
提示: 白名单策略应遵循“最小必要”原则,只开放必要的端口和协议。建议使用 ports 字段限制通信端口,例如 ports: - protocol: TCP port: 443。

4.5 租户隔离网络拓扑 SVG 图

下图展示了基于 NetworkPolicy 的多租户隔离网络拓扑,包含两个租户命名空间、默认拒绝策略、内部允许策略以及白名单通信路径。

基于 NetworkPolicy 的多租户隔离网络拓扑 命名空间: tenant-a 默认拒绝 (Deny All) 内部允许 (Allow) Pod-A1 Pod-A2 命名空间: tenant-b 默认拒绝 (Deny All) 内部允许 (Allow) Pod-B1 Pod-B2 跨租户阻断 白名单通信 白名单通信示例 允许 tenant-a 中的 Pod-A1 访问 tenant-b 中的 Pod-B2(仅限 443 端口) 阻断流量 允许流量 租户 A Pod 租户 B Pod 命名空间边界

4.6 策略生效验证与排错

部署 NetworkPolicy 后,需要通过以下方法验证隔离效果:

  1. 使用 kubectl describe networkpolicy 查看策略详情。
  2. 使用 kubectl run 临时 Pod 进行连通性测试,例如 kubectl run test --image=busybox --rm -it -- wget -O- http://pod-ip。
  3. 检查 CNI 插件日志,确认策略是否被正确下发到节点。
  4. 使用网络诊断工具(如 netshoot)进行抓包分析。
常见问题: 如果策略未生效,请检查:
- CNI 插件是否支持 NetworkPolicy(如 Calico、Cilium、Weave Net 支持,Flannel 默认不支持)。
- Pod 标签是否与策略中的 podSelector 匹配。
- 命名空间标签是否与 namespaceSelector 匹配。
- 策略是否按顺序应用(Kubernetes 中 NetworkPolicy 是累加的,非覆盖)。

4.7 多租户 NetworkPolicy 配置清单

配置项 说明 示例值
podSelector 选择策略作用的 Pod matchLabels: {app: web}
policyTypes 指定策略类型(Ingress/Egress) [Ingress, Egress]
ingress.from 允许入站流量的来源 podSelector / namespaceSelector / ipBlock
egress.to 允许出站流量的目标 podSelector / namespaceSelector / ipBlock
ports 限制通信端口和协议 - protocol: TCP port: 443
总结: 基于 NetworkPolicy 的租户隔离实现,通过“默认拒绝 + 内部允许 + 白名单”三层策略模型,能够有效构建多租户环境下的网络边界。结合命名空间隔离和标签体系,可以实现灵活、安全、可扩展的租户网络拓扑。