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 的多租户隔离网络拓扑,包含两个租户命名空间、默认拒绝策略、内部允许策略以及白名单通信路径。
4.6 策略生效验证与排错
部署 NetworkPolicy 后,需要通过以下方法验证隔离效果:
- 使用
kubectl describe networkpolicy查看策略详情。 - 使用
kubectl run临时 Pod 进行连通性测试,例如kubectl run test --image=busybox --rm -it -- wget -O- http://pod-ip。 - 检查 CNI 插件日志,确认策略是否被正确下发到节点。
- 使用网络诊断工具(如
netshoot)进行抓包分析。
常见问题: 如果策略未生效,请检查:
- CNI 插件是否支持 NetworkPolicy(如 Calico、Cilium、Weave Net 支持,Flannel 默认不支持)。
- Pod 标签是否与策略中的
- 命名空间标签是否与
- 策略是否按顺序应用(Kubernetes 中 NetworkPolicy 是累加的,非覆盖)。
- 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 的租户隔离实现,通过“默认拒绝 + 内部允许 + 白名单”三层策略模型,能够有效构建多租户环境下的网络边界。结合命名空间隔离和标签体系,可以实现灵活、安全、可扩展的租户网络拓扑。