Container Networking Interface(CNI)提供了一种linux的应用容器的插件化网络解决方案。最初是由rkt Networking Proposal发展而来。他的模型只涉及两个概念:
容器(container) : 容器是拥有独立linux网络命名空间的独立单元。比如rkt/docker创建出来的容器。
网络(network): 网络指代了可以相互联系的一组实体。这些实体拥有各自独立唯一的ip。这些实体可以是容器,是物理机,或者其他网络设备(比如路由器)等。
Github地址:
这个地址包括两个项目,一个是CNI项目,一个是plugin项目,plugin主要用来适配CNI项目。
plugin项目主要包括以下插件:
以常见的bridge插件开始分析
插件路径:
函数入口:
skel.PluginMain函数由"github.com/containernetworking/cni/pkg/skel"包导入,这个包属于CNI项目,代码路径:
进入skel.go文件,查看PluginMain函数:
PluginMain函数把传入的变量再传入PluginMainWithError函数,PluginMainWithError函数再调用dispatcher变量的pluginMain方法,pluginMain方法定义如下:
pluginMain方法首先根据环境变量获取当前请求的动作是ADD或者DEL还是CHECK,然后进入对应的分支,接着使用checkVersionAndCall方法检查传入的版本号然后调用传入的参数,这里被调用的函数就是插件本身传入的函数,如bridge.go文件里面定义的“cmdAdd, cmdGet, cmdDel”这些函数,过程如下:
最终使用toCall调用到了bridge.go文件对应的函数。
bridge插件的cmdAdd方法用于添加一个容器到指定的网桥,核心过程是首先在宿主机创建网桥然后在容器内部通过系统调用创建VETH接口对,然后把属于host的接口设备为host命名空间,最后再配置容器接口IP地址:
1、加载输入参数
2、创建网桥
3、获取容器命名空间
4、创建VETH接口对
5、使用ipam获取IP地址并计算网关地址
6、配置容器IP地址
7、网关地址设置为网桥IP