一、为什么你需要 NetworkPolicy?
Kubernetes 默认情况下,Pod 与 Pod 之间的网络是完全开放的。这虽然利于通信,但从安全的角度来看极其危险,特别是在以下场景中:
- 多租户集群,不同业务线之间需要隔离;
- 防止横向移动攻击(Lateral Movement);
- 金融/政企场景有合规要求(如等保三级);
- 需要精细控制哪些 Pod 能访问数据库等敏感服务。
NetworkPolicy 就是 K8s 提供的“东向流量控制机制” ,能精细控制网络访问权限,防止“Pod 裸奔”。
二、NetworkPolicy 是什么?
NetworkPolicy 是一种 Kubernetes 资源,用来控制:
- 哪些 Pod 可以访问其他 Pod;
- 哪些命名空间或 IP 范围可以访问特定 Pod;
- 控制入站(Ingress)和出站(Egress)网络流量。
重要前提:需要网络插件支持(如 Calico、Cilium、Weave Net)。K8s 原生并不强制执行 NetworkPolicy。
三、语法结构详解
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-access
spec:
podSelector: # 选中“被访问”的 Pod
matchLabels:
role: db
policyTypes:
- Ingress
ingress: # 定义“谁可以访问”
- from:
- podSelector:
matchLabels:
role: api
逐项解释:
- podSelector:选中哪些 Pod 受本策略保护;
- policyTypes:定义策略类型,常见为 Ingress(进入)或 Egress(出去);
- ingress.from:指定允许哪些来源访问该 Pod。
四、实战场景一:只允许特定 Pod 访问数据库
目标:只有 role=api 的 Pod 能访问 role=db 的 Pod。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-allow-only-api
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: api
效果:非 API Pod 将无法访问 DB,即使在同一命名空间。
注意:一旦为某 Pod 应用了 NetworkPolicy,没有明确“允许”的来源,其余访问会被默认拒绝。
五、实战场景二:跨命名空间访问控制
目标:允许来自 namespace: team-a 的 role=frontend 访问 namespace: team-b 的 role=backend。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: team-b
spec:
podSelector:
matchLabels:
role: backend
ingress:
- from:
- namespaceSelector:
matchLabels:
name: team-a
podSelector:
matchLabels:
role: frontend
用法要点:
- namespaceSelector 控制跨 NS;
- podSelector 控制具体 Pod;
- 必须部署在目标命名空间(即被访问方所在 NS)。
六、实战场景三:禁止 Pod 访问外网(Egress)
目标:防止某些 Pod 访问公网,只允许访问内网资源(如内部 API)。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-egress
spec:
podSelector:
matchLabels:
app: secure-service
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/8 # 仅允许访问内网
无此策略时,Pod 可随意访问公网!这在金融、运营商行业中风险极大。
七、测试 NetworkPolicy 的正确姿势
✅ 推荐使用以下方式测试是否生效:
- 使用 busybox 容器作为 curl 测试器:
kubectl run curl --rm -it --image=busybox:1.28 --restart=Never -- sh
- 进入容器内部:
wget --spider http://myservice.default.svc.cluster.local
- 根据返回的连接结果判断策略是否生效。
八、常见误区与最佳实践
| 误区/问题 | 正确做法 |
|---|---|
| 忽略网络插件是否支持 | 使用如 Calico、Cilium 这类支持 NetworkPolicy 的插件 |
| 写了策略没生效 | 确认是否选择了正确的 podSelector 和 namespaceSelector |
| 想“禁止所有访问”却放开了默认值 | 一旦启用策略,需要显式写出所有允许的访问规则 |
| 将 NetworkPolicy 写在错误命名空间 | 策略必须部署在被保护 Pod 所在命名空间 |
| 使用 subnet IP 而不是服务名 | 尽量使用 K8s Service 名称作为目标而非裸 IP,避免漂移 |
九、总结:掌握 K8s 网络策略的核心要点
| 维度 | 建议实践 |
|---|---|
| 启用网络插件 | 使用支持 NetworkPolicy 的 CNI 插件 |
| 最小权限原则 | 只允许必要的通信,默认拒绝其他访问 |
| Ingress + Egress 配合使用 | 控制内外流量,提升安全性 |
| 多策略组合 | 一组 Pod 可匹配多个策略,注意覆盖顺序 |
| 版本控制与 GitOps 管理 | 推荐将 NetworkPolicy 纳入版本控制 |