第280篇:云原生网络策略 NetworkPolicy 实现
关键词:NetworkPolicy、Kubernetes、网络策略、Calico、Cilium、Iptables、eBPF、安全组
一、引言
Kubernetes NetworkPolicy是K8s原生的网络安全策略API,用于控制Pod之间的网络访问权限。NetworkPolicy本身只是一个API规范,其实际执行依赖于CNI插件的数据面实现。
本文将深入解析NetworkPolicy的工作原理、不同CNI插件的实现差异,以及在实际生产环境中的最佳实践。
二、核心概念
2.1 NetworkPolicy API
NetworkPolicy的核心字段:
| 字段 | 说明 |
|---|---|
| podSelector | 选择策略应用的Pod |
| ingress | 入站规则列表 |
| egress | 出站规则列表 |
| policyTypes | 策略类型(Ingress/Egress) |
| namespaceSelector | 选择源/目的命名空间 |
规则匹配元素:
| 元素 | 说明 |
|---|---|
| podSelector | 匹配Pod标签 |
| namespaceSelector | 匹配命名空间标签 |
| ipBlock | 匹配CIDR地址段 |
| ports | 匹配端口和协议 |
2.2 NetworkPolicy 匹配逻辑
NetworkPolicy的匹配规则:
| 条件 | 匹配逻辑 |
|---|---|
| 多个ingress规则 | 任一规则匹配即允许(OR) |
| 规则内的多个from | 任一from匹配即允许(OR) |
| from内的多个条件 | 满足任一条件即匹配(OR) |
| 无ingress规则 | 拒绝所有入站流量 |
| policyTypes不含Ingress | 不限制入站流量 |

2.3 不同 CNI 的实现差异
| CNI | 数据面 | 实现方式 | L4支持 | L7支持 |
|---|---|---|---|---|
| Calico(Iptables) | Iptables | 每个Pod生成iptables规则 | ✓ | ✗ |
| Calico(eBPF) | eBPF | eBPF程序+Map | ✓ | ✗ |
| Cilium | eBPF | 原生eBPF策略引擎 | ✓ | ✓ |
| OVS | OpenFlow | OVS流表 | ✓ | ✗ |
| kube-router | Iptables | iptables规则 | ✓ | ✗ |
2.4 NetworkPolicy 与 安全组对比
| 特性 | 云安全组 | K8s NetworkPolicy |
|---|---|---|
| 粒度 | 实例级 | Pod级 |
| 选择器 | IP/安全组 | Pod标签/命名空间标签 |
| 状态检测 | 有(状态型) | 有(有状态策略) |
| L7策略 | 不支持 | Cilium支持 |
| 动态更新 | API | K8s API |
| 默认策略 | 云厂商定义 | 取决于CNI |
三、技术细节
3.1 Calico Iptables 模式实现
Calico在iptables模式下,为每个Pod生成两条iptables链:
FORWARD链处理流程:

3.2 Calico eBPF 模式实现
Calico的eBPF模式使用eBPF程序替代iptables:
| 组件 | 说明 |
|---|---|
| CNI插件 | 创建veth pair, 加载eBPF程序 |
| eBPF TC程序 | 挂载到veth的ingress/egress |
| Policy Map | eBPF Map存储策略规则 |
| Identity | 每个Pod分配唯一的Security Identity |
3.3 Cilium 原生实现
Cilium的eBPF原生实现是最为高效的:
| 特性 | 说明 |
|---|---|
| 端点标识 | 每个Pod分配唯一的Security ID |
| eBPF程序 | 直接在内核网络栈执行策略检查 |
| L7策略 | 基于eBPF Socket程序实现HTTP/gRPC过滤 |
| 策略编译 | 策略编译为高效的eBPF字节码 |
3.4 NetworkPolicy 有状态策略
有状态(Stateful)策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: stateful-web-policy
namespace: default
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: client
ports:
- protocol: TCP
port: 80
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
ports:
- protocol: TCP
port: 443
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
3.5 策略即代码(Policy as Code)
将NetworkPolicy纳入GitOps工作流,实现策略的版本管理和自动化部署:

