4. 网络隔离策略:NetworkPolicy 原理、Ingress/Egress 规则、多租户网络隔离实战、Calico/Cilium 集成
在多租户 Kubernetes 集群中,网络隔离是防止租户间横向移动攻击、保障数据合规与业务边界的关键防线。本章从 Kubernetes 原生 NetworkPolicy 的声明式模型出发,逐步深入到 Ingress/Egress 规则设计、多租户网络隔离实战模式,并对比 Calico 与 Cilium 两大主流 CNI 插件的集成方案。
4.1 NetworkPolicy 核心原理
NetworkPolicy 是 Kubernetes 中用于控制 Pod 间网络访问的 API 资源。它通过标签选择器(Label Selector)定义“谁可以访问谁”,而非基于 IP 地址或 CIDR 块,从而与 Pod 的动态生命周期解耦。
| 概念 | 说明 | 示例 |
|---|---|---|
| PodSelector | 指定策略生效的目标 Pod 集合 | matchLabels: { app: frontend } |
| PolicyTypes | 声明策略类型:Ingress、Egress 或两者 | Ingress / Egress |
| Ingress 规则 | 定义允许进入 Pod 的流量来源 | from: - podSelector: ... |
| Egress 规则 | 定义允许 Pod 外发的流量目标 | to: - ipBlock: ... |
| 默认拒绝 | 一旦有 NetworkPolicy 匹配 Pod,未显式允许的流量默认被拒绝 | 白名单模型 |
关键理解: NetworkPolicy 是“白名单”机制。只要 Namespace 中存在一条匹配 Pod 的 NetworkPolicy,该 Pod 的所有未显式允许的入站或出站流量都会被拒绝。因此,多租户隔离通常从“默认拒绝所有”策略开始,再逐条开放必要规则。
4.2 Ingress / Egress 规则详解
4.2.1 Ingress 规则
Ingress 规则控制进入 Pod 的流量。支持三种来源选择器:
- podSelector:允许来自同一 Namespace 内特定标签的 Pod。
- namespaceSelector:允许来自特定 Namespace 的所有 Pod。
- ipBlock:允许来自特定 CIDR 范围的流量(如集群外服务或监控系统)。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: tenant-a
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
4.2.2 Egress 规则
Egress 规则控制 Pod 对外发起的连接。同样支持三种目标选择器,常用于限制 Pod 访问外部数据库、DNS 或互联网。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-egress-dns-only
namespace: tenant-b
spec:
podSelector:
matchLabels:
app: worker
policyTypes:
- Egress
egress:
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- to:
- ipBlock:
cidr: 10.0.0.0/8
except:
- 10.96.0.0/12 # 排除 Service CIDR
常见陷阱: 当同时定义 Ingress 和 Egress 规则时,务必检查
policyTypes 字段是否包含两者。如果只写 Ingress,Egress 规则不会生效,Pod 仍可自由外发流量。反之亦然。
4.3 多租户网络隔离实战模式
在多租户场景中,网络隔离通常采用分层策略:
- 租户级 Namespace 隔离:每个租户独占一个 Namespace,通过 RBAC 限制跨 Namespace 访问。
- 默认拒绝所有流量:在每个租户 Namespace 中部署一条拒绝所有 Ingress/Egress 的基线策略。
- 按需开放规则:根据业务需求,逐条添加允许特定 Pod 间通信的规则。
- 共享服务例外:允许访问集群 DNS、监控、日志收集等共享基础设施。
| 层级 | 策略示例 | 作用范围 |
|---|---|---|
| 基线拒绝 | 拒绝所有 Ingress + Egress | 每个租户 Namespace |
| 租户内部通信 | 允许同 Namespace 内特定标签 Pod 互访 | 单个 Namespace |
| 跨租户服务 | 允许访问共享 Namespace 中的服务 | 跨 Namespace |
| 外部访问 | 允许访问特定 CIDR 或外部 API | 集群外 |
实战建议: 使用
namespaceSelector 配合 matchLabels 实现跨租户的精细控制。例如,为共享监控 Namespace 打上 role: monitoring 标签,然后在租户策略中允许 Egress 到该标签的 Namespace。
4.4 Calico 与 Cilium 集成方案
Kubernetes 原生 NetworkPolicy 功能有限(仅支持 L3/L4 过滤),且依赖 CNI 插件实现。Calico 和 Cilium 是两大主流增强方案,各自提供了更丰富的网络隔离能力。
| 特性 | Calico | Cilium |
|---|---|---|
| 数据平面 | eBPF / iptables / Windows HNS | eBPF(内核级) |
| L3/L4 策略 | 完全兼容 Kubernetes NetworkPolicy | 完全兼容 Kubernetes NetworkPolicy |
| L7 策略 | 通过 Envoy sidecar(Application Layer Policy) | 原生 eBPF L7 策略(HTTP/gRPC/Kafka/DNS) |
| 全局网络策略 | GlobalNetworkPolicy(跨 Namespace) | CiliumClusterwideNetworkPolicy |
| DNS 策略 | 支持基于 FQDN 的 Egress 规则 | 原生支持基于 FQDN 的 Egress 规则 |
| 可观测性 | Calico Enterprise / Calico Cloud | Hubble(内置 eBPF 可观测性) |
| 性能开销 | 低(eBPF 模式) | 极低(纯 eBPF 内核态) |
4.4.1 Calico 集成要点
- 安装模式:推荐使用 eBPF 数据平面以获得最佳性能,需内核版本 ≥ 5.3。
- 全局网络策略:使用
GlobalNetworkPolicy定义跨 Namespace 的基线规则,例如“禁止所有跨租户流量”。 - FQDN 策略:通过
DNS字段在 Egress 规则中允许访问特定域名,避免硬编码 IP。 - 网络隔离层级:Calico 支持在 Namespace、节点、甚至主机级别实施隔离。
# Calico 全局网络策略示例:禁止所有跨 Namespace 流量
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: deny-cross-namespace
spec:
selector: all()
ingress:
- action: Deny
source:
namespaceSelector: "projectcalico.org/name != 'kube-system'"
notNamespaceSelector: "projectcalico.org/name == '${NAMESPACE}'"
egress:
- action: Deny
destination:
namespaceSelector: "projectcalico.org/name != 'kube-system'"
notNamespaceSelector: "projectcalico.org/name == '${NAMESPACE}'"
4.4.2 Cilium 集成要点
- 核心优势:原生 eBPF 实现,无需 iptables 或 sidecar,性能与可观测性极强。
- L7 策略:可直接在 NetworkPolicy 中定义 HTTP 方法、路径、gRPC 服务等应用层规则。
- Hubble:内置网络可观测性工具,实时查看流量、策略命中与拒绝日志。
- ClusterMesh:支持多集群网络隔离策略统一管理。
# Cilium L7 HTTP 策略示例:仅允许 GET /api/v1/orders
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-orders-api
namespace: tenant-a
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/orders"
选型建议:
- 如果团队需要 L7 策略 + 原生可观测性,且内核版本 ≥ 5.10,优先选择 Cilium。
- 如果团队已有 Calico 生态(如 Calico Enterprise),或需要 Windows 节点支持,选择 Calico。
- 两者都支持 Kubernetes 原生 NetworkPolicy,迁移成本较低。
4.5 实战:多租户网络隔离策略部署流程
- 确认 CNI 插件:检查集群当前使用的 CNI 是否支持 NetworkPolicy(Calico、Cilium、Weave、Antrea 等支持)。
- 创建基线拒绝策略:为每个租户 Namespace 创建默认拒绝所有 Ingress 和 Egress 的 NetworkPolicy。
- 开放共享服务:添加 Egress 规则允许访问 kube-system 中的 CoreDNS、监控 Namespace 中的 Prometheus 等。
- 租户内部通信:根据应用架构,添加允许同 Namespace 内特定 Pod 间通信的 Ingress 规则。
- 跨租户例外:如果存在合法的跨租户服务调用(如共享 API 网关),使用 namespaceSelector 精确开放。
- 验证与监控:使用
kubectl describe networkpolicy查看策略详情,结合 Hubble(Cilium)或 calicoctl(Calico)验证流量是否被正确允许或拒绝。
避坑指南:
- 不要忘记在
policyTypes中同时声明Ingress和Egress,否则未声明的方向不受限制。 - 使用
ipBlock时注意排除 Service CIDR 和 Pod CIDR,避免意外阻断集群内部通信。 - 在 Cilium 中启用 L7 策略前,确保已开启 Hubble 并配置正确的端口映射。