【kubernetes/k8s概念】CNI详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhonglinzhang/article/details/82697524

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两种类型
git clone https://github.com/containernetworking/plugins.git
./build.sh

(2)、创建配置文件

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

# cat >/etc/cni/net.d/10-mynet.conflist <<EOF
{
        "cniVersion": "0.3.0",
        "name": "mynet",
        "plugins": [
          {
                "type": "bridge",
                "bridge": "cni0",
                "isGateway": true,
                "ipMasq": true,
                "ipam": {
                        "type": "host-local",
                        "subnet": "10.22.0.0/16",
                        "routes": [
                                { "dst": "0.0.0.0/0" }
                        ]
                }
          }
        ]
}
EOF


# cat >/etc/cni/net.d/99-loopback.conf <<EOF
{
    "cniVersion": "0.3.0",
    "type": "loopback"
}
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进行网络配置,从而模拟一个新建的容器加入一个容器网络的过程

扫描二维码关注公众号,回复: 3544147 查看本文章
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<UP,BROADCAST,RUNNING,MULTICAST>  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

4、源码分析

      (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

猜你喜欢

转载自blog.csdn.net/zhonglinzhang/article/details/82697524