GitOps策略管理流程:
| 步骤 | 工具 | 说明 |
|---|---|---|
| 编写策略 | 编辑器 | YAML格式NetworkPolicy |
| 语法校验 | kubeval/kubeconform | 检查YAML语法和API版本 |
| 策略模拟 | Cilium NP Simulator | 模拟策略效果, 预览允许/拒绝的流量 |
| 冲突检测 | kubectl-np-viewer | 检测策略冲突和重叠 |
| 代码审查 | Git PR Review | 团队审核策略变更 |
| 自动部署 | ArgoCD/Flux | GitOps控制器自动同步到集群 |
3.6 NetworkPolicy 可视化与调试
| 工具 | 功能 | 特点 |
|---|---|---|
| kubectl-np-viewer | NetworkPolicy可视化 | 生成HTML拓扑图 |
| Cilium Hubble | 流量观察和策略调试 | 实时流日志, 服务拓扑 |
| Calico CLI | 策略查询和调试 | calicoctl get networkpolicy |
| Cyclonus | 默认拒绝策略批量部署 | 一键部署default-deny |
| Network Policy Editor | 在线策略编辑器 | 图形化编辑NetworkPolicy |
Cilium Hubble调试示例:
# 1. 观察特定Pod的入站流量
hubble observe --pod app-pod --protocol tcp --verdict forwarded
# 2. 观察被策略拒绝的流量
hubble observe --verdict dropped --reason policy_DENIED
# 3. 生成服务依赖图
hubble lens graph --json
# 4. 查询特定流量路径
hubble flow get --source-pod app-pod --destination-pod db-pod
# 5. 查看策略覆盖率
hubble status
3.7 NetworkPolicy 与 外部防火墙协同
| 协同维度 | NetworkPolicy | 外部防火墙 | 协同策略 |
|---|---|---|---|
| 作用范围 | Pod间(L3/L4) | 集群边界(L3-L7) | 分层防御 |
| granularity | Pod级 | IP/端口级 | 内外互补 |
| 策略管理 | K8s API | 防火墙管理台 | 统一策略平台 |
| 审计 | K8s审计日志 | 防火墙日志 | 集中日志分析 |
| 故障隔离 | Pod间隔离 | 南北向隔离 | 全向防护 |
四、实战配置/案例分析
4.1 完整的租户网络策略模板
# 1. 默认拒绝所有入站和出站
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: tenant-a
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# 2. 允许同命名空间内通信
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-ns
namespace: tenant-a
spec:
podSelector: {}
ingress:
- from:
- podSelector: {}
policyTypes:
- Ingress
---
# 3. 允许DNS解析
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: tenant-a
spec:
podSelector: {}
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
policyTypes:
- Egress
---
# 4. 允许Ingress访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress
namespace: tenant-a
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
policyTypes:
- Ingress
4.2 故障案例:NetworkPolicy Egress规则遗漏导致应用异常
现象:某应用Pod无法连接外部API服务,但同命名空间内的其他Pod通信正常。
排查过程:
# 1. 检查NetworkPolicy
kubectl get networkpolicy -n app-ns
# 存在default-deny策略和有限的egress规则
# 2. 从Pod测试外部连接
kubectl exec app-pod -- curl https://api.external.com/data
# 连接超时
# 3. 检查egress规则
kubectl get networkpolicy -n app-ns -o yaml
# egress规则只允许DNS(UDP 53)和内部K8s服务
# 没有放行HTTPS(TCP 443)到外部地址的规则
# 4. 添加egress规则
kubectl apply -f external-api-egress.yaml
根因:NetworkPolicy的egress规则配置不完整,只放行了DNS和内部K8s服务的流量,未放行到外部API的HTTPS流量。
解决:
1. 添加egress规则放行外部API的HTTPS流量
2. 建议在NetworkPolicy模板中包含常见的egress规则(DNS、HTTP/HTTPS、NTP等)
3. 使用kubectl-np-viewer等可视化工具审计NetworkPolicy
4.3 故障案例:Calico策略链性能下降
现象:当集群中NetworkPolicy数量超过1000条时,Pod间通信延迟明显增加。
排查过程:
# 1. 检查iptables规则数量
iptables -L -n | wc -l
# 规则数超过5000条
# 2. 检查Calico策略链长度
iptables -S CALICO-FORWARD | wc -l
# 策略链非常长
# 3. 分析性能瓶颈
# Iptables模式需要线性遍历所有规则
# 规则越多, 匹配时间越长
# 4. 切换到Calico eBPF模式
# 升级Calico到支持eBPF的版本
# 配置CALICO_DATASTORE_TYPE=kubernetes
# 配置FELIX_BPFENABLEDTYPE=Fat
根因:Calico的iptables模式需要线性遍历策略链,当NetworkPolicy数量众多时,每条报文的策略检查时间线性增加,导致延迟上升。
解决: 1. 迁移到Calico eBPF模式,利用哈希查找替代线性遍历 2. 精简NetworkPolicy规则,减少不必要的策略 3. 使用命名空间级别的默认策略,减少Pod级别的细粒度策略
五、总结
| CNI实现 | 数据面 | 性能 | L7支持 | 推荐场景 |
|---|---|---|---|---|
| Calico Iptables | iptables | 中(规则多时下降) | ✗ | 中小集群 |
| Calico eBPF | eBPF | 高 | ✗ | 大规模集群 |
| Cilium | eBPF | 最高 | ✓ | 微服务/L7需求 |
| OVS | OpenFlow | 中 | ✗ | OVS环境 |
| 最佳实践 | 说明 |
|---|---|
| 默认拒绝 | 始终部署default-deny策略 |
| 最小权限 | 只开放必要的端口和地址 |
| 策略分层 | 命名空间级+Pod级策略结合 |
| 定期审计 | 使用可视化工具审计策略 |
| eBPF优先 | 大规模集群使用eBPF数据面 |
| 策略即代码 | GitOps管理策略变更 |
| 策略模拟 | 部署前使用模拟器验证策略效果 |
思考
- NetworkPolicy只能控制L3/L4流量,如何控制L7(HTTP/gRPC)级别的访问权限?
- NetworkPolicy的
podSelector: {}(空选择器)匹配什么Pod?与不指定podSelector有什么区别? - 如果集群中同时存在多个NetworkPolicy匹配同一个Pod,它们之间如何交互?
- 策略即代码(Policy as Code)模式下,如何避免策略变更导致业务中断?
- Cilium Hubble如何帮助调试NetworkPolicy?与传统的tcpdump抓包相比有什么优势?
下篇预告:第281篇:华为 CloudFabric 数据中心方案简介