在Kubernetes集群里部署Agent类工作负载时,很多人默认认为Pod之间是隔离的,实际上只要没有配置任何NetworkPolicy,所有Pod都可以互相访问,任何Pod都能对外发起任意连接。对于一个采集指标、上报日志、可能还持有敏感凭证的Agent来说,这种默认全通的网络环境风险不小。本文围绕NetworkPolicy和防火墙两条线,聊聊如何为Agent构建一套行之有效的网络隔离策略。

一、为什么NetworkPolicy是Agent隔离的第一道防线
Kubernetes的网络模型要求Pod之间可以直接通信,不经过NAT。这意味着只要攻击者拿到集群内任意一个Pod的执行权限,就能扫描整个Pod网络。NetworkPolicy的作用就是在Pod级别做访问控制,它是K8s原生的API资源,由CNI插件负责真正落地执行。
需要注意的一点是,NetworkPolicy是白名单语义。一旦某个Pod被一条策略选中,那么所有未被策略明确允许的流量都会被丢弃。这一点和传统防火墙的黑名单思维正好相反,理解了这一点才能正确设计规则。另外一个关键前提是:NetworkPolicy需要CNI插件支持,如果集群用的是不支持网络策略的CNI(比如早期的Flannel),配置了NetworkPolicy也不会生效,策略会被静默忽略,这在排查问题时经常让人困惑。
对于Agent场景,典型的需求有两类:一是限制Agent只能访问特定的API地址和端口,防止被攻破后横向移动;二是限制谁可以访问Agent的端口,避免Agent暴露的管理接口被集群内其他工作负载随意调用。这两个需求分别对应Egress和Ingress策略。
二、用default deny构建最小权限基线
实践中的推荐做法是先建立默认拒绝基线,再逐条放行必要流量。下面是一个针对agent命名空间的默认全拒策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: agent
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
podSelector: {}表示选中命名空间内的所有Pod,policyTypes同时声明Ingress和Egress后,没有任何放行规则的这条策略就实现了双向默认拒绝。有了基线之后,Agent的日志上报、DNS解析、健康检查都需要显式放行,否则Agent会直接失联。这是很多团队第一次上NetworkPolicy时踩的坑:策略一提交,整个命名空间的服务全挂了。
接着补充一条放行DNS和指定出口的策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: agent-egress-allow
namespace: agent
spec:
podSelector:
matchLabels:
app: metrics-agent
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- to:
- ipBlock:
cidr: 10.0.20.0/24
ports:
- protocol: TCP
port: 443
这里放行了两类出口:一是kube-system命名空间的DNS(UDP 53),二是访问10.0.20.0/24网段的443端口,比如日志服务所在的子网。namespaceSelector配合K8s 1.21以后自动打上的kubernetes.io/metadata.name标签,可以精准锁定目标命名空间,比按CIDR圈DNS地址更可靠。
三、策略叠加规则与常见坑
NetworkPolicy的叠加语义是并集而非交集:多条策略选中同一个Pod时,只要任意一条允许了某个流量,该流量就是放行的。比如你先写了一条只允许443出口的策略,又写了一条测试用的允许全部出口的策略,那么实际效果就是全部放行。排查时可以用kubectl get networkpolicy -n agent列出所有命中的策略逐一检查。
第二个容易出错的点是ingress里的from规则组合。同一列表内的多个元素是或的关系,不同字段之间也是或的关系。如果你想表达“只有带特定标签的Pod才能访问”,podSelector必须写在from列表的单个元素里,而不能拆成多个元素,否则语义就变了。另外ipBlock支持except字段排除部分地址,比如放行整个网段但排除某个网关:
- from:
- ipBlock:
cidr: 172.16.0.0/16
except:
- 172.16.0.5/32
第三个坑是NetworkPolicy是面向连接的状态化控制,放行了Agent访问外部服务器的Egress,回程流量会自动放行,不需要再为响应包单独写Ingress规则。这一点和裸的iptables思路不同,不需要双向都配。
四、Calico与Cilium的策略表达力差异
原生NetworkPolicy的能力是有限的:只能基于Pod标签、命名空间标签和CIDR,不能按域名(FQDN)过滤,也不能在传输层做更细的判断。如果Agent需要按域名限制出口,就得依赖CNI插件各自的扩展策略。
Calico提供了GlobalNetworkPolicy,支持按域名放行出口,例如:
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: agent-fqdn-egress
spec:
selector: app == 'metrics-agent'
egress:
- action: Allow
protocol: TCP
destination:
ports: [443]
domains:
- 'ops.ipipp.com'
Cilium则使用CiliumNetworkPolicy,除了FQDN外还能基于HTTP路径、L7协议做精细控制,比如只允许Agent调用某个API的特定路径。两者思路不同:Calico偏传统三层四层规则模型,运维容易上手;Cilium基于eBPF,可以做七层策略但依赖内核版本。选型时要结合团队对策略可读性和精细度的需求。
五、防火墙与NetworkPolicy的分工配合
NetworkPolicy解决的是集群内部的东西向流量和Pod与外部的连接控制,但集群边界的安全还是要靠传统防火墙或云安全组。一个合理的分工是:防火墙管南北向,控制哪些外部IP能到达集群的NodePort或LoadBalancer,以及集群能访问哪些外部网段;NetworkPolicy管东西向,控制Pod之间的访问关系。
具体到Agent场景,可以在防火墙上限制NodePort的来源IP白名单,只允许跳板机或监控平台所在网段访问Agent的暴露端口。同时建议按网络用途划分命名空间:采集类Agent放monitoring命名空间,安全类Agent放security命名空间,每个命名空间独立配置default deny和放行规则。这样即使某个Agent被攻破,影响范围也被限制在单个命名空间内。
最后强调可审计性:所有NetworkPolicy建议通过GitOps管理,纳入版本控制并定期用工具审计策略与实际流水的差异。网络隔离不是一次性配置,随着服务演进,放行规则会越积越多,定期回收冗余规则和用Hubble或Calico的流量日志验证策略有效性,才能让这套体系长期保持可信。
NetworkPolicyKubernetes网络策略防火墙修改时间:2026-09-04 10:21:10