带你玩转kubernetes-k8s(第46篇:深入分析k8s网络原理[CNM、CNI]网络模型)

释放双眼,带上耳机,听听看~!

      随着容器技术在企业生产系统中的逐步落地,用户对容器云的网络特性要求也越来越高。跨主机容器间的网络互通已经成为基本要求,更高的要求包括容器固定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个组件进行实现,

带你玩转kubernetes-k8s(第46篇:深入分析k8s网络原理[CNM、CNI]网络模型)

 

◎ 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进行连接的模型。

带你玩转kubernetes-k8s(第46篇:深入分析k8s网络原理[CNM、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进行设置:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1{
2   "cniVersion": "0.4.0",
3   "name": "dbnet",
4   "type": "bridge",
5   "bridge": "cni0",
6   "ipam": {
7    "type": "host-local",
8    "subnet": "10.1.0.0/16",
9    "gateway": "10.1.0.1"
10    },
11    "dns": {
12       "nameservers": ["10.1.0.1"]
13     }
14
15}
16

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报文:

    


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1{
2    "cniVersion": "0.4.0",
3    "ips":[
4          {
5
6                   "version": "<4-or-6>",
7                    "address": "<ip-and-prefix-in-CIDR>",
8                    "gateway": "<ip-address-of-the-gateway>" (optional)
9           },
10           ..........
11      ],
12      "routes":[
13       {
14          "dst": "<ip-and-prefix-in-cidr>",
15           "gw": "<ip-of-next-hop>"
16        },
17       ........
18      ]
19
20      "dns":{
21       "nameservers": <list-of-nameservers> (optional)
22       "domain": <name-of-local-domain>  (optional)
23       "search": <list-of-options>  (optional)
24     }
25}
26

 

其中包括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插件:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1{
2  "cniVersion": "0.4.1",
3  "name": "dbnet",
4  "plugins": [
5    {
6      "type": "bridge",
7      // type (plugin) specific
8      "bridge": "cni0",
9      // args may be ignored by plugins
10      "args": {
11        "labels": {
12          "appVersion": "1.0"
13        }
14      },
15      "ipam": {
16        "type": "host-local",
17        // ipam specific
18        "subnet": "10.1.0.0/16",
19        "gateway": "10.1.0.1"
20      },
21      "dns": {
22        "nameserver": [ "10.1.0.1" ]
23      }
24    },
25    {
26      "type": "tuning",
27      "sysctl": {
28        "net.core.somaxconn": "500"
29      }
30    }
31  ]
32}
33
34

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1{
2  "cniVersion": "0.4.1",
3  "name": "dbnet",
4  "type": "bridge",
5  "bridge": "cni0",
6  "args": {
7    "labels": {
8      "appVersion": "1.0"
9    }
10  },
11  "ipam": {
12    "type": "host-local",
13    "subnet": "10.1.0.0/16",
14    "gateway": "10.1.0.1"
15  },
16  "dns": {
17    "nameservers": [ "10.1.0.1" ]
18  }
19}
20

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1{
2  "cniVersion": "0.4.1",
3  "name": "dbnet",
4  "type": "tuning",
5  "sysctl": {
6    "net.core.somaxconn": "500"
7  },
8  "prevResult": {
9    "ips": [
10       {
11         "version": "4",
12         "address": "10.0.0.5/32"
13         "interface": 2
14       }  
15    ] ,
16    "interfaces": [
17      {"name": "cni0","mac": :"xxxx",},
18      {"name": "veth3243","nac":"xxxx",},
19      {"name": "eth0","mac":"xxxx","sandbox":"/var/ryb/netns/blue",}
20   ],
21    "dbs":{
22      "baneservers": ["10.1.0.1"]  
23   }
24    
25  }
26}
27

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

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1{
2  "cniVersion": "0.4.0",
3  "name": "dbnet",
4  "type": "tuning",
5  "sysctl": {
6    "net.core.somaxconn": "500"
7  },
8  "prevResult":{
9     "ips":[
10    
11        "version": "4",
12        "address": "10.0.0.5/32"
13        "interface": 2
14
15     ],
16    "interfaces": [
17      {"name": "cni0","mac": :"xxxx",},
18      {"name": "veth3243","nac":"xxxx",},
19      {"name": "eth0","mac":"xxxx","sandbox":"/var/ryb/netns/blue",}
20   ],
21    "dbs":{
22      "baneservers": ["10.1.0.1"]  
23   }
24   }
25}
26

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
1{
2  "cniVersion": "0.4.1",
3  "name": "dbnet",
4  "type": "bridge",
5  "vridge": "cni0"
6      "agrs" :{
7
8         "appVersion": "1.0"
9      },
10      "ipam": {
11        "type": "host-local",
12        // ipam specific
13        "subnet": "10.1.0.0/16",
14        "gateway": "10.1.0.1"
15      },
16      "dns": {
17        "nameserver": [ "10.1.0.1" ]
18     
19       },
20    "prevResult":{
21     "ips":[
22    
23        "version": "4",
24        "address": "10.0.0.5/32"
25        "interface": 2
26
27     ],
28    "interfaces": [
29      {"name": "cni0","mac": :"xxxx",},
30      {"name": "veth3243","nac":"xxxx",},
31      {"name": "eth0","mac":"xxxx","sandbox":"/var/ryb/netns/blue",}
32   ],
33    "dbs":{
34      "baneservers": ["10.1.0.1"]  
35   }
36  ]
37}
38

命令返回信息说明

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1{
2  "cniVersion": "0.4.0",
3  "interfaces": [     (this key omitted by IPAM plugins)
4    {
5      "name": "<name>",
6      "mac": "<MAC address>",     (required if L2 addresses are meaningfull)
7      "sandbox": "<netns path or hypervisor identifier>"     (required for container/hypervisor interfaces, empty/omitted for host interfaces)
8    }
9  ],
10  "ips": [
11    {
12      "version": "<4-or-6>",
13      "address": "<ip-and-prefix-in-CIDR>",
14      "gateway": "<ip-address-of-the-gateway>"  (optional)
15      "interface": <numeric index into 'interfaces' list>
16    },
17    ...
18  ],
19  "routes": [    (optional)
20    {
21      "dst": "<ip-and-prefix-in-cidr>",
22      "gw": "<ip-of-next-hop>"   (optional)
23    },
24    ...
25  ],
26  "dns": {
27      "nameservers": "<list-of-nameservers>",  (optional)
28      "domain": "<name-of-local-domain>",  (optional)
29      "search": "<list-of-search-domains>"  (optional)
30      "options": "<list-of-options>"  (optional)
31    }
32}
33
34

 

 

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

  


1
2
3
4
5
6
7
1{
2  "cniVersion": "0.4.0",
3  "code": <numeric-error-code>,
4  "msg": <short-error-message>,
5  "details": <long-error-message>     (optional)
6}
7

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

 

 

小结:

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

谢谢大家的支持与浏览

 

给TA打赏
共{{data.count}}人
人已打赏
安全运维

故障复盘的简洁框架-黄金三问

2021-9-30 19:18:23

安全运维

OpenSSH-8.7p1离线升级修复安全漏洞

2021-10-23 10:13:25

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索