4. 容器网络模型:CNI规范、Pod网络命名空间、veth pair与容器连通性
在深入Cilium缓存命中故障排查之前,必须透彻理解容器网络的基础模型。Cilium作为CNI插件运行,其eBPF程序挂载点、缓存查找路径以及数据包转发逻辑,都直接依赖于Pod网络命名空间、veth pair以及CNI规范的交互方式。本节将拆解这三个核心概念,并展示它们如何协同工作以实现容器连通性。
4.1 CNI规范:容器网络的标准化接口
容器网络接口(Container Network Interface, CNI)是Kubernetes与网络插件之间的契约。它定义了一组标准操作(ADD、DEL、CHECK等)和参数传递格式,使得任何符合CNI规范的插件(如Cilium、Calico、Flannel)都能被Kubernetes kubelet调用。
| CNI操作 | 触发时机 | 核心职责 |
|---|---|---|
| ADD | Pod创建时 | 创建网络命名空间、分配IP、配置接口与路由 |
| DEL | Pod删除时 | 清理网络资源、释放IP、删除接口 |
| CHECK | 周期性健康检查 | 验证Pod网络配置是否仍然有效 |
| VERSION | 插件初始化时 | 返回插件支持的CNI规范版本 |
CNI规范的核心设计原则是可组合性。一个CNI配置可以包含多个插件(通过插件链实现),例如:先由cilium-cni执行主网络配置,再由portmap插件处理主机端口映射。Cilium作为CNI插件,在ADD操作中会完成以下关键步骤:
- 接收kubelet传递的Pod名称、命名空间、容器ID等信息。
- 创建或获取Pod的网络命名空间(netns)。
- 创建veth pair,将一端放入Pod netns,另一端留在主机网络栈。
- 为Pod netns内的veth端分配IP地址(通常来自Cilium IPAM)。
- 在主机端配置路由规则,将Pod IP的流量导向veth主机端。
- 通过eBPF程序(如
cilium_net)附加到主机端veth,实现策略执行和转发。
cilium endpoint list 确认Pod的endpoint状态是否为 ready。若状态为 not-ready 或 disconnected,通常意味着CNI配置阶段出现了问题,例如IP分配失败或veth pair创建异常。
4.2 Pod网络命名空间:隔离与独立的网络栈
每个Pod在Kubernetes中拥有独立的网络命名空间(Network Namespace)。这意味着Pod拥有自己的:
- 网络接口:包括lo回环接口和veth pair的Pod端。
- 路由表:决定数据包如何从Pod内部发出。
- ARP表:用于解析同一二层网络内的MAC地址。
- iptables/nftables规则:Pod内部的网络过滤规则(通常为空)。
- 套接字(socket):所有网络连接都绑定在Pod的netns内。
这种隔离机制确保了Pod A的网络故障不会直接影响Pod B,同时也为Cilium的eBPF程序提供了清晰的边界。Cilium在主机网络命名空间中运行其代理(cilium-agent),并通过eBPF程序在主机端veth接口上捕获进出Pod的所有流量。
nsenter 命令可以进入Pod的网络命名空间进行调试。例如:nsenter -t <container-pid> -n ip addr 可以查看Pod内部的IP地址配置。这在排查Pod内部路由或ARP问题时非常有效。
4.3 veth pair:连接Pod与主机的虚拟网线
veth(Virtual Ethernet)pair是一对虚拟网络接口,它们像一根网线的两端:数据包从一端进入,会立即从另一端出来。在容器网络模型中,veth pair扮演着连接Pod网络命名空间与主机网络命名空间的桥梁角色。
典型的veth pair配置如下:
# 主机端接口(通常命名为 lxcXXXX 或 eth0 在主机netns中)
# Pod端接口(通常命名为 eth0 在Pod netns中)
# 查看主机端veth接口
ip link show type veth
# 查看Pod端veth接口(需进入Pod netns)
nsenter -t <container-pid> -n ip link show eth0
veth pair的关键特性:
- 对称性:两端接口完全对称,没有主从关系。
- 数据包透传:所有从一端发送的L2帧都会直接出现在另一端。
- 无内置过滤:veth本身不执行任何网络策略,所有策略由附加的eBPF程序或iptables规则实现。
- MTU一致性:两端MTU必须一致,否则可能导致分片或丢包。
4.4 容器连通性:从Pod内部到外部的数据流
理解数据包从Pod内部出发,经过veth pair、主机网络栈,最终到达目标的过程,是排查Cilium缓存命中的基础。下图展示了这一完整的数据流路径:
数据流的关键步骤:
- Pod内部发送:Pod中的应用通过socket发送数据包,目标IP为10.96.0.1。
- 路由决策:Pod netns内的路由表查找,匹配默认网关10.0.1.1,数据包从eth0发出。
- veth传输:数据包从Pod端eth0进入veth pair,立即出现在主机端lxcXXXX接口。
- eBPF程序处理:Cilium在主机端veth接口上附加了tc或XDP eBPF程序。程序执行缓存查找(如CT map、LB map),决定是转发、丢弃还是执行NAT。
- 主机网络栈:如果eBPF程序允许转发,数据包进入主机网络栈,进行路由查找和iptables处理。
- 物理出口:最终数据包通过物理网卡eth0发送到外部网络或目标Pod所在节点。
4.5 Cilium视角:eBPF程序与veth的绑定关系
Cilium通过eBPF程序直接附加到主机端的veth接口上,这是实现高性能网络策略和负载均衡的关键。下图展示了Cilium eBPF程序与veth pair的绑定关系:
在Cilium中,eBPF程序通过tc(traffic control)或XDP(eXpress Data Path)附加到veth主机端接口。当数据包从Pod端通过veth到达主机端时,eBPF程序会:
- 查找连接跟踪缓存(CT map):判断数据包是否属于已有连接。如果命中,直接应用缓存的转发决策。
- 查找负载均衡缓存(LB map):如果数据包目标是Service IP,查找后端Pod的真实IP。
- 执行策略检查:根据CiliumNetworkPolicy规则,决定允许或拒绝数据包。
1.
cilium bpf ct list 查看连接跟踪表是否包含预期的连接。2.
cilium bpf lb list 查看负载均衡表是否包含目标Service的后端映射。3. 确认veth接口的eBPF程序是否正确加载:
tc filter show dev lxcXXXX ingress。
4.6 总结:容器网络模型对Cilium缓存的影响
容器网络模型中的每个组件都可能影响Cilium的缓存命中率:
| 组件 | 对缓存命中的潜在影响 | 排查方向 |
|---|---|---|
| CNI规范 | CNI ADD操作未正确配置IP或路由,导致eBPF程序无法关联endpoint | 检查 cilium endpoint list 状态 |
| Pod网络命名空间 | Pod netns内路由错误,导致数据包从错误接口发出,绕过eBPF程序 | 使用 nsenter 检查Pod内部路由表 |
| veth pair | MTU不匹配导致分片,eBPF程序无法正确解析L4头部 | 检查veth MTU与主机网卡MTU是否一致 |
| eBPF程序绑定 | eBPF程序未正确附加到veth主机端,导致缓存查找不生效 | 使用 tc filter show 验证程序加载 |