一 CNI的核心作用
CNI(Container Network Interface)是一个标准化的容器网络接口规范,
其核心作用包括:
1.1 为Pod分配IP地址:根据集群网络规划(如Calico的BGP路由、Flannel的vxlan隧道等)为Pod动态分配唯一IP。
1.2 配置网络连接:创建虚拟网络设备(如veth pair)、设置路由规则、配置防火墙策略(如NetworkPolicy)。
1.3 实现跨节点通信:通过隧道(如vxlan)、路由(如BGP)或三层网络(如Underlay)打通不同节点上Pod的网络
二 K8S创建POD时,CNI插件的网络配置过程
前提: 每个节点都已经配置好CNI插件 : Calico / Flannel / Weave / Net 等
这些插件安装完成后自动在Node节点上生成CNI的配置文件 /etc/cni/net.d/下
用户通过`kubectl apply`提交Pod清单后,
第一个创建的一定是 Infra 容器。所以在这一步,dockershim 就会先调用 Docker API (本文第三部分)创建并启动 Infra 容器,紧接着执行一个叫作SetUpPod 的方法。这个方法的作用就是:为 CNI 插件准备参数,然后调用 CNI 插件为Infra 容器配置网络
(1)K8S API Server将Pod信息存储到etcd
(2)Scheduler 为pod选址
(3)kubelet 发送创建请求到CRI
(4)CRI 调用 CNI
CRI读取`/etc/cni/net.d/`目录下的配置文件,解析插件类型(如`calico`、`flannel`)和参数
构造CNI请求参数:参数包括Pod名称、命名空间、网络命名空间路径(如`/var/run/netns/cni-xxx`)、容器ID
(5)CNI插件(依据/etc/cni/net.d)完成IP分配 + 设备创建 + 路由设置
(5.1)CNI插件通过IPAM(IP Address Management)模块分配IP
常见的IPAM插件包括`host-local`(本地IP池)、`dhcp`(动态主机配置协议)
host-local:从预定义的IP池(如`10.244.0.0/16`)中分配IP,并在本地文件(如`/var/lib/cni/networks/`)记录IP使用状态,避免冲突
(5.2)创建虚拟网络设备CNI插件为Pod创建虚拟网络设备,实现Pod与宿主机/其他Pod的网络连接
注意: flannel 和 Calico的网络设备连接情况不同
(5.2.1)在flannel项目中,CNI插件生成的veth pair设备一端连接容器的eth0,另一端连接宿主机的cni0网卡。cni0网卡是flannel创建的一个虚拟网络设备,用于在宿主机上模拟一个网络接口,以便容器可以通过这个接口与宿主机通信。cni0网卡的命名通常是固定的,因为它代表的是flannel创建的网络接口
(5.2.2)在Calico项目中,CNI插件生成的veth pair设备一端连接容器的eth0,另一端连接宿主机的以cali开头的虚拟网卡。这是因为Calico在宿主机上创建的虚拟网络设备通常以cali开头,如cali5863f3。这样的命名方式有助于区分不同容器的网络接口,因为每个容器的网络接口都会有一个唯一的名称。
总结: flannel通常使用一个固定的网络接口(如cni0)来连接所有容器
Calico则为每个容器创建一个唯一的虚拟网络设备,以提供更细粒度的网络控制和安全性
(5.3)CNI插件需配置Pod内、宿主机及集群级别的网络规则:
Pod内路由:设置Pod的默认网关(通常为宿主机端veth所在网段的网关,如`10.244.1.1`)
宿主机路由:添加宿主机到Pod的路由(如`10.244.1.5/32 via 10.244.1.0 dev cni0`)
跨节点路由:通过插件特定机制实现,例如:
Flannel:使用vxlan隧道封装跨节点数据包,宿主机通过`flannel.1`接口进行隧道转发。
Calico:通过BGP协议在节点间交换路由表,直接路由Pod流量。
(5.4)若集群启用NetworkPolicy
CNI插件(如Calico、Cilium)会根据策略规则配置iptables或eBPF规则,限制Pod间的通信
(6)容器网络namespace挂载: veth pair 的一端挂载到pod的 Network NameSpace中
(6.1)将 vethb4963f3 设备连接在 CNI 网桥之后,CNI bridge 插件还会为它设置Hairpin
Mode(发夹模式):在默认情况下,网桥设备是不允许一个数据包从一个端口进来后,再从这个端口发出去的。但是,它允许你为这个端口开启 Hairpin Mode,从而取消这个限制。
所以:Flannel 插件要在 CNI 配置文件里声明 hairpinMode=true。这样,将来这个集群里的 Pod 才可以通过它自己的 Service 访问到自己
(7)CNI插件完成网络配置,将POD的ip 网关等返回给CRI
CRI再将信息传递给Kubelet。Kubelet将IP信息记录到Pod的状态中,完成网络配置

三 dockershim 调用 Docker API
dockershim 分为两部分变量
(1)CNI_COMMAND : 取值 ADD / DEL
ADD 操作的含义是:把容器添加到 CNI 网络里
DEL 操作的含义则是:把容器从CNI 网络里移除掉
(2)dockershim读取CNI插件配置文件的信息
dockershim将配置信息以json格式,输入到CNI插件