第280篇:云原生网络策略 NetworkPolicy 实现
关键词
NetworkPolicy、K8s 网络策略、Pod 选择器、Ingress/Egress 规则、策略规则、CiliumNetworkPolicy、Calico NetworkPolicy、零信任网络
一、NetworkPolicy 基础
1.1 什么是 NetworkPolicy
NetworkPolicy 是 K8s 原生资源,控制 Pod 之间以及 Pod 与外部之间的流量:
NetworkPolicy 核心模型:
NetworkPolicy spec: podSelector: {} ← 选择目标 Pod policyTypes: - Ingress ← 控制入方向 - Egress ← 控制出方向 ingress: ← 入规则 - from: - ipBlock: {...} - namespaceSelector: {...} - podSelector: {...} ports: - protocol: TCP port: 8080 egress: ← 出规则 - to: - ipBlock: {...} ports: [...]
1.2 流量控制模型
NetworkPolicy 的流量控制:
| ┌─ 入方向(Ingress)控制 ┌─ 出方向(Egress)控制 | |||
|---|---|---|---|
| 外部 ──► Pod-A ┌─ ipBlock Pod-A ──► 外部 ┌─ ipBlock ┌───────── ┤─ namespaceSelector ┌───────── ┤─ namespaceSelector ▼ ▼ 通过规则? → 允许/拒绝 通过规则? → 允许/拒绝 ┌──┴──┐ ┌──┴──┐ └─────┘ └─────┘ | └─ podSelector 通过 | └─ podSelector | 通过 |
| 关键行为: | |||
| ┌─ 未匹配任何 NetworkPolicy → 默认允许 | |||
| ├─ 匹配到一条 NetworkPolicy → 默认拒绝(白名单模式) | |||
| ├─ 多条策略取并集 → 任一策略允许即放行 | |||
| └─ 空 podSelector({})→ 匹配 Namespace 中所有 Pod |
二、策略规则详解
2.1 podSelector —— 目标 Pod
podSelector 示例:
# 选择 app=web 的 Pod
podSelector:
matchLabels:
app: web
# 选择所有 Pod(空选择器)
podSelector: {}
# 表达式选择
podSelector:
matchExpressions:
- key: tier
operator: In # In/NotIn/Exists/DoesNotExist
values:
- frontend
- backend
2.2 from/to —— 流量来源/目标
from/to 支持四种选择器:
-
podSelector(同 Namespace)
┌─ 选择源 Namespace 内的 Pod └─ 示例: from: - podSelector: matchLabels: app: frontend
-
namespaceSelector(跨 Namespace)
┌─ 选择目标 Namespace 的所有 Pod └─ 示例: from: - namespaceSelector: matchLabels: tenant: monitoring
-
namespaceSelector + podSelector 组合
┌─ 同时匹配 Namespace 和 Pod └─ 示例: from: - namespaceSelector: {} podSelector: matchLabels: app: monitoring
-
ipBlock(外部 IP)
┌─ 基于 CIDR 匹配(非 K8s 管理的 IP) └─ 示例: from: - ipBlock: cidr: 10.0.0.0/8 except: - 10.96.0.0/12 # 排除 Service CIDR
2.3 ports —— 端口与协议
ports 规则:
ports:
- protocol: TCP # TCP/UDP/SCTP(默认 TCP)
port: 80 # 单个端口
- protocol: TCP
port: 8080
- protocol: UDP
port: 53
- protocol: TCP
port: 3000-4000 # 端口范围(K8s 1.7+)
注意:
┌─ 不指定 ports → 匹配所有端口
├─ 指定 ports → 只匹配指定端口
└─ 多个 port 条目 → 任一匹配即放行
三、典型策略示例
3.1 默认拒绝所有
# 默认拒绝入站
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
# 默认拒绝出站
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
3.2 三层架构访问控制
# web 层:仅允许 Ingress 访问 80 端口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-policy
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
egress:
- to:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 8080
# api 层:仅允许 web 访问 8080,允许访问 db 3306
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-policy
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: web
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: db
ports:
- protocol: TCP
port: 3306
# db 层:仅允许 api 访问 3306
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-policy
spec:
podSelector:
matchLabels:
app: db
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 3306
3.3 DNS 出口放行
# 所有 Pod 允许出站 DNS 查询
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
四、不同 CNI 的 NetworkPolicy 实现
| CNI 方案 | 实现方式 | 性能 | 增强特性 |
|---|---|---|---|
| Calico | iptables/IPVS + Felix | 中(策略多时 iptables 规则膨胀) | 全局策略(GlobalNetworkPolicy)、HTTP 方法过滤 |
| Cilium | eBPF TC/XDP | 高(策略匹配 O(1)) | L7 策略、DNS 策略、Kafka/gRPC 策略 |
| Antrea | OVS OpenFlow | 中高 | ClusterNetworkPolicy、流量镜像 |
| Weave Net | iptables | 中 | 基本 NettworkPolicy |
| Kube-router | iptables/IPVS | 中 | 基于 iptables 的 NetworkPolicy |
4.1 Calico 增强策略
# Calico 全局网络策略(跨 Namespace)
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: deny-all-external
spec:
selector: all() # 匹配所有 Namespace 所有 Pod
ingress:
- action: Deny
source:
notSelector: "projectcalico.org/namespace == 'default'"
egress:
- action: Allow
# Calico 支持 HTTP 方法过滤
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: web-http-restrict
spec:
selector: app == 'web'
ingress:
- action: Allow
protocol: TCP
destination:
ports:
- 80
http:
methods:
- GET
- POST
paths:
- "/api/v1/*"
4.2 Cilium 增强策略(L7)
# Cilium L7 HTTP 策略
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l7-http-policy
spec:
endpointSelector:
matchLabels:
app: api
ingress:
- fromEndpoints:
- matchLabels:
app: web
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: GET
path: "/api/v1/users/.*"
- method: POST
path: "/api/v1/orders"
- method: "GET"
path: "/healthz"
# Cilium DNS 策略
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: dns-egress-allow
spec:
endpointSelector:
matchLabels:
app: web
egress:
- toEndpoints:
- matchLabels:
"k8s:io.kubernetes.pod.namespace": kube-system
"k8s:k8s-app": kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
rules:
dns:
- matchName: "*.example.com"
# Cilium 支持 Kafka/gRPC 等协议过滤
# Kafka 示例:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: kafka-policy
spec:
endpointSelector:
matchLabels:
app: kafka-broker
ingress:
- fromEndpoints:
- matchLabels:
app: producer
toPorts:
- ports:
- port: "9092"
protocol: TCP
rules:
kafka:
- apiKey: "produce"
topic: "orders"
- apiKey: "fetch"
topic: "orders"
五、策略管理最佳实践
5.1 策略设计原则
NetworkPolicy 设计原则:
1. 默认拒绝原则
┌─ 每个 Namespace 先部署默认拒绝策略
├─ 然后按需添加放行策略
└─ 确保无策略的 Pod 默认隔离
2. 最小权限原则
┌─ 只放行业务所需的最小流量
├─ 精确到端口和协议
├─ 限制出口范围(仅允许必要的 CIDR)
└─ 定期审计和收紧策略
3. 分层管理
┌─ 基础策略:DNS、监控、日志等公共策略
├─ 应用策略:业务 Pod 间访问
└─ 安全策略:跨租户、外部访问
4. 命名规范
┌─ 策略命名:<app>-<direction>-<purpose>
├─ 标签命名统一(app/tier/tenant)
└─ 使用注释描述策略用途
5.2 策略验证与故障排查
策略排查常用命令:
# 查看策略是否应用到 Pod
kubectl get networkpolicy -n <namespace>
kubectl describe networkpolicy <name> -n <namespace>
# 测试连通性(临时 Pod)
kubectl run test-pod --image=busybox -it --rm -- sh
wget -qO- http://<target-svc>:8080
# Calico 策略审计
calicoctl get networkpolicy -n <namespace> -o yaml
calicoctl get workloadendpoints -n <namespace>
# Cilium 策略验证
cilium endpoint list
cilium endpoint get <id>
cilium policy trace -n <ns> -s <src-pod> -d <dst-pod>
cilium monitor -v # 实时查看策略命中
# 常见的策略不通原因:
1. 缺少默认拒绝 → 检查是否有策略生效
2. DNS 不通 → 确保 egress 允许 DNS 53
3. 跨 Namespace 缺漏 → 检查 namespaceSelector
4. 端口不匹配 → 确认目标端口是否正确
5. 策略顺序 → 多条策略是并集,不会互相覆盖
5.3 大规模策略优化
大规模集群策略优化:
1. 减少策略数量
┌─ 使用标签组合代替每条策略一个选择器
├─ 使用全局策略(GlobalNetworkPolicy)
└─ 使用 Cilium 的 Clusterwide 策略
2. 预计算策略
┌─ Calico Felix 预计算策略 → iptables
├─ Cilium Identity 预计算 → eBPF Map
└─ 避免运行时实时评估
3. 监控策略性能
┌─ 监控策略同步延迟
├─ 监控数据面规则数量
├─ 监控策略变更频率
└─ 设置策略数量告警阈值
4. 策略即代码
┌─ 策略存储在 Git 仓库
├─ CI/CD 自动部署策略
├─ 变更前预检策略影响
└─ 自动化策略合规检查
总结
| 关键点 | 说明 |
|---|---|
| 模型核心 | podSelector 选择目标 + ingress/egress 规则 |
| 默认行为 | 未匹配策略 → 允许;匹配到策略 → 白名单模式 |
| 选择器类型 | podSelector、namespaceSelector、ipBlock |
| CNI 差异 | Cilium eBPF 最高效,Calico iptables 成熟稳定 |
| 增强策略 | Cilium L7 HTTP/DNS/Kafka,Calico HTTP 方法过滤 |
| 最佳实践 | 默认拒绝 + 最小权限 + 策略即代码 |
思考
- NetworkPolicy 的默认行为是什么?为什么说它是白名单模式?
- 如何实现"只允许同 Namespace 的 Pod 互相访问"?
- 如何放行特定 Namespace 的所有 Pod 访问本 Namespace 的某个 Pod?
- ipBlock 的 except 字段有什么用途?
- Cilium L7 策略与 K8s 原生 NetworkPolicy 有什么区别?
- 如何验证一条 NetworkPolicy 是否生效?有哪些常用排错命令?
下篇预告:第281篇 - 华为 CloudFabric 数据中心方案简介,介绍华为数据中心网络方案的整体架构、核心组件和典型部署模型。