2. CNI基础回顾:CNI规范、常见CNI插件架构对比、CNI与kubelet交互流程

2.1 CNI规范核心要素

容器网络接口(Container Network Interface, CNI)是 Cloud Native Computing Foundation(CNCF)旗下的一个项目,由一组规范和库组成,用于配置 Linux 容器的网络接口。其核心设计原则是“插件化”和“最小化”,不关心容器运行时本身,只关注网络配置。

规范要素 说明 关键字段/行为
CNI 命令 插件必须实现的三个操作 ADD、DEL、CHECK(可选)
网络配置 JSON 格式描述网络参数 cniVersion、name、type、ipam、dns
运行时参数 通过环境变量传递 CNI_CONTAINERID、CNI_NETNS、CNI_IFNAME、CNI_ARGS、CNI_PATH
结果输出 标准输出打印 JSON cniVersion、interfaces、ips、routes、dns
IPAM 委托 IP 地址管理可独立为子插件 host-local、dhcp、static
关键约束:CNI 插件必须是可执行二进制文件,kubelet 通过 exec 方式调用,插件必须在 CNI_PATH 指定的目录中。插件执行超时通常为 30 秒,超时后 kubelet 会重试或标记 Pod 失败。

2.2 常见CNI插件架构对比

当前 Kubernetes 生态中最主流的三个 CNI 插件是 Calico、Flannel 和 Cilium。它们在数据平面、控制平面、网络策略支持和性能特征上存在显著差异。

维度 Calico Flannel Cilium
数据平面 Linux 内核路由 + iptables / eBPF VXLAN / host-gw / UDP 隧道 eBPF(内核态)
控制平面 BGP(Bird 或 Felix) etcd 或 Kubernetes API Kubernetes API + eBPF Map
网络策略 原生支持(NetworkPolicy) 不支持(需配合其他组件) 原生支持(增强版,支持 L7)
封装开销 无封装(纯路由)或 IPIP 封装 VXLAN 封装(约 50 字节) 无封装(直接路由)
性能特征 高吞吐,低延迟(纯路由模式) 中等吞吐,封装带来额外延迟 极高吞吐,极低延迟(eBPF 加速)
运维复杂度 中等(需管理 BGP 或 IPIP 配置) 低(配置简单,适合小规模) 高(需内核 >= 5.10,eBPF 调试复杂)
典型场景 大规模集群、混合云、需要精细策略 开发测试、小规模集群、快速部署 高性能场景、安全敏感、可观测性要求高
缓存命中率视角:Flannel 的 VXLAN 隧道模式在节点间通信时,数据包需要经过内核隧道处理,容易导致 conntrack 表项膨胀和缓存抖动。Calico 的纯路由模式依赖主机路由表,路由缓存命中率较高。Cilium 通过 eBPF 直接接管网络路径,绕过了传统 iptables 和路由缓存,在连接密集型场景下缓存命中率最优。

2.3 CNI与kubelet交互流程

kubelet 是 Kubernetes 节点上最核心的 agent,负责 Pod 生命周期管理。当 kubelet 需要为 Pod 创建网络时,会按照以下标准流程调用 CNI 插件:

  1. Sandbox 创建:kubelet 调用容器运行时(如 containerd)创建 Pod 的 network namespace(netns)。
  2. CNI 配置加载:kubelet 从 /etc/cni/net.d/ 目录读取 CNI 配置文件(通常为 10-calico.conflist 或 10-flannel.conflist)。
  3. 环境变量组装:kubelet 设置 CNI_CONTAINERID、CNI_NETNS(指向 netns 路径)、CNI_IFNAME(通常为 eth0)、CNI_ARGS(如 IgnoreUnknown=1)、CNI_PATH(插件二进制目录)。
  4. 执行 ADD 命令:kubelet 在 netns 中执行 CNI_COMMAND=ADD 的插件二进制,传递标准输入中的 JSON 配置。
  5. 插件处理:CNI 插件根据配置创建 veth pair、分配 IP(委托 IPAM)、设置路由、配置 iptables 或 eBPF 规则。
  6. 结果返回:插件将接口信息、IP 地址、路由和 DNS 配置以 JSON 格式打印到标准输出。
  7. Pod 网络就绪:kubelet 将结果写入 Pod 状态,容器运行时将 eth0 移动到 Pod 的 netns 中。
CNI 与 kubelet 交互流程(ADD 操作) kubelet 容器运行时 CNI 配置 CNI 插件 IPAM 子插件 Pod netns JSON 结果 1. 创建 Sandbox 2. 读取配置 3. 执行 ADD 命令 4. 分配 IP IP 地址返回 5. 配置 veth/路由 6. 输出结果 7. 返回结果给 kubelet,Pod 网络就绪
缓存命中率关键点:在步骤 5 中,CNI 插件配置网络时,会创建 conntrack 条目、路由缓存和邻居表项。如果插件在 ADD 或 DEL 操作中频繁刷新 iptables 规则或路由表,会导致内核缓存抖动,直接影响后续数据包的缓存命中率。Cilium 通过 eBPF 将网络策略和转发逻辑下沉到内核态,避免了传统 iptables 规则遍历带来的缓存污染。

2.4 CNI 插件执行环境与缓存影响

CNI 插件在 kubelet 的上下文中执行,其执行环境对缓存命中率有直接影响:

  • 进程隔离:每个 CNI 插件调用都是独立的进程,插件退出后其内存状态全部释放,无法跨调用共享缓存。
  • 内核状态依赖:插件配置的 iptables 规则、路由表、邻居表、conntrack 表都是内核全局状态,插件之间的操作可能相互覆盖或冲突。
  • 并发风险:kubelet 可能同时为多个 Pod 调用 CNI 插件,并发操作同一张内核表时,可能导致锁竞争和缓存失效。
  • IPAM 缓存:IPAM 子插件(如 host-local)会在本地文件系统维护 IP 分配记录,频繁读写文件会影响整体延迟,间接影响缓存一致性。