1. 多租户网络基础:概念、隔离需求与 NetPolicy 角色

1.1 多租户概念与核心特征

多租户(Multi-Tenancy)是一种软件架构模式,允许单个 Kubernetes 集群实例同时服务多个相互隔离的“租户”。每个租户可以是一个团队、一个项目、一个业务线或一个外部客户。在 Kubernetes 语境下,租户通常对应一个 命名空间(Namespace) 或一组命名空间的集合。

特征 说明
资源隔离 租户之间不能越权访问对方的 Pod、Service、ConfigMap 等资源。
网络隔离 租户的 Pod 流量默认不能进入其他租户的 Pod,除非显式授权。
配额管理 每个租户拥有独立的 CPU、内存、存储等资源配额,防止“吵闹邻居”效应。
身份与权限 通过 RBAC 控制不同租户对集群 API 的访问范围。
实践要点: 在 Kubernetes 中,命名空间是最常用的租户边界。但多租户不仅限于命名空间,还可以通过“虚拟集群”或“租户 CRD”实现更细粒度的控制。

1.2 网络隔离需求:为什么默认网络不隔离?

Kubernetes 默认的网络模型是“扁平网络”:集群内所有 Pod 都可以直接通信,无论它们属于哪个命名空间。这种设计简化了服务发现和微服务调用,但在多租户场景下带来了严重的安全风险。

  • 风险一:数据泄露 —— 租户 A 的数据库 Pod 可能被租户 B 的恶意 Pod 直接访问。
  • 风险二:横向移动 —— 攻击者攻破一个租户的 Pod 后,可以自由扫描并攻击集群内其他租户的服务。
  • 风险三:流量干扰 —— 一个租户的高流量应用可能耗尽网络带宽,影响其他租户的延迟和吞吐。

因此,多租户集群必须引入 网络隔离策略,将默认的“允许所有”转变为“默认拒绝,按需放行”。

常见误区: 仅靠命名空间隔离并不能阻止网络层面的互通。命名空间只是逻辑分组,Pod 仍然可以通过 IP 地址直接跨命名空间通信。网络隔离必须通过 NetworkPolicy 或 CNI 插件(如 Calico、Cilium)的额外机制来实现。

1.3 NetPolicy 在 Kubernetes 中的角色

NetworkPolicy(简称 NetPolicy)是 Kubernetes 原生的 API 资源,用于定义 Pod 组之间的网络通信规则。它在多租户架构中扮演着 “网络防火墙” 的角色,是实施租户间隔离的核心工具。

NetPolicy 的工作机制基于以下三个要素:

  1. 选择器(PodSelector) —— 指定策略作用于哪些 Pod(通常通过标签选择)。
  2. 策略类型(PolicyTypes) —— 定义是控制入站流量(Ingress)、出站流量(Egress),还是两者都控制。
  3. 规则(Ingress/Egress Rules) —— 定义允许哪些来源(IP 段、命名空间、Pod 标签)访问目标 Pod,或允许目标 Pod 访问哪些目的地。

下面这张图展示了 NetPolicy 在集群中的核心位置与作用范围:

NetPolicy 在多租户集群中的角色 Kubernetes 集群 租户 A(Namespace: tenant-a) Pod: frontend Pod: backend 允许 NetPolicy: allow-internal 租户 B(Namespace: tenant-b) Pod: web Pod: db NetPolicy: deny-other-tenants 默认拒绝 NetPolicy 核心作用 1. 租户内 Pod 默认允许通信(通过 allow-internal 策略) 2. 跨租户流量默认被拒绝(通过 deny-other-tenants 策略)

1.4 NetPolicy 与 CNI 插件的关系

NetPolicy 本身只是一个 API 定义,真正的网络规则执行依赖于底层的 CNI(Container Network Interface)插件。如果集群使用的 CNI 插件不支持 NetworkPolicy(例如 Flannel 的默认模式),那么定义的策略将不会生效。

CNI 插件 NetPolicy 支持 多租户特性
Calico ✅ 原生支持 支持全局网络策略、租户级隔离、BGP 路由
Cilium ✅ 原生支持 基于 eBPF 的高性能策略,支持 L3-L7 隔离
Weave Net ✅ 支持 支持加密通信,适合跨主机租户隔离
Flannel ❌ 默认不支持 需配合 kube-router 或 Calico 的 policy-only 模式
关键结论: 在多租户集群中,NetPolicy 是定义“谁可以访问谁”的声明式接口,而 CNI 插件是执行这些规则的底层引擎。两者缺一不可。排查网络故障时,首先要确认 CNI 插件是否支持并正确实现了 NetworkPolicy。

1.5 多租户网络隔离的典型策略模式

在实际生产环境中,多租户网络隔离通常采用以下三种策略模式的组合:

  • 默认拒绝所有入站流量 —— 每个租户的 Pod 默认不接收来自任何来源的流量,除非显式添加允许规则。
  • 允许同命名空间内通信 —— 允许同一租户内的 Pod 互相访问,便于微服务调用。
  • 显式允许跨租户通信 —— 对于需要共享的服务(如监控、日志收集),通过精细的标签选择器或 IP 段规则放行特定流量。

下面是一个典型的“默认拒绝 + 同命名空间允许”策略示例:

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

第一个策略拒绝所有入站流量,第二个策略允许来自同一命名空间的流量。两个策略叠加后,租户 A 的 Pod 只能被同命名空间的 Pod 访问,外部流量全部被阻断。

排障提示: 当多租户网络出现连通性问题时,首先检查目标 Pod 所在命名空间是否存在 NetworkPolicy 资源。使用 kubectl get netpol -n <namespace> 查看策略列表,然后使用 kubectl describe netpol <name> -n <namespace> 检查规则细节。如果策略为空或缺失,则可能意味着网络处于“默认允许”状态,这往往是安全事件的根源。