本节来学习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)在解析时优先于domainoptions(list of strings, optional): 一组可以传递给解析器(resolver)的选项值
cni网络的JSON配置除了上面这些标准字段外,某个具体的插件还可以定义自己的附加字段,但如果配置了插件未定义的字段将会报错。args中配置的附加字段可以用来传递任意数据,如果插件不认识args中传递的字段,将会直接忽略而不会报错。
下面是一些cni网络配置的示例:
{
"cniVersion": "0.4.0",
"name": "dbnet",
"type": "bridge",
// type (plugin) specific
"bridge": "cni0",
"ipam": {
"type": "host-local",
// ipam specific
"subnet": "10.1.0.0/16",
"gateway": "10.1.0.1"
},
"dns": {
"nameservers": [ "10.1.0.1" ]
}
}{
"cniVersion": "0.4.0",
"name": "pci",
"type": "ovs",
// type (plugin) specific
"bridge": "ovs0",
"vxlanID": 42,
"ipam": {
"type": "dhcp",
"routes": [ { "dst": "10.3.0.0/16" }, { "dst": "10.4.0.0/16" } ]
},
// args may be ignored by plugins
"args": {
"labels" : {
"appVersion" : "1.0"
}
}
}{
"cniVersion": "0.4.0",
"name": "wan",
"type": "macvlan",
// ipam specific
"ipam": {
"type": "dhcp",
"routes": [ { "dst": "10.0.0.0/8", "gw": "10.0.0.1" } ]
},
"dns": {
"nameservers": [ "10.0.0.1" ]
}
}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网络配置列表的示例:
{
"cniVersion": "0.4.0",
"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": {
"nameservers": [ "10.1.0.1" ]
}
},
{
"type": "tuning",
"sysctl": {
"net.core.somaxconn": "500"
}
}
]
}下面一起看一下,对于上面示例的cni网络配置列表容器运行时是如何执行ADD、CHEK、DEL的。
ADD
- 首先使用下面的配置调用
bridge插件
{
"cniVersion": "0.4.0",
"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插件,配置中preResult是前面bridge插件的执行结果
{
"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": "00:11:22:33:44:55",
},
{
"name": "veth3243",
"mac": "55:44:33:22:11:11",
},
{
"name": "eth0",
"mac": "99:88:77:66:55:44",
"sandbox": "/var/run/netns/blue",
}
],
"dns": {
"nameservers": [ "10.1.0.1" ]
}
}
}CHECK
- 首先使用下面的配置调用
brdige插件,配置中的preResutl包含ADD的执行结果
{
"cniVersion": "0.4.0",
"name": "dbnet",
"type": "bridge",
"bridge": "cni0",
"args": {
"labels" : {
"appVersion" : "1.0"
}
},
"ipam": {
"type": "host-local",
// ipam specific
"subnet": "10.1.0.0/16",
"gateway": "10.1.0.1"
},
"dns": {
"nameservers": [ "10.1.0.1" ]
}
"prevResult": {
"ips": [
{
"version": "4",
"address": "10.0.0.5/32",
"interface": 2
}
],
"interfaces": [
{
"name": "cni0",
"mac": "00:11:22:33:44:55",
},
{
"name": "veth3243",
"mac": "55:44:33:22:11:11",
},
{
"name": "eth0",
"mac": "99:88:77:66:55:44",
"sandbox": "/var/run/netns/blue",
}
],
"dns": {
"nameservers": [ "10.1.0.1" ]
}
}
}2.接下来使用下面的配置调用tuning插件,配置中的preResutl包含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": "00:11:22:33:44:55",
},
{
"name": "veth3243",
"mac": "55:44:33:22:11:11",
},
{
"name": "eth0",
"mac": "99:88:77:66:55:44",
"sandbox": "/var/run/netns/blue",
}
],
"dns": {
"nameservers": [ "10.1.0.1" ]
}
}
}DEL
DEL执行插件的顺序与ADD和CHECK相反。
- 首先使用下面的配置调用
tuning插件,配置中的preResult字段是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": "00:11:22:33:44:55",
},
{
"name": "veth3243",
"mac": "55:44:33:22:11:11",
},
{
"name": "eth0",
"mac": "99:88:77:66:55:44",
"sandbox": "/var/run/netns/blue",
}
],
"dns": {
"nameservers": [ "10.1.0.1" ]
}
}
}- 接下来使用下面的配置调用
bridge插件,配置中的preResult字段是ADD的执行结果
{
"cniVersion": "0.4.0",
"name": "dbnet",
"type": "bridge",
"bridge": "cni0",
"args": {
"labels" : {
"appVersion" : "1.0"
}
},
"ipam": {
"type": "host-local",
// ipam specific
"subnet": "10.1.0.0/16",
"gateway": "10.1.0.1"
},
"dns": {
"nameservers": [ "10.1.0.1" ]
},
"prevResult": {
"ips": [
{
"version": "4",
"address": "10.0.0.5/32",
"interface": 2
}
],
"interfaces": [
{
"name": "cni0",
"mac": "00:11:22:33:44:55",
},
{
"name": "veth3243",
"mac": "55:44:33:22:11:11",
},
{
"name": "eth0",
"mac": "99:88:77:66:55:44",
"sandbox": "/var/run/netns/blue",
}
],
"dns": {
"nameservers": [ "10.1.0.1" ]
}
}
}k8s pod网络的CNI配置列表
已经学习了CNI网络配置和网络配置列表,再看k8s pod网络的CNI配置列表文件就很清晰了。
使用calico作为k8s pod网络组件时,其CNI将配置列表文件/etc/cni/net.d/10-calico.conflist如下:
{
"name": "k8s-pod-network",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "calico",
"datastore_type": "kubernetes",
"mtu": 0,
"nodename_file_optional": false,
"log_level": "Info",
"log_file_path": "/var/log/calico/cni/cni.log",
"ipam": { "type": "calico-ipam", "assign_ipv4" : "true", "assign_ipv6" : "false"},
"container_settings": {
"allow_ip_forwarding": false
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"k8s_api_root":"https://10.96.0.1:443",
"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
}
},
{
"type": "bandwidth",
"capabilities": {"bandwidth": true}
},
{"type": "portmap", "snat": true, "capabilities": {"portMappings": true}}
]
}上面的配置中使用calico的k8s-pod-network,遵循cni 0.3.1规范,插件列表配置了calico, bandwidth, portmap插件。
使用flannel作为k8s pod网络组件时,其CNI将配置列表文件10-flannel.conflist如下:
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}