CNI 架构源码解析
kubelet cni 源码解析
1 | # kubelet 使用cni 参数设置 |
/opt/cni/bin 目录中插件
- bridge
- cnitool
- dhcp
- flannel
- host-local
- ipvlan
- loopback
- macvlan
- noop
- portmap
- ptp
- tuning
- vlan
cni 配置文件解析 10-flannel.conflist
1 | { |
1 | // kubernetes/pkg/kubelet/dockershim/network/cni/cni.go |
containernetworking/cni 源码解析
1 | // github.com/containernetworking/cni/libcni/api.go |
1 | { |
1 | // AddNetworkList executes a sequence of plugins with the ADD command |
- AddNetworkList 从上至下调用10-flannel.conflist 中plugins 中type 字段的命令
- AddNetworkList 调用 /opt/cni/bin/flannel 命令
- AddNetworkList 调用 /opt/cni/bin/portmap 命令
1 | // DelNetworkList executes a sequence of plugins with the DEL command |
- DelNetworkList 从下至上调用10-flannel.conflist 中plugins 中type 字段的命令
- DelNetworkList 调用 /opt/cni/bin/portmap 命令
- DelNetworkList 调用 /opt/cni/bin/flannel 命令
/opt/cni/bin/flannel 命令 源码解析
1 | // github.com/containernetworking/cni/plugins/plugins/meta/flannel/flannel.go |
- flannel 命令接受ADD, DEL, VERSION 命令行参数
- cni 插件接口只需实现ADD, DEL, VERSION 三方法即可
/opt/cni/bin/flanel 命令所支持配置文件字段如下:
1 | # /run/flannel/subnet.env 文件为flanneld 服务启动时候生成 |
1 | { |
add 命令源码解析
1 | // NetConf describes a network. |
代码解释
- 保存配置文件中的 delegate 字段信息到 /var/lib/cni/flannel/<容器id>
1 | cat 577ed940b4972515b0270636b82c8b0d8151043d93b0c14cf98edfd01ef0da8b | python -m json.tool |
- 调用 /opt/cni/bin/bridge 命令
1 | type NetConf struct { |
- 注意:hairpin mode 介绍http://chenchun.github.io/network/2017/10/09/hairpin
1 | func cmdAdd(args *skel.CmdArgs) error { |
ADD命令:
- 执行ADD命令时,brdige组件创建一个指定名字的网桥,如果网桥已经存在,就使用已有的网桥;
- 创建vethpair,将node端的veth设备连接到网桥上;
- 从ipam获取一个给容器使用的ip数据,并根据返回的数据计算出容器对应的网关;
- 进入容器网络名字空间,修改容器中网卡名和网卡ip,以及配置路由,并进行arp广播(注>- 意我们只为vethpair的容器端配置ip,node端是没有ip的);
- 如果IsGW=true,将网桥配置为网关,具体方法是:将第三步计算得到的网关IP配置到网桥上同时根据需要将网桥上其他ip删除。最后开启网桥的ip_forward内核参数;
- 如果IPMasq=true,使用iptables增加容器私有网网段到外部网段的masquerade规则,这样容器内部访问外部网络时会进行snat,在很多情况下配置了这条路由后容器内部才能访问外网。(这里代码中会做exist检查,防止生成重复的iptables规则);
- 配置结束,整理当前网桥的信息,并返回给调用者。
DEL命令:
- 根据命令执行的参数,确认要删除的容器ip,调用ipam的del命令,将IP还回IP pool;
- 进入容器的网络名字空间,根据容器IP将对应的网卡删除;
- 如果IPMasq=true,在node上删除创建网络时配置的几条iptables规则。
- 调用 /opt/cni/bin/host-local 命令
1 | type Range struct { |
1 | #配置文件范例: |
- host-local组件通过在配置文件中指定的subnet进行网络划分。
- host-local在本地通过指定目录(默认为/var/lib/cni/networks)记录当前的ip pool数据。
- host-local将IP分配并告知调用者时,还可以告知dns、路由等配置信息。这些信息通过配置文件和对应的resolv文件记录。
- 调用 /opt/cni/bin/portmap 命令
iptalbes 流量顺序执行图链接
1 | // NetConf describes a network. |
1 | portmap 配置参数设置 |
- 用于在node上配置iptables规则,进行SNAT,DNAT和端口转发。
- portmap组件通常在main组件执行完毕后执行,因为它的执行参数仰赖之前的组件提供。
- capabilities 中的 portMappings 参数设置true 则会开启ports 中信息增加DNAT, SNAT
根据pod 中ports 段 配置iptables 规则链
1 | spec: |
添加容器网络操作
1 | # 生成 CNI-HOSTPORT-DNAT 链路存在于NAT表中 |
添加容器网络操作
1 | 删除 CNI-SN-0c252d022e0443e29bc25, CNI-DN-d1d39c44eab8f1c7243ad 链表 |