随着容器技术在企业生产系统中的逐步落地,用户对容器云的网络特性要求也越来越高。跨主机容器间的网络互通已经成为基本要求,更高的要求包括容器固定IP地址、一个容器多个IP地址、多个子网隔离、ACL控制策略、与SDN集成等。目前主流的容器网络模型主要有Docker公司提出的Container Network Model(CNM)模型和CoreOS公司提出的Container Network Interface(CNI)模型。

1.CNM模型

    CNM模型是由Docker公司提出的容器网络模型,现在已经被Cisco Contiv、Kuryr、Open Virtual Networking(OVN)、Project Calico、 VMware、Weave和Plumgrid等项目采纳。另外,Weave、Project Calico、Kuryr和Plumgrid等项目也为CNM提供了网络插件的具体实现。

    CNM模型主要通过Network Sandbox、Endpoint和Network这3个组件进行实现,

 

◎ Network Sandbox:容器内部的网络栈,包括网络接口、路由表、DNS等配置的管理。Sandbox可用Linux网络命名空间、FreeBSD Jail等机制进行实现。一个Sandbox可以包含多个Endpoint。
◎ Endpoint:用于将容器内的Sandbox与外部网络相连的网络接口。可以使用veth对、Open vSwitch的内部port等技术进行实现。一个Endpoint仅能够加入一个Network。
◎ Network:可以直接互连的Endpoint的集合。可以通过Linux网桥、VLAN等技术进行实现。一个Network包含多个Endpoint。

2.CNI模型

   CNI是由CoreOs公司公司提出的另一种容器网络规范,现在已经被Kubernetes、rkt、Apache Mesos、Cloud Foundry和Kurma等项目采纳。另外,Contiv Networking, Project Calico、Weave、SR-IOV、Cilium、Infoblox、Multus、Romana、Plumgrid和Midokura等项目也为CNI提供网络插件的具体实现。下图描述了容器运行环境与各种网络插件通过CNI进行连接的模型。

      CNI定义的是容器运行环境与网络插件之间的简单接口规范,通过一个JSON Schema定义CNI插件提供的输入和输出参数。一个容器可以通过绑定多个网络插件加入多个网络中。

CNI规范概述

        CNI提供了一种应用容器的插件化网络解决方案,定义对容器网络进行操作和配置的规范,通过插件的形式对CNI接口进行实现。CNI是由rkt Networking Proposal发展而来的,试图提供一种普适的容器网络解决方案。CNI仅关注在创建容器时分配网络资源,和在销毁容器时删除网络资源,这使得CNI规范非常轻巧、易于实现,得到了广泛的支持。

      在CNI模型中只涉及两个概念: 容器和网络。

◎ 容器(Container):是拥有独立Linux网络命名空间的环境,例如使用Docker或rkt创建的容器。关键之处是容器需要拥有自己的Linux网络命名空间,这是加入网络的必要条件。
◎ 网络(Network):表示可以互连的一组实体,这些实体拥有各自独立、唯一的IP地址,可以是容器、物理机或者其他网络设备(比如路由器)等。

      对容器网络的设置和操作都通过插件(Plugin)进行具体实现,CNI插件包括两种类型:CNI Plugin和IPAM(IP Address Management)Plugin。CNI Plugin负责为容器配置网络资源,IPAM Plugin负责对容器的IP地址进行分配和管理。IPAM Plugin作为CNI Plugin的一部分,与CNI Plugin一起工作。

CNI Plugin插件详解

    CNI Plugin包括3个基本接口的定义:添加(ADD)、删除(DELETE)、检查(CHECK)和版本查询(VERSION)。这些接口的具体实现要求插件提供一个可执行的程序,在容器网络添加或删除时进行调用,以完成具体的操作。

  (1)添加:将容器添加到某个网络。主要过程为在Container Runtime创建容器时,先创建好容器内的网络命名空间(Network Namespace),然后调用CNI插件为该netns进行网络配置,最后启动容器内的进程。

添加接口的参数如下:
◎ Version:CNI版本号。
◎ ContainerID: 容器ID。
◎ Network namespace path:容器的网络命名空间路径,例如/proc/[pid]/ns/net。
◎ Network configuration:网络配置JSON文档,用于描述容器待加入的网络。
◎ Extra arguments:其他参数,提供基于容器的CNI插件简单配置机制。
◎ Name of the interface inside the container:容器内的网卡名。

返回的信息如下。

◎ Interfaces list:网卡列表,根据Plugin的实现,可能包括Sandbox Interface名称、主机Interface名称、每个Interface的地址等信息。
◎ IPs assigned to the interface:IPv4或者IPv6地址、网关地址、路由信息等。
◎ DNS information:DNS相关的信息。

(2)删除:容器销毁时将容器从某个网络中删除。

删除接口的参数如下:

◎ Version:CNI版本号。
◎ ContainerID: 容器ID。
◎ Network namespace path:容器的网络命名空间路径,例如/proc/[pid]/ns/net。
◎ Network configuration:网络配置JSON文档,用于描述容器待加入的网络。
◎ Extra arguments:其他参数,提供基于容器的CNI插件简单配置机制。
◎ Name of the interface inside the container:容器内的网卡名。

(3)检查:检查容器网络是否正确设置。
检查接口的参数如下:

◎ ContainerID: 容器ID。
◎ Network namespace path:容器的网络命名空间路径,例如/proc/[pid]/ns/net。
◎ Network configuration:网络配置JSON文档,用于描述容器待加入的网络。
◎ Extra arguments:其他参数,提供基于容器的CNI插件简单配置机制。
◎ Name of the interface inside the container:容器内的网卡名。

(4)版本查询:查询网络插件支持的CNI规范版本号。
无参数,返回值为网络插件支持的CNI规范版本号。

      CNI插件应能够支持通过环境变量和标准输入传入参数。可执行文件通过网络配置参数中的type字段标识的文件名在环境变量CNI_PATH设定的路径下进行查找。一旦找到,容器运行时将调用该可执行程序,并传入以下环境变量和网络配置参数,供该插件完成容器网络资源和参数的设置。

环境变量参数如下:

◎ CNI_COMMAND:接口方法,包括ADD、DEL和VERSION。
◎ CNI_CONTAINERID:容器ID。
◎ CNI_NETNS:容器的网络命名空间路径,例如/proc/[pid]/ns/net。
◎ CNI_IFNAME:待设置的网络接口名称。
◎ CNI_ARGS:其他参数,为key=value格式,多个参数之间用分号分隔,例如"FOO=BAR; ABC=123"。
◎ CNI_PATH:可执行文件的查找路径,可以设置多个。

网络配置参数则由一个JSON报文组成,以标准输入(stdin)的方式传递给可执行程序。
网络配置参数如下:

◎ name(string): 网络名称,应在一个管理域内唯一。
◎ type(string):CNI插件的可执行文件的名称。
◎ args(dictionary):其他参数。
◎ ipMasq(boolean):是否设置IP Masquerade(需插件支持),适用于主机可作为网关的环境中。
◎ ipam:IP地址管理的相关配置。
- type(string):IPAM可执行的文件名。
◎ dns:DNS服务的相关配置。

nameservers(list of strings):名字服务器列表,可以使用IPv4或IPv6地址。
- domain(string):本地域名,用于短主机名查询。
- search(list of strings):按优先级排序的域名查询列表。
- options(list of strings):传递给resolver的选项列表。

下面的例子定义了一个名为dbnet的网络配置参数,IPAM使用host-local进行设置:

{
   "cniVersion": "0.4.0",
   "name": "dbnet",
   "type": "bridge",
   "bridge": "cni0",
   "ipam": {
    "type": "host-local",
    "subnet": "10.1.0.0/16",
    "gateway": "10.1.0.1"
    }, 
    "dns": {
       "nameservers": ["10.1.0.1"]
     }

}

3.IPAM Plugin插件详解

      为了减轻CNI Plugin对IP地址管理的负担,在CNI规范中设置了一个新的插件专门用于管理容器的IP地址(还包括网关、路由等信息),被称为IPAM Plugin。通常由CNI Plugin在运行时自动调用IPAM Plugin完成容器IP地址的分配。

     IPAM Plugin负责为容器分配IP地址、网关、路由和DNS,典型的实现包括host-local和dhcp。与CNI Plugin类似,IPAM插件也通过可执行程序完成IP地址分配的具体操作。IPAM可执行程序也处理传递给CNI插件的环境变量和标准输入(stdin)传入的网络配置参数。

     如果成功完成了容器IP地址的分配,则IPAM插件应该通过标准输出(stdout)返回以下JSON报文:

    

{
    "cniVersion": "0.4.0",
    "ips":[
          {

                   "version": "<4-or-6>",
                    "address": "<ip-and-prefix-in-CIDR>",
                    "gateway": "<ip-address-of-the-gateway>" (optional)
           },
           ..........
      ],
      "routes":[
       {
          "dst": "<ip-and-prefix-in-cidr>",
           "gw": "<ip-of-next-hop>"
        },
       ........
      ]

      "dns":{
       "nameservers": <list-of-nameservers> (optional)
       "domain": <name-of-local-domain>  (optional)
       "search": <list-of-options>  (optional)
     }
}

 

其中包括ips、routes和dns三段内容。

◎   ips段:分配给容器的IP地址(也可能包括网关)。
◎ routes段:路由规则记录。
◎ dns段:DNS相关的信息。

4.多网络插件

   在很多情况下,一个容器需要连接多个网络,CNI规范支持为一个容器运行多个CNI Plugin来实现这个目标。多个网络插件将按照网络配置列表中的顺序执行,并将前一个网络配置的执行结果传递给后面的网络配置。多网络配置用JSON报文进行配置,包括如下信息。

◎ cniVersion(string):CNI版本号。
◎ name(string):网络名称,应在一个管理域内唯一,将用于下面的所有Plugin。
◎ plugins(list):网络配置列表。

下面的例子定义了两个网络配置参数,分别作用于两个插件,第1个为bridge,第2个为tuning。CNI将首先执行第1个bridge插件设置容器的网络,然后执行第2个tuning插件:

{
  "cniVersion": "0.4.1",
  "name": "dbnet",
  "plugins": [
    {
      "type": "bridge",
      // type (plugin) specific
      "bridge": "cni0",
      // args may be ignored by plugins
      "args": {
        "labels": {
          "appVersion": "1.0"
        }
      },
      "ipam": {
        "type": "host-local",
        // ipam specific
        "subnet": "10.1.0.0/16",
        "gateway": "10.1.0.1"
      },
      "dns": {
        "nameserver": [ "10.1.0.1" ]
      }
    },
    {
      "type": "tuning",
      "sysctl": {
        "net.core.somaxconn": "500"
      }
    }
  ]
}

在容器运行且执行第1个bridge插件时,网络配置参数将被设置为:

{
  "cniVersion": "0.4.1",
  "name": "dbnet",
  "type": "bridge",
  "bridge": "cni0",
  "args": {
    "labels": {
      "appVersion": "1.0"
    }
  },
  "ipam": {
    "type": "host-local",
    "subnet": "10.1.0.0/16",
    "gateway": "10.1.0.1"
  },
  "dns": {
    "nameservers": [ "10.1.0.1" ]
  }
}

接下来执行第2个tuning插件,网络配置参数将被设置为:

{
  "cniVersion": "0.4.1",
  "name": "dbnet",
  "type": "tuning",
  "sysctl": {
    "net.core.somaxconn": "500"
  },
  "prevResult": {
    "ips": [
       {
         "version": "4",
         "address": "10.0.0.5/32"
         "interface": 2
       }   
    ] ,
    "interfaces": [
      {"name": "cni0","mac": :"xxxx",},
      {"name": "veth3243","nac":"xxxx",},
      {"name": "eth0","mac":"xxxx","sandbox":"/var/ryb/netns/blue",}
   ],
    "dbs":{
      "baneservers": ["10.1.0.1"]  
   }
    
  }
}

     其中,prevResult字段包含的信息为上一个bridge插件执行的结果。

     在删除多个CNI Plugin时,则以逆序执行删除操作,以上例为例,将先删除tuning插件的网络配置,其中prevResult字段包含的信息为新增操作(ADD)时补充的信息:

{
  "cniVersion": "0.4.0",
  "name": "dbnet",
  "type": "tuning",
  "sysctl": {
    "net.core.somaxconn": "500"
  },
  "prevResult":{
     "ips":[
     
        "version": "4",
        "address": "10.0.0.5/32"
        "interface": 2
 
     ],
    "interfaces": [
      {"name": "cni0","mac": :"xxxx",},
      {"name": "veth3243","nac":"xxxx",},
      {"name": "eth0","mac":"xxxx","sandbox":"/var/ryb/netns/blue",}
   ],
    "dbs":{
      "baneservers": ["10.1.0.1"]  
   }
   }
}

然后删除bridge插件的网络配置,其中prevResult字段包含的信息也是在新增操作(ADD)时补充的信息:

{
  "cniVersion": "0.4.1",
  "name": "dbnet",
  "type": "bridge",
  "vridge": "cni0"
      "agrs" :{

         "appVersion": "1.0"
      },
      "ipam": {
        "type": "host-local",
        // ipam specific
        "subnet": "10.1.0.0/16",
        "gateway": "10.1.0.1"
      },
      "dns": {
        "nameserver": [ "10.1.0.1" ]
      
       },
    "prevResult":{
     "ips":[
     
        "version": "4",
        "address": "10.0.0.5/32"
        "interface": 2
 
     ],
    "interfaces": [
      {"name": "cni0","mac": :"xxxx",},
      {"name": "veth3243","nac":"xxxx",},
      {"name": "eth0","mac":"xxxx","sandbox":"/var/ryb/netns/blue",}
   ],
    "dbs":{
      "baneservers": ["10.1.0.1"]  
   }
  ]
}

命令返回信息说明

     对于ADD或DELETE操作,返回码为0表示执行成功,非0表示失败,并以JSON报文的格式通过标准输出(stdout)返回操作的结果。
     以ADD操作为例,成功将容器添加到网络的结果将返回以下JSON报文。其中ips、routes和dns段的信息应该与IPAM Plugin(IPAM Plugin的说明详见下节)返回的结果相同,重要的是interfaces段,应通过CNI Plugin进行设置并返回。

{
  "cniVersion": "0.4.0",
  "interfaces": [     (this key omitted by IPAM plugins)
    {
      "name": "<name>",
      "mac": "<MAC address>",     (required if L2 addresses are meaningfull)
      "sandbox": "<netns path or hypervisor identifier>"     (required for container/hypervisor interfaces, empty/omitted for host interfaces)
    }
  ],
  "ips": [
    {
      "version": "<4-or-6>",
      "address": "<ip-and-prefix-in-CIDR>",
      "gateway": "<ip-address-of-the-gateway>"  (optional)
      "interface": <numeric index into 'interfaces' list>
    },
    ...
  ],
  "routes": [    (optional)
    {
      "dst": "<ip-and-prefix-in-cidr>",
      "gw": "<ip-of-next-hop>"   (optional)
    },
    ...
  ],
  "dns": {
      "nameservers": "<list-of-nameservers>",  (optional)
      "domain": "<name-of-local-domain>",  (optional)
      "search": "<list-of-search-domains>"  (optional)
      "options": "<list-of-options>"  (optional)
    }
}

 

 

  接口调用失败时,返回码不为0,应通过标准输出返回包含错误信息的如下JSON报文:

  

{
  "cniVersion": "0.4.0",
  "code": <numeric-error-code>,
  "msg": <short-error-message>,
  "details": <long-error-message>     (optional)
}

错误码包括如下内容。
◎ CNI版本不匹配。
◎ 在网络配置中存在不支持的字段,详细信息应在msg中说明。

 

 

小结:

 本章内容大家作文了解即可。

谢谢大家的支持与浏览

 

Logo

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

更多推荐