NetworkPolicy 工作原理详解
NetworkPolicy 工作原理详解
NetworkPolicy 是 Kubernetes 中用于控制 Pod 间网络流量的核心资源对象,它通过定义规则来允许或拒绝 Pod 之间、Pod 与外部服务之间的网络通信。其本质是为 Kubernetes 集群提供网络微分段(Micro-segmentation) 能力,确保只有授权的流量才能在 Pod 间流动,是实现集群网络安全的关键组件。
一、NetworkPolicy 的核心定位与依赖前提
在理解工作原理前,需先明确其 “角色” 和 “运行条件”:
1. 核心定位
NetworkPolicy 本身不直接实现流量控制,而是一个 “规则定义层”—— 它仅声明 “哪些流量允许 / 拒绝”,真正执行流量过滤的是支持 NetworkPolicy 的网络插件(CNI)。
2. 依赖前提:CNI 插件支持
并非所有 Kubernetes 网络插件都支持 NetworkPolicy,只有实现了 Kubernetes NetworkPolicy API
的插件才能生效。常见支持的插件包括:
- Calico(应用最广泛,支持丰富的策略规则)
- Flannel(需配合
flannel-vxlan+policy
或第三方组件才支持) - Cilium(基于 eBPF,性能优异,支持 L3/L4/L7 层策略)
- Weave Net(原生支持 NetworkPolicy)
如果使用不支持的插件(如原生 Flannel),创建的 NetworkPolicy 会处于 “空转” 状态,无法对流量产生任何影响。
二、NetworkPolicy 的核心概念与规则模型
NetworkPolicy 通过 “选择目标 Pod” 和 “定义流量规则” 两个核心步骤工作,先明确控制对象,再限定流量范围。
1. 核心概念:目标 Pod 选择(Pod Selector)
NetworkPolicy 首先需要通过 podSelector
字段指定要控制的 Pod—— 只有匹配该选择器的 Pod,才会应用此策略的流量规则。
示例:通过
labels
匹配 Pod(标签为app: nginx
的所有 Pod)apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata:name: nginx-policy spec:podSelector: # 选择目标 PodmatchLabels:app: nginxpolicyTypes: # 策略类型:Ingress(入站)、Egress(出站)- Ingress- Egress# ... 后续规则省略
特殊情况:若
podSelector
为空(podSelector: {}
),则策略会应用于同一 Namespace 下的所有 Pod。
2. 核心概念:策略类型(Policy Types)
NetworkPolicy 支持两种流量方向的控制,通过 policyTypes
声明:
- Ingress:控制 “进入目标 Pod 的流量”(即其他 Pod / 外部服务向目标 Pod 发送的请求)。
- Egress:控制 “从目标 Pod 发出的流量”(即目标 Pod 向其他 Pod / 外部服务发送的请求)。
注意:若未显式声明
policyTypes
,Kubernetes 会默认规则:
- 若策略中定义了
ingress
规则,则自动添加Ingress
类型;- 若策略中定义了
egress
规则,则自动添加Egress
类型。
3. 规则模型:“默认拒绝,显式允许”
NetworkPolicy 遵循最小权限原则,默认规则是 “拒绝所有未授权流量”:
- 若某 Namespace 下存在针对 Pod 的 Ingress 策略,默认拒绝所有入站流量,仅允许策略中显式声明的入站流量;
- 若存在 Egress 策略,默认拒绝所有出站流量,仅允许策略中显式声明的出站流量;
- 若某 Pod 未被任何 NetworkPolicy 匹配,则该 Pod 的流量不受限制(允许所有入站和出站)。
三、Ingress 规则:控制入站流量
Ingress 规则定义 “哪些来源的流量可以进入目标 Pod”,核心是通过 from
(流量来源)和 ports
(目标端口)组合限制。
1. Ingress 规则结构
spec:ingress:- from: # 允许的流量来源(可多个)- podSelector: # 来源1:集群内的其他 Pod(通过标签匹配)matchLabels:app: client- namespaceSelector: # 来源2:指定 Namespace 下的所有 PodmatchLabels:env: prod- ipBlock: # 来源3:外部 IP 段(支持 CIDR 格式)cidr: 192.168.0.0/16except: # 排除该段中的部分 IP- 192.168.1.0/24ports: # 允许访问的目标 Pod 端口(可多个)- protocol: TCP # 协议:TCP/UDP/SCTPport: 80 # 端口号(可写具体数字或容器端口名,如 "http")
2. 流量来源(from)的三种类型
from
字段用于定义 “允许哪些对象向目标 Pod 发送流量”,支持三种来源:
来源类型 | 作用 | 示例场景 |
---|---|---|
podSelector | 匹配同一 Namespace下的特定 Pod | 允许 “前端 Pod(app: frontend)” 访问 “后端 Pod(app: backend)” |
namespaceSelector | 匹配特定 Namespace下的所有 Pod | 允许 “测试环境 Namespace(env: test)” 的所有 Pod 访问 “生产环境的数据库 Pod” |
ipBlock | 匹配外部 IP 段(集群外的流量) | 允许公司办公网(10.0.0.0/8)访问集群内的 Nginx Pod |
组合使用:
podSelector
和namespaceSelector
可组合(逻辑 “与”),例如:yaml
from: - podSelector: {matchLabels: {app: client}}namespaceSelector: {matchLabels: {env: prod}}
含义:仅允许 “prod 命名空间下,标签为 app: client 的 Pod” 访问目标 Pod。
3. 目标端口(ports)
ports
字段定义 “允许访问目标 Pod 的哪些端口”,支持:
- 具体端口号:如
port: 80
; - 容器端口名:如
port: http
(需在 Pod 的containers.ports.name
中定义该名称); - 协议指定:默认 TCP,可显式指定
protocol: UDP
或SCTP
。
四、Egress 规则:控制出站流量
Egress 规则定义 “目标 Pod 可以向哪些目的地发送流量”,核心是通过 to
(流量目的地)和 ports
(目标端口)组合限制。
1. Egress 规则结构
spec:egress:- to: # 允许的流量目的地(可多个)- podSelector: # 目的地1:集群内的其他 PodmatchLabels:app: db- namespaceSelector: # 目的地2:指定 Namespace 下的所有 PodmatchLabels:env: prod- ipBlock: # 目的地3:外部 IP 段(如公网服务、数据库)cidr: 10.244.0.0/16ports: # 允许访问的目的地端口(可多个)- protocol: TCPport: 5432 # 例如:允许目标 Pod 访问数据库的 5432 端口(PostgreSQL)
2. 流量目的地(to)的三种类型
to
字段与 Ingress 的 from
逻辑完全对称,支持三种目的地:
podSelector
:同一 Namespace 下的特定 Pod;namespaceSelector
:特定 Namespace 下的所有 Pod;ipBlock
:外部 IP 段(如集群外的数据库、API 服务)。
3. 常见场景:限制 Pod 访问外部服务
例如,限制 “应用 Pod” 仅能访问 “公网的支付 API(IP: 203.0.113.0/24,端口 443)”,则 Egress 规则如下:
egress:
- to:- ipBlock:cidr: 203.0.113.0/24ports:- protocol: TCPport: 443
五、NetworkPolicy 的执行逻辑与优先级
当多个 NetworkPolicy 同时匹配一个 Pod 时,流量规则的执行需遵循 “叠加允许、无拒绝叠加” 的原则。
1. 规则叠加逻辑
- 允许规则叠加:多个 Ingress/Egress 策略中,只要有一个策略允许某类流量,该流量就会被允许(逻辑 “或”);
- 拒绝规则不叠加:NetworkPolicy 仅支持 “显式允许”,不支持 “显式拒绝”(没有
deny
字段)。若需实现 “拒绝特定流量”,需通过 “先允许所有,再排除特定” 的方式间接实现(例如:ipBlock.cidr: 0.0.0.0/0
允许所有 IP,再通过except
排除特定 IP 段)。
2. 优先级规则
Kubernetes 本身不直接支持 NetworkPolicy 的优先级声明(如 priority
字段),但部分 CNI 插件(如 Calico)扩展了优先级功能:
- 高优先级策略的规则会先于低优先级策略执行;
- 若高优先级策略拒绝某流量,低优先级策略的允许规则无法覆盖。
若使用原生 Kubernetes NetworkPolicy(无扩展),则所有匹配的策略规则平等叠加,允许规则 “取并集”。
六、NetworkPolicy 的底层执行流程(以 Calico 为例)
不同 CNI 插件的执行细节不同,但核心逻辑都是 “将 NetworkPolicy 规则转化为节点上的网络过滤规则”。以最常用的 Calico 为例,流程如下:
- 用户创建 NetworkPolicy:通过
kubectl apply
提交 NetworkPolicy YAML 到 Kubernetes API Server; - CNI 插件监听策略变化:Calico 的
calico-kube-controllers
组件持续监听 API Server 中的 NetworkPolicy 资源,实时获取策略更新; - 规则转化:Calico 将 NetworkPolicy 规则转化为 Linux iptables 规则(或 eBPF 程序,取决于 Calico 模式);
- 规则下发到节点:Calico 通过
calico-node
守护进程(每个节点上运行),将转化后的 iptables/eBPF 规则下发到目标 Pod 所在的节点; - 流量过滤执行:当流量到达节点时,节点的内核通过 iptables/eBPF 规则检查流量的 “源 / 目的 Pod、端口、协议”,符合规则则放行,否则拒绝。
关键细节:为何基于节点执行规则?
Kubernetes Pod 的网络是 “Overlay 网络”(如 Calico 的 BGP 模式、Flannel 的 VXLAN 模式),Pod 的 IP 是虚拟 IP,流量最终需通过节点的物理网卡转发。因此,在节点上通过 iptables/eBPF 拦截流量,是最高效的执行方式。
七、常见误区与注意事项
- Namespace 隔离性:NetworkPolicy 是 ** Namespace 级别的资源 **,仅对同一 Namespace 下的 Pod 生效。若需跨 Namespace 控制,需通过
namespaceSelector
匹配目标 Namespace。 - 不影响 HostNetwork Pod:使用
hostNetwork: true
的 Pod(直接使用节点网络)不受 NetworkPolicy 控制,因为其流量不经过集群的 Overlay 网络,无法被 CNI 插件拦截。 - 不控制 Kubernetes 系统组件流量:默认情况下,kube-proxy、etcd、kube-apiserver 等系统组件的流量不受 NetworkPolicy 限制(需手动配置策略控制)。
- L7 层策略支持有限:原生 NetworkPolicy 仅支持 L3(IP)和 L4(端口、协议)层的控制;若需 L7 层(HTTP 路径、域名、请求头)的策略(如 “仅允许访问
/api/v1
路径”),需使用 Cilium(基于 eBPF)或 Istio(服务网格)等扩展方案。
八、总结
NetworkPolicy 的工作原理可归纳为三句话:
- 通过
podSelector
锁定目标 Pod,明确要控制的对象; - 通过 Ingress/Egress 规则定义 “允许的流量方向、来源 / 目的地、端口”,遵循 “默认拒绝,显式允许”;
- 依赖 CNI 插件将规则转化为节点的网络过滤规则(如 iptables),在流量转发时执行过滤。
它是 Kubernetes 集群网络安全的基石,通过精细化的流量控制,可有效防范 “横向渗透攻击”(如某 Pod 被入侵后,限制其访问其他核心 Pod),是生产环境中不可或缺的配置。