2. Kubernetes网络模型与数据路径
要真正理解Kubernetes网络性能问题,必须先建立一张清晰的“数据包地图”:一个Pod发出的报文,究竟经过哪些内核对象、在哪一层被转发、由谁决定下一跳。Kubernetes本身并不实现网络转发,它只定义了一套网络模型约束,真正的转发能力来自Linux内核网络栈与CNI插件。本节沿着“Pod → Pod”的完整路径,逐层拆解网络命名空间、veth pair、网桥、路由与CNI插件的职责边界。
一、Kubernetes网络模型的三条基本约束
Kubernetes网络模型对Pod网络提出三条硬性要求:第一,任意Pod之间可以直接通信,无需NAT;第二,任意Node与任意Pod之间可以直接通信,无需NAT;第三,Pod看到的自身IP与其它Pod看到的该Pod IP完全一致,即不存在“内外地址不一致”的问题。这三条约束决定了CNI插件必须为每个Pod分配集群内唯一且可路由的IP,并保证跨节点转发路径上不做源地址转换。
需要强调的是,Kubernetes只规定“结果”,不规定“实现”。Flannel、Calico、Cilium、Antrea等插件可以用Overlay隧道、BGP路由、eBPF等完全不同的机制满足同一套约束,这也是不同集群网络性能差异巨大的根本原因。
二、Pod网络命名空间:隔离的起点
每个Pod在创建时,容器运行时(containerd或CRI-O)会调用CNI插件,为Pod创建一个独立的Linux网络命名空间(netns)。这个命名空间内至少包含:一个回环接口lo、一个以太网接口(通常命名为eth0)、一张独立的路由表、独立的ARP表和独立的连接跟踪表。Pod内容器的所有网络行为都发生在这个命名空间内,容器之间通过共享该命名空间实现“同Pod即同主机”的通信语义。
可以用下面的命令观察一个Pod的网络命名空间内部结构(示例参数,非实测结果):
# 在Pod所在节点上找到容器PID
crictl inspect <container-id> | grep pid
# 进入该Pod的网络命名空间
nsenter -t <pid> -n ip addr show
nsenter -t <pid> -n ip route show
nsenter -t <pid> -n ip neigh show
典型输出中,eth0会获得CNI分配的Pod IP(例如10.244.1.37/24),路由表中默认路由指向一个链路本地网关(例如10.244.1.1),而这个“网关”实际上并不存在于任何真实网卡上,它只是veth pair对端所在网桥的代理ARP响应。理解这一点,是理解后续转发路径的关键。
三、veth pair与网桥:把Pod接入节点网络
Pod的eth0并不是一块物理网卡,而是veth pair的一端。veth pair是一对虚拟以太网设备,从一端进入的报文会从另一端出来,类似一根“虚拟网线”。CNI插件把其中一端留在Pod netns内(命名为eth0),把另一端移入宿主机的根命名空间(通常命名为vethXXXXXX),并把它挂到节点上的一个Linux网桥(如cni0、docker0或Calico的caliXXXX)或直接交给路由/BPF程序处理。
当Pod A向Pod B发包时,报文先经过Pod A的eth0,穿过veth pair进入宿主机根命名空间,再进入网桥。网桥根据目的MAC地址决定从哪个端口转发出去。如果Pod B在同一节点,网桥直接把帧转发到Pod B对应的veth端口;如果Pod B在其它节点,网桥把帧交给宿主机路由子系统,由路由表决定下一跳。
四、路由与CNI插件:决定跨节点怎么走
跨节点转发时,宿主机路由表是核心。以Flannel host-gw模式为例,每个节点会为其它节点的Pod网段写入一条路由,例如:
10.244.2.0/24 via 192.168.1.22 dev eth0
这表示去往节点2上Pod网段的报文,直接以节点2的物理IP为下一跳,封装成普通以太帧发出,不做隧道封装,因此性能接近原生网络。而Flannel VXLAN模式则会创建flannel.1虚拟接口,把原始报文封装进UDP(默认端口8472)再发出,多了一层封装与解封装开销,MTU也会相应减小。
CNI插件的职责可以归纳为四件事:为Pod分配IP、创建并连接veth pair、配置Pod内路由与宿主机路由、在Pod删除时回收资源。它不负责Service转发(那是kube-proxy或eBPF的事),也不负责网络策略(除非插件自身实现)。
五、Pod到Pod完整数据路径
把上述环节串起来,一个跨节点Pod到Pod的报文路径如下:Pod A应用发出报文 → Pod A netns内eth0 → veth pair → 宿主机网桥 → 宿主机路由表查表 → 按CNI模式选择直接路由或隧道封装 → 物理网卡发出 → 对端节点物理网卡接收 → 解封装(如有)→ 对端宿主机路由 → 对端网桥 → 对端veth pair → Pod B netns内eth0 → Pod B应用。整条路径上,源IP和目的IP始终是Pod IP,不发生NAT。
六、从路径看性能与排障切入点
理解这条路径后,性能优化与排障就有了明确的着力点。第一,MTU:VXLAN封装会额外占用50字节,若物理网卡MTU为1500,则Pod内MTU通常需设为1450,否则大包会被分片或丢弃,表现为“小包通、大包不通”。第二,连接跟踪:kube-proxy的iptables模式会在宿主机上为每个连接维护conntrack表项,高并发下conntrack表满会导致新连接被丢弃。第三,网桥与veth的中断开销:每个报文都要经过多次内核态软中断处理,Pod密度越高,单节点转发压力越大。
排障时可按路径逐段验证:先在Pod内ping对端Pod IP,确认应用层可达;再用ip neigh检查ARP是否解析成功;然后在宿主机上ip route get 10.244.2.18确认路由命中;最后用tcpdump -i any -n host 10.244.2.18在两端节点抓包,观察报文是否真正离开源节点、是否到达目的节点。若源节点已发出但目的节点未收到,问题通常在物理网络或隧道配置;若目的节点收到但Pod未响应,问题多在目的端路由或网桥。
把Pod网络命名空间、veth pair、网桥、路由和CNI插件这五个对象的关系理清,后续无论是分析Service转发、NetworkPolicy生效点,还是定位丢包与延迟,都能沿着同一条数据路径快速缩小范围。