重学容器17: CNI网络配置详解
2021-06-27
本节来学习CNI的网络配置。
CNI网络配置(Network Configuration) #
CNI的网络配置是JSON格式的,可以是存储在磁盘中的文件,也可以由容器运行时以其他方式生成。
下面是cni json配置文件中的一些重要字段:
cniVersion
(string): 描述cni配置遵循的cni规范版本(版本号为语义化版本,如0.4.0)name
(string): 表示network name,在主机(或其他管理域)上的所有容器中应该是唯一的type
(string): 表示cni插件的可执行文件名args
(dictionary, optional): 由容器运行时提供的可选参数。例如,可以通过将标签添加到args下的标签字段,将标签字典传递给CNI插件ipMasq
(boolean, optional): 如果插件支持此字段,将为这个网络上的主机设置一个ip伪装(ip masquerade)。如果主机将充当分配给容器的子网的网管,那么这个配置字段是必须的ipam
(boolean, optional): 包含具体IPAM(IP地址管理)值的键值对type
(string) 表示ipam插件的可执行文件名,如dhscp
,host-local
,static
dns
(dictionary, optional): 包含具体DNS配置的键值对nameservers
(list of strings, optional): 一个对配置网络可见的按优先级顺序排列的dns服务器列表,列表中的每个值是一个IPV4或IPV6的字符串domain
(string, optional): 用于短主机名查找的本地域名search
(list of strings, optional): 用于短主机名查找的优先级排序搜索域列表,被大多数解析器(resolver)在解析时优先于domain
options
(list of strings, optional): 一组可以传递给解析器(resolver)的选项值
cni网络的JSON配置除了上面这些标准字段外,某个具体的插件还可以定义自己的附加字段,但如果配置了插件未定义的字段将会报错。args
中配置的附加字段可以用来传递任意数据,如果插件不认识args中传递的字段,将会直接忽略而不会报错。
下面是一些cni网络配置的示例:
1{
2 "cniVersion": "0.4.0",
3 "name": "dbnet",
4 "type": "bridge",
5 // type (plugin) specific
6 "bridge": "cni0",
7 "ipam": {
8 "type": "host-local",
9 // ipam specific
10 "subnet": "10.1.0.0/16",
11 "gateway": "10.1.0.1"
12 },
13 "dns": {
14 "nameservers": [ "10.1.0.1" ]
15 }
16}
1{
2 "cniVersion": "0.4.0",
3 "name": "pci",
4 "type": "ovs",
5 // type (plugin) specific
6 "bridge": "ovs0",
7 "vxlanID": 42,
8 "ipam": {
9 "type": "dhcp",
10 "routes": [ { "dst": "10.3.0.0/16" }, { "dst": "10.4.0.0/16" } ]
11 },
12 // args may be ignored by plugins
13 "args": {
14 "labels" : {
15 "appVersion" : "1.0"
16 }
17 }
18}
1{
2 "cniVersion": "0.4.0",
3 "name": "wan",
4 "type": "macvlan",
5 // ipam specific
6 "ipam": {
7 "type": "dhcp",
8 "routes": [ { "dst": "10.0.0.0/8", "gw": "10.0.0.1" } ]
9 },
10 "dns": {
11 "nameservers": [ "10.0.0.1" ]
12 }
13}
CNI网络配置列表(Network Configuration Lists) #
CNI的网络配置列表提供了一种机制,可以为单个容器按已经定义好的顺序运行多个CNI插件,执行过程中将每个插件的结果传递给下一个插件。 CNI的网络配置列表由多个标准的CN网络配置组成。
CNI网络配置也是JSON格式的,可以是存储在磁盘中的文件,也可以由容器运行时以其他方式生成。下面是CNI网络配置列表的字段:
cniVersion
(string): 描述cni配置遵循的cni规范版本(版本号为语义化版本,如0.4.0)name
(string): 表示network name,在主机(或其他管理域)上的所有容器中应该是唯一的disableCheck
(string): 如果配置为false,运行时将不会为此配置列表调用CHECK接口plugins
(list): 一组CNI网络配置(如前面描述)
当执行一个插件列表时,运行时必须将列表中的每个网络配置的name
和cniVersion
字段替换为列表本身的name
和cniVersion
字段,这样可以确保列表中所有插件的name
和cniVersion
是一致的,避免出现插件之间的版本冲突 。
CNI接口定义了ADD,DEL,VERSION,CHECK等接口,对于CNI网络配置列表在执行时需满足以下要求。
对于ADD操,运行时必须在每一个插件后面的插件的JSON配置中添加一个prevResult
字段,该字段必须是前一个插件(如果有的话)执行的JSON格式的结果。
对于CHECK和DEL,运行时必须在每个插件的配置JSON中添加一个prevResult
字段(除非DEL不可用可以省略),该字段必须是前一个ADD执行的JSON结果。
对于ADD操作,插件应该将prevResult
字段的内容显示到的标准输出中,以允许后边的插件及运行时接收结果,除非它们希想要改或禁抑制前面的结果。
允许插件修改或抑制前一个插件的结果preResult的全部或部分内容。运行时必须使用相同的环境执行列表中的每个插件,对于DEL操作运行时必须以反向顺序执行插件。
当在插件列表上执行一个操作(如ADD或DEL)时发生了错误,运行时必须停止列表的执行。如果ADD执行失败,当运行时决定进行错误处理时,它应该为列表中的所有插件以与上面指定的ADD相反的顺序执行DEL,即使有些插件在ADD操作期间没有被调用。
下面是一些cni网络配置列表的示例:
1{
2 "cniVersion": "0.4.0",
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 "nameservers": [ "10.1.0.1" ]
23 }
24 },
25 {
26 "type": "tuning",
27 "sysctl": {
28 "net.core.somaxconn": "500"
29 }
30 }
31 ]
32}
下面一起看一下,对于上面示例的cni网络配置列表容器运行时是如何执行ADD、CHEK、DEL的。
ADD #
- 首先使用下面的配置调用
bridge
插件
1{
2 "cniVersion": "0.4.0",
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}
2.接下来使用下面的配置调用tuning
插件,配置中preResult
是前面bridge
插件的执行结果
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 {
18 "name": "cni0",
19 "mac": "00:11:22:33:44:55",
20 },
21 {
22 "name": "veth3243",
23 "mac": "55:44:33:22:11:11",
24 },
25 {
26 "name": "eth0",
27 "mac": "99:88:77:66:55:44",
28 "sandbox": "/var/run/netns/blue",
29 }
30 ],
31 "dns": {
32 "nameservers": [ "10.1.0.1" ]
33 }
34 }
35}
CHECK #
- 首先使用下面的配置调用
brdige
插件,配置中的preResutl
包含ADD的执行结果
1{
2 "cniVersion": "0.4.0",
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 // ipam specific
14 "subnet": "10.1.0.0/16",
15 "gateway": "10.1.0.1"
16 },
17 "dns": {
18 "nameservers": [ "10.1.0.1" ]
19 }
20 "prevResult": {
21 "ips": [
22 {
23 "version": "4",
24 "address": "10.0.0.5/32",
25 "interface": 2
26 }
27 ],
28 "interfaces": [
29 {
30 "name": "cni0",
31 "mac": "00:11:22:33:44:55",
32 },
33 {
34 "name": "veth3243",
35 "mac": "55:44:33:22:11:11",
36 },
37 {
38 "name": "eth0",
39 "mac": "99:88:77:66:55:44",
40 "sandbox": "/var/run/netns/blue",
41 }
42 ],
43 "dns": {
44 "nameservers": [ "10.1.0.1" ]
45 }
46 }
47}
2.接下来使用下面的配置调用tuning
插件,配置中的preResutl
包含ADD的执行结果
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 {
18 "name": "cni0",
19 "mac": "00:11:22:33:44:55",
20 },
21 {
22 "name": "veth3243",
23 "mac": "55:44:33:22:11:11",
24 },
25 {
26 "name": "eth0",
27 "mac": "99:88:77:66:55:44",
28 "sandbox": "/var/run/netns/blue",
29 }
30 ],
31 "dns": {
32 "nameservers": [ "10.1.0.1" ]
33 }
34 }
35}
DEL #
DEL执行插件的顺序与ADD和CHECK相反。
- 首先使用下面的配置调用
tuning
插件,配置中的preResult
字段是ADD的执行结果
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 {
18 "name": "cni0",
19 "mac": "00:11:22:33:44:55",
20 },
21 {
22 "name": "veth3243",
23 "mac": "55:44:33:22:11:11",
24 },
25 {
26 "name": "eth0",
27 "mac": "99:88:77:66:55:44",
28 "sandbox": "/var/run/netns/blue",
29 }
30 ],
31 "dns": {
32 "nameservers": [ "10.1.0.1" ]
33 }
34 }
35}
- 接下来使用下面的配置调用
bridge
插件,配置中的preResult
字段是ADD的执行结果
1{
2 "cniVersion": "0.4.0",
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 // ipam specific
14 "subnet": "10.1.0.0/16",
15 "gateway": "10.1.0.1"
16 },
17 "dns": {
18 "nameservers": [ "10.1.0.1" ]
19 },
20 "prevResult": {
21 "ips": [
22 {
23 "version": "4",
24 "address": "10.0.0.5/32",
25 "interface": 2
26 }
27 ],
28 "interfaces": [
29 {
30 "name": "cni0",
31 "mac": "00:11:22:33:44:55",
32 },
33 {
34 "name": "veth3243",
35 "mac": "55:44:33:22:11:11",
36 },
37 {
38 "name": "eth0",
39 "mac": "99:88:77:66:55:44",
40 "sandbox": "/var/run/netns/blue",
41 }
42 ],
43 "dns": {
44 "nameservers": [ "10.1.0.1" ]
45 }
46 }
47}
k8s pod网络的CNI配置列表 #
已经学习了CNI网络配置和网络配置列表,再看k8s pod网络的CNI配置列表文件就很清晰了。
使用calico作为k8s pod网络组件时,其CNI将配置列表文件/etc/cni/net.d/10-calico.conflist如下:
1{
2 "name": "k8s-pod-network",
3 "cniVersion": "0.3.1",
4 "plugins": [
5 {
6 "type": "calico",
7 "datastore_type": "kubernetes",
8 "mtu": 0,
9 "nodename_file_optional": false,
10 "log_level": "Info",
11 "log_file_path": "/var/log/calico/cni/cni.log",
12 "ipam": { "type": "calico-ipam", "assign_ipv4" : "true", "assign_ipv6" : "false"},
13 "container_settings": {
14 "allow_ip_forwarding": false
15 },
16 "policy": {
17 "type": "k8s"
18 },
19 "kubernetes": {
20 "k8s_api_root":"https://10.96.0.1:443",
21 "kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
22 }
23 },
24 {
25 "type": "bandwidth",
26 "capabilities": {"bandwidth": true}
27 },
28 {"type": "portmap", "snat": true, "capabilities": {"portMappings": true}}
29 ]
30}
上面的配置中使用calico的k8s-pod-network
,遵循cni 0.3.1规范,插件列表配置了calico, bandwidth, portmap插件。
使用flannel作为k8s pod网络组件时,其CNI将配置列表文件10-flannel.conflist如下:
1{
2 "name": "cbr0",
3 "cniVersion": "0.3.1",
4 "plugins": [
5 {
6 "type": "flannel",
7 "delegate": {
8 "hairpinMode": true,
9 "isDefaultGateway": true
10 }
11 },
12 {
13 "type": "portmap",
14 "capabilities": {
15 "portMappings": true
16 }
17 }
18 ]
19}