4. 网络隔离策略(NetworkPolicy)
在多租户 Kubernetes 集群中,仅靠命名空间(Namespace)的逻辑隔离远远不够。恶意 Pod 或配置错误的组件可能绕过命名空间边界,访问其他租户的资源。NetworkPolicy 是 Kubernetes 原生的网络隔离声明式资源,它通过标签选择器定义 Pod 之间、Pod 与外部端点之间的流量规则,是实现多租户网络隔离的核心手段。
4.1 NetworkPolicy 定义与核心字段
NetworkPolicy 属于 networking.k8s.io/v1 API 组,其声明式 YAML 结构包含以下关键字段:
| 字段 | 类型 | 说明 |
|---|---|---|
podSelector |
LabelSelector | 选择策略生效的目标 Pod(必须字段) |
policyTypes |
[]string | 指定策略类型:Ingress、Egress 或两者 |
ingress |
[]IngressRule | 入站规则:允许哪些来源访问目标 Pod |
egress |
[]EgressRule | 出站规则:目标 Pod 允许访问哪些目的地 |
关键理解:NetworkPolicy 是“白名单”机制。一旦命名空间内存在任何 NetworkPolicy 匹配某个 Pod,该 Pod 默认拒绝所有未显式允许的流量。没有 NetworkPolicy 的命名空间,默认允许所有流量。
4.2 Pod 选择器与策略类型
4.2.1 Pod 选择器(podSelector)
通过标签选择器精确匹配目标 Pod。空选择器 {} 匹配命名空间内所有 Pod。
# 示例:选择标签 app=web 的 Pod
podSelector:
matchLabels:
app: web
4.2.2 策略类型(policyTypes)
显式声明策略生效方向,避免歧义:
- Ingress:控制入站流量。未指定时,默认只对 Ingress 规则生效。
- Egress:控制出站流量。必须显式声明才能生效。
- 同时声明:同时控制入站和出站,实现双向隔离。
常见陷阱:如果只写
ingress 规则但未在 policyTypes 中包含 Egress,出站流量不会被策略限制。反之亦然。建议始终显式声明 policyTypes。
4.3 多租户网络隔离实战
假设集群中有两个租户:租户 A(命名空间 tenant-a)和 租户 B(命名空间 tenant-b)。要求:
- 租户 A 的 Pod 只能与同命名空间内的 Pod 通信。
- 租户 B 的 Pod 可以访问租户 A 中标签为
app: api的 Pod(跨租户白名单)。 - 所有 Pod 禁止访问公网(除 DNS 解析外)。
4.3.1 租户 A 的隔离策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tenant-a-isolation
namespace: tenant-a
spec:
podSelector: {} # 匹配命名空间内所有 Pod
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: tenant-a
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: tenant-a
- to:
- namespaceSelector: {} # 允许访问 kube-system 的 DNS
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
4.3.2 租户 B 的跨租户访问策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tenant-b-to-tenant-a-api
namespace: tenant-a
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: tenant-b
实战要点:
namespaceSelector与podSelector可组合使用,实现精细的跨命名空间访问控制。- DNS 解析通常由
kube-dns或CoreDNS提供,必须显式放行 UDP 53 端口,否则 Pod 无法解析域名。 - NetworkPolicy 依赖 CNI 插件支持(如 Calico、Cilium、Weave Net)。部分 CNI 不支持 Egress 策略,需提前验证。
4.4 网络隔离策略工作流程
下图展示了多租户场景下 NetworkPolicy 的匹配与流量控制逻辑:
4.5 策略验证与排错
部署 NetworkPolicy 后,使用以下方法验证隔离效果:
| 验证方法 | 命令/工具 | 预期结果 |
|---|---|---|
| 查看策略是否生效 | kubectl get networkpolicy -n tenant-a |
显示已创建的策略列表 |
| 测试 Pod 连通性 | kubectl exec -n tenant-b pod/frontend -- curl -m 3 http://service-a:8080 |
白名单路径成功,其他路径超时 |
| 检查 DNS 解析 | kubectl exec -n tenant-a pod/web -- nslookup kubernetes.default |
成功返回 IP(证明 DNS 放行正常) |
| 审计日志 | CNI 插件自带工具(如 calicoctl、cilium monitor) |
查看被拒绝的流量记录 |
排错建议:如果策略未按预期生效,首先检查 CNI 插件是否支持 NetworkPolicy(如 Flannel 默认不支持)。其次确认
policyTypes 字段是否显式声明,以及 namespaceSelector 的标签是否正确(Kubernetes 1.22+ 推荐使用 kubernetes.io/metadata.name 标签匹配命名空间名称)。
4.6 多租户网络隔离最佳实践
- 默认拒绝所有流量:为每个租户命名空间创建一条默认拒绝所有 Ingress 和 Egress 的策略,再逐步添加白名单规则。
- 使用命名空间标签:为每个租户命名空间打上唯一标签(如
tenant: alpha),便于namespaceSelector批量匹配。 - 分层策略:将全局策略(如允许监控系统访问)与租户级策略分开管理,避免策略冲突。
- 策略即代码:将 NetworkPolicy YAML 纳入 GitOps 流程,通过 CI/CD 自动部署并验证隔离效果。
- 监控与告警:集成网络流量审计工具,对违反策略的访问行为进行实时告警。
通过 NetworkPolicy 的声明式定义,多租户集群可以实现细粒度、可审计的网络隔离,为后续的制品签名链路和发布证据链提供安全的网络基础。