1、为什么CNI

       CNI是Container Network Interface的是一个标准的,通用的接口。现在容器平台:docker,kubernetes,mesos,容器网络解决方案:flannel,calico,weave。只要提供一个标准的接口,就能为同样满足该协议的所有容器平台提供网络功能,而CNI正是这样的一个标准接口协议。

 

2、什么CNI

       CNI用于连接容器管理系统和网络插件。提供一个容器所在的network namespace,将network interface插入该network namespace中(比如veth的一端),并且在宿主机做一些必要的配置(例如将veth的另一端加入bridge中),最后对namespace中的interface进行IP和路由的配置。

      CNI的工作是从容器管理系统处获取运行时信息,包括network namespace的路径,容器ID以及network interface name,再从容器网络的配置文件中加载网络配置信息,再将这些信息传递给对应的插件,由插件进行具体的网络配置工作,并将配置的结果再返回到容器管理系统中。

     

3、怎么CNI

     CNI插件是可执行文件,会被kubelet调用。启动kubelet --network-plugin=cni,--cni-conf-dir 指定networkconfig配置,默认路径是:/etc/cni/net.d,并且,--cni-bin-dir 指定plugin可执行文件路径,默认路径是:/opt/cni/bin;

         CNI plugin 只需要通过 CNI 库实现两类方法, 一类事创建容器时调用, 一类是删除容器时调用.

cni plugin

(1)、编译安装CNI

        官方提供了三种类型的插件:main,meta和ipam:

  •  main插件:提供某种网络功能,比如使用的brdige,以及loopback,ipvlan,macvlan等等
  •  meta插件:不能作为独立的插件使用,需要调用其他插件,例如flannel,或者配合其他插件使用,例如portmap
  •  ipam插件:对所有CNI插件共有的IP管理部分的抽象,从而减少插件编写过程中的重复工作,官方提供的有dhcp和host-local两种类型

 
 
  1. git clone https: //github.com/containernetworking/plugins.git
  2. ./build.sh

(2)、创建配置文件

       工作目录/etc/cni/net.d默认的网络配置文件目录,从中加载配置文件进行容器网络的创建


 
 
  1. # cat >/etc/cni/net.d/ 10-mynet.conflist <<EOF
  2. {
  3. "cniVersion": "0.3.0",
  4. "name": "mynet",
  5. "plugins": [
  6. {
  7. "type": "bridge",
  8. "bridge": "cni0",
  9. "isGateway": true,
  10. "ipMasq": true,
  11. "ipam": {
  12. "type": "host-local",
  13. "subnet": "10.22.0.0/16",
  14. "routes": [
  15. { "dst": "0.0.0.0/0" }
  16. ]
  17. }
  18. }
  19. ]
  20. }
  21. EOF
  22. # cat >/etc/cni/net.d/ 99-loopback.conf <<EOF
  23. {
  24. "cniVersion": "0.3.0",
  25. "type": "loopback"
  26. }
  27. EOF
  • cniVersion(string):指定了插件使用的CNI版本
  • name (string):Network name。这应该在整个管理域中都是唯一的
  • type (string):插件类型,也代表了CNI插件可执行文件的文件名
  • args (dictionary):由容器运行时提供的可选的参数。比如,可以将一个由label组成的dictionary传递给CNI插件,通过在args下增加一个labels字段来实现
  • ipMasqs (boolean):可选项(如果插件支持的话)。为network在宿主机创建IP masquerade。如果需要将宿主机作为网关,为了能够路由到容器分配的IP,这个字段是必须的
  • ipam:由特定的IPAM值组成的dictionary
    • type (string):IPAM插件的类型,也表示IPAM插件的可执行文件的文件名
  • dns:由特定的DNS值组成的dictionary
    • nameservers (list of strings):一系列对network可见的,以优先级顺序排列的DNS nameserver列表。列表中的每一项都包含了一个IPv4或者一个IPv6地址
    • domain (string):用于查找short hostname的本地域
    • search (list of strings):以优先级顺序排列的用于查找short domain的查找域。对于大多数resolver,它的优先级比domain更高
    • options(list of strings):一系列可以被传输给resolver的可选项

(3)、模拟CNI的执行过程,创建network namespace

       cnitool是一个模拟程序,创建一个ns的network namespace,模拟一个新创建的容器,再调用cnitool对该network namespace进行网络配置,从而模拟一个新建的容器加入一个容器网络的过程


 
 
  1. git clone https: //github.com/containernetworking/cni.git
  2. ./build.sh

 


 
 
  1. export CNI_PATH=$GOPATH/src/github.com/containernetworking/plugins/bin
  2. ip netns add ns
  3. # ./cnitool add mynet / var/run/netns/ns
  4. {
  5. "cniVersion": "0.3.0",
  6. "interfaces": [
  7. {
  8. "name": "cni0",
  9. "mac": "f2:62:59:82:c0:b7"
  10. },
  11. {
  12. "name": "veth3ad23ebb",
  13. "mac": "ba:d8:65:00:23:92"
  14. },
  15. {
  16. "name": "eth0",
  17. "mac": "fa:c8:0f:b8:83:3f",
  18. "sandbox": "/var/run/netns/ns"
  19. }
  20. ],
  21. "ips": [
  22. {
  23. "version": "4",
  24. "interface": 2,
  25. "address": "10.22.0.2/16",
  26. "gateway": "10.22.0.1"
  27. }
  28. ],
  29. "routes": [
  30. {
  31. "dst": "0.0.0.0/0"
  32. }
  33. ],
  34. "dns": {}
  35. }

      cnitool的执行结果,返回一个包含了interface,IP,路由等等各种信息的


 
 
  1. # ip netns exec ns ifconfig
  2. eth0: flags= 4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  3. inet 10.22 .0 .2 netmask 255.255 .0 .0 broadcast 0.0 .0 .0
  4. ether fa:c8: 0f:b8: 83: 3f txqueuelen 0 (Ethernet)
  5. RX packets 2 bytes 84 ( 84.0 B)
  6. RX errors 0 dropped 0 overruns 0 frame 0
  7. TX packets 1 bytes 42 ( 42.0 B)
  8. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

 

4、源码分析

      (1)、kubelet启动时,调用InitNetworkPlugin初始化网络插件


 
 
  1. plug, err := network.InitNetworkPlugin(kubeDeps.NetworkPlugins, crOptions.NetworkPluginName, &criNetworkHost{&networkHost{klet}, &network.NoopPortMappingGetter{}}, hairpinMode, nonMasqueradeCIDR, int(crOptions.NetworkPluginMTU))
  2. if err != nil {
  3. return nil, err
  4. }

 

 

参考:

https://github.com/keontang/k8s-notes/blob/master/kubernetes-network.md

https://github.com/containernetworking/plugins

https://github.com/containernetworking/cni

原文地址

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