文章背景图

Kubernetes NetworkPolicy 实战:默认拒绝、精确放行与排障

2026-07-25
3
-
- 分钟

Kubernetes 默认更强调网络连通性:如果网络插件没有额外限制,Pod 往往可以与集群中的其他 Pod 通信。NetworkPolicy 用于在三层和四层控制流量,让应用只访问真正需要的目标。

一、NetworkPolicy 能做什么

NetworkPolicy 可以控制选中 Pod 的入站(Ingress)和出站(Egress)连接,主要匹配 TCP、UDP,以及在实现支持时的 SCTP 流量。

允许来源或目标时,可以使用:

1. podSelector:按 Pod 标签选择。

2. namespaceSelector:按命名空间标签选择。

3. ipBlock:按 CIDR 网段选择。

4. ports:限制协议和端口。

它不是七层防火墙,不能原生按 HTTP URL、请求方法或用户身份授权;也不负责 TLS 加密、应用认证和内容审计。这些需求通常要结合 Ingress、Gateway、Service Mesh 或应用自身能力。

二、先确认 CNI 是否真正支持

NetworkPolicy 是 Kubernetes API,但真正执行规则的是网络插件。集群必须使用支持 NetworkPolicy 的 CNI 或策略引擎。

如果实现不支持,YAML 仍可能创建成功,却不会产生任何隔离效果。因此上线前必须查看所用 CNI 的官方文档,并通过真实连接测试验证,而不能只看:

kubectl get networkpolicy

三、默认行为与隔离触发条件

没有策略选中 Pod 时,Pod 在相应方向通常是非隔离的,也就是默认允许。

当某个 NetworkPolicy 选中 Pod,并在 policyTypes 中包含 Ingress 时,该 Pod 的入站流量开始受策略限制;包含 Egress 时,出站流量开始受限制。

多个策略不会按先后顺序覆盖,也不存在传统防火墙那种“第一条命中”。适用于同一 Pod 的允许规则会合并,最终结果是所有允许集合的并集。

一次 Pod 到 Pod 的连接要成功,源 Pod 的出站策略和目标 Pod 的入站策略都必须允许。任意一侧不允许,连接就不会建立。

四、建立命名空间默认拒绝

下面的策略选择当前命名空间内所有 Pod,并拒绝所有未明确允许的入站和出站连接:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

name: default-deny-all

namespace: production

spec:

podSelector: {}

policyTypes:

- Ingress

- Egress

podSelector: {} 表示选中该命名空间中的全部 Pod。空的 ingress 和 egress 允许列表意味着没有业务流量被放行。

不要在生产命名空间里直接套用后就离开。默认拒绝可能同时阻断 DNS、监控、配置中心、数据库、外部 API 和健康检查,应先梳理依赖并准备回滚方案。

五、只允许前端访问后端

假设 backend 命名空间中的 api Pod 监听 TCP 8080,只允许 frontend 命名空间内带 app=web 标签的 Pod 访问:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

name: allow-frontend-to-api

namespace: backend

spec:

podSelector:

matchLabels:

app: api

policyTypes:

- Ingress

ingress:

- from:

- namespaceSelector:

matchLabels:

kubernetes.io/metadata.name: frontend

podSelector:

matchLabels:

app: web

ports:

- protocol: TCP

port: 8080

namespaceSelector 和 podSelector 位于同一个 from 条目中,因此是 AND 关系:来源必须同时满足命名空间和 Pod 标签。

如果把它们写成两个独立的列表项,则会变成 OR 关系:允许整个 frontend 命名空间,或者允许当前策略语义下匹配 app=web 的另一组 Pod。缩进看似只差一点,授权范围可能扩大很多。

六、放行 DNS

启用默认拒绝出站后,应用经常首先出现 DNS 解析失败。需要根据集群 DNS 的实际命名空间、标签、协议和端口放行 UDP/TCP 53。

一个常见思路如下,但标签必须以你的集群为准:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

name: allow-dns

namespace: production

spec:

podSelector: {}

policyTypes:

- Egress

egress:

- to:

- namespaceSelector:

matchLabels:

kubernetes.io/metadata.name: kube-system

podSelector:

matchLabels:

k8s-app: kube-dns

ports:

- protocol: UDP

port: 53

- protocol: TCP

port: 53

有些集群使用不同的 DNS 标签或实现,创建前应先执行:

kubectl get pods -n kube-system --show-labels

kubectl get service -n kube-system

七、使用 ipBlock 的注意事项

ipBlock 适合描述集群外网段,例如允许访问某个受控 API 网段:

ipBlock:

cidr: 203.0.113.0/24

except:

- 203.0.113.128/25

但 Service、负载均衡器和节点网络可能进行地址转换。NetworkPolicy 在 DNAT 或 SNAT 前后看到哪个地址,可能因网络插件、云环境和数据路径而不同。

不要用 Pod IP 范围替代 podSelector;Pod 是动态的,标签选择器更符合 Kubernetes 的管理方式。

八、安全上线步骤

1. 列出应用真实依赖,包括 DNS、数据库、缓存、监控、日志、镜像和外部 API。

2. 统一命名空间和 Pod 标签,避免选择器含义不清。

3. 先写允许规则,再逐步启用默认拒绝。

4. 在测试命名空间做正向与反向测试。

5. 小范围上线并观察连接失败、超时和网络插件日志。

6. 保存回滚清单,避免策略错误导致运维入口一起被阻断。

九、验证与排障

查看策略和目标标签:

kubectl get networkpolicy -A

kubectl describe networkpolicy -n production

kubectl get pod -n production --show-labels

kubectl get namespace --show-labels

从允许来源测试目标:

kubectl exec -n frontend <POD_NAME> -- \

wget -S -O- http://api.backend.svc.cluster.local:8080

再从未授权来源执行同样测试,确认它失败。只做“应该成功”的测试不够,还必须验证“应该失败”的路径确实被拒绝。

排障时按顺序检查:

1. 策略是否选中了预期 Pod。

2. namespaceSelector 与 podSelector 是 AND 还是 OR。

3. 源 Egress 和目标 Ingress 是否同时允许。

4. 端口是 Service port、targetPort 还是容器实际监听端口。

5. DNS 是否已放行。

6. CNI 是否支持并成功加载策略。

7. 云安全组、节点防火墙或 Service Mesh 是否还有额外限制。

十、NetworkPolicy 的边界

NetworkPolicy 主要解决 L3/L4 连通性,不等同于完整的零信任体系。它通常不能表达 HTTP 路径权限、用户身份、请求内容审计、数据加密或应用层速率限制。

更完整的防护还应包括:最小权限 RBAC、Pod Security、Secret 管理、镜像供应链、安全上下文、TLS、审计日志和运行时监控。

总结

NetworkPolicy 最适合采用“默认拒绝、按业务依赖精确放行”的模型。真正困难的不是 YAML 语法,而是识别真实通信关系、正确理解选择器逻辑,并通过正反测试证明策略确实生效。

参考资料:

https://kubernetes.io/docs/concepts/services-networking/network-policies/

https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy/

原创

Kubernetes NetworkPolicy 实战:默认拒绝、精确放行与排障

本文链接: Kubernetes NetworkPolicy 实战:默认拒绝、精确放行与排障

本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

评论交流

文章目录