CNI是Container Network Interface的是一个标准的,通用的接口。现在容器平台:docker,kubernetes,mesos,容器网络解决方案:flannel,calico,weave。只要提供一个标准的接口,就能为同样满足该协议的所有容器平台提供网络功能,而CNI正是这样的一个标准接口协议。
CNI用于连接容器管理系统和网络插件。提供一个容器所在的network namespace,将network interface插入该network namespace中(比如veth的一端),并且在宿主机做一些必要的配置(例如将veth的另一端加入bridge中),最后对namespace中的interface进行IP和路由的配置。
CNI的工作是从容器管理系统处获取运行时信息,包括network namespace的路径,容器ID以及network interface name,再从容器网络的配置文件中加载网络配置信息,再将这些信息传递给对应的插件,由插件进行具体的网络配置工作,并将配置的结果再返回到容器管理系统中。
CNI插件是可执行文件,会被kubelet调用。启动kubelet --network-plugin=cni,--cni-conf-dir 指定networkconfig配置,默认路径是:/etc/cni/net.d,并且,--cni-bin-dir 指定plugin可执行文件路径,默认路径是:/opt/cni/bin;
CNI plugin 只需要通过 CNI 库实现两类方法, 一类事创建容器时调用, 一类是删除容器时调用.
官方提供了三种类型的插件:main,meta和ipam:
git clone https://github.com/containernetworking/plugins.git
./build.sh
工作目录/etc/cni/net.d默认的网络配置文件目录,从中加载配置文件进行容器网络的创建
# cat >/etc/cni/net.d/10-mynet.conflist </etc/cni/net.d/99-loopback.conf <
cnitool是一个模拟程序,创建一个ns的network namespace,模拟一个新创建的容器,再调用cnitool对该network namespace进行网络配置,从而模拟一个新建的容器加入一个容器网络的过程
git clone https://github.com/containernetworking/cni.git
./build.sh
export CNI_PATH=$GOPATH/src/github.com/containernetworking/plugins/bin
ip netns add ns
# ./cnitool add mynet /var/run/netns/ns
{
"cniVersion": "0.3.0",
"interfaces": [
{
"name": "cni0",
"mac": "f2:62:59:82:c0:b7"
},
{
"name": "veth3ad23ebb",
"mac": "ba:d8:65:00:23:92"
},
{
"name": "eth0",
"mac": "fa:c8:0f:b8:83:3f",
"sandbox": "/var/run/netns/ns"
}
],
"ips": [
{
"version": "4",
"interface": 2,
"address": "10.22.0.2/16",
"gateway": "10.22.0.1"
}
],
"routes": [
{
"dst": "0.0.0.0/0"
}
],
"dns": {}
}
cnitool的执行结果,返回一个包含了interface,IP,路由等等各种信息的
# ip netns exec ns ifconfig
eth0: flags=4163 mtu 1500
inet 10.22.0.2 netmask 255.255.0.0 broadcast 0.0.0.0
ether fa:c8:0f:b8:83:3f txqueuelen 0 (Ethernet)
RX packets 2 bytes 84 (84.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1 bytes 42 (42.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
(1)、kubelet启动时,调用InitNetworkPlugin初始化网络插件
plug, err := network.InitNetworkPlugin(kubeDeps.NetworkPlugins, crOptions.NetworkPluginName, &criNetworkHost{&networkHost{klet}, &network.NoopPortMappingGetter{}}, hairpinMode, nonMasqueradeCIDR, int(crOptions.NetworkPluginMTU))
if err != nil {
return nil, err
}
https://github.com/keontang/k8s-notes/blob/master/kubernetes-network.md
https://github.com/containernetworking/plugins
https://github.com/containernetworking/cni