前段时间写过一篇文章Xin He:kubernetes的clusterip机制调研及macvlan网路下的clusterip坑解决方案[1],提到过对于k8s多网卡方案multus-cni[2]插件的吐槽,认为其缺少创新性,没有把自己定位成Pod网路与Node节点的一个解耦层,表示遗憾。但是经过这几天深入研究,发现通过某种配置实践方式,multus-cni是能够实现Pod网路与Node节点的网路配置完全解耦的,换句话说,我们可以通过multus-cni提供的能力,实现创建Pod的时候,任意指定其网路类型(这个任意,几乎可以做到完全任意,不受约束,不过个人表示很可惜,multus-cni能够实现这个能力,但是在他的README.md[3]说明上,并没有重点强调这一点,如果不是笔者深入使用,可能也不会发现这个内在的能力)

这里通过multus-cni的v3.2[4]版本,来说明如何实现这个能力。PS:对于multus-cni的原理,这里不做重点介绍,大家可以自己去了解,简单说,顾名思义,multus-cni就是多个cni插件可以同时被使用的意思,相当于在多个cni插件上面又配置了一层cni插件,通过配置这层插件,来实现多个底层cni插件的选择和执行,从名字上来看,大家更多理解使用它来做多网卡Pod,但其实也可以实现任意选择CNI网路的能力(单网卡的更换选择,也可以,后面说)。

回主题,重点讲multus-cni如何实现灵活指定Pod网路:

本文以具备Calico+macvlan网路能力的cluster环境为例,实现Pod的三种网路类型:1、单独Calico网路;2、单独macvlan网路;3、Calico+macvlan双网路,同时macvlan网路是默认网路(即默认路由走macvlan网卡)。

先说1、单独Calico网路:

首先需要部署Calico,这里笔者部署的是Calico v3.8[5][6]版本,部署方式[7]如下:

1.Download the Calico networking manifest for the Kubernetes API datastore.

curl https://docs.projectcalico.org/v3.8/manifests/calico.yaml -O

2.If you are using pod CIDR 192.168.0.0/16, skip to the next step. If you are using a different pod CIDR, use the following commands to set an environment variable called POD_CIDR containing your pod CIDR and replace 192.168.0.0/16 in the manifest with your pod CIDR.

POD_CIDR="<your-pod-cidr>"
sed -i -e "s?192.168.0.0/16?$POD_CIDR?g" calico.yaml

3.Apply the manifest using the following command.

kubectl apply -f calico.yaml

# NOTE:对于多网卡的node,注意修改calico.yaml,在
- name: IP
value: "autodetect"
后面加入
- name: IP_AUTODETECTION_METHOD
value: "can-reach=114.114.114.114"
找到默认网卡。

安装calicoctl(非必要,略过),安装过程可以参考附注[8]

然后部署multus-cni,基于v3.2[4]版本,部署方式[9]如下:

git clone https://github.com/intel/multus-cni.git && cd multus-cni
git checkout -b branch_v3.2 v3.2
cat ./images/multus-daemonset.yml | kubectl apply -f -

修改multus-cni的配置文件/etc/cni/net.d/00-multus.conf:

{
"name": "multus-cni-network",
"type": "multus",
"confDir": "/etc/cni/multus/net.d",
"cniDir": "/var/lib/cni/multus",
"binDir": "/opt/cni/bin",
"logFile": "/var/log/multus.log",
"logLevel": "info",
"capabilities": {
"portMappings": true
},
"clusterNetwork": "net-calico",
"defaultNetworks": [],
"delegates": [],
"kubeconfig": "/etc/cni/net.d/multus.d/multus.kubeconfig"
}

这里参考官方配置文档[10],不做赘述。重点提示下,net-calico这个网路,在后面的提到的配置文件中,必须正确配置,否则会报无法找到网路,但是因为multus的报错缺少细节,所以之前排查原因,还花了一段时间,刚开始以为是上面这个配置文件的格式不对,确认了multus-cni源码,配置格式没问题,后来仔细看net-calico的配置,才知道是net-calico自身的配置错误造成。

对于net-calico这个网路,笔者采用的是NetworkAttachmentDefinition[11]的方式配置,同时没有指定具体的配置内容,而是通过每台Node节点上的/etc/cni/multus/net.d/下的同name配置文件来配置,这样做可以基于Node定制配置(因为采用了host-local的IPAM,所以必须这样),具体看配置:

# Execute following command at Kubernetes master
# 这里强调一下,配置到00-multus.conf配置文件中的NetworkAttachmentDefinition的namespace
# 必须与multus-cni daemonset的namespace相同.
# 参见https://github.com/intel/multus-cni/issues/302#issuecomment-484407240
# https://github.com/intel/multus-cni/blob/v3.2/doc/configuration.md#network-selection-flow-of-clusternetworkdefaultnetworks

cat <<EOF | kubectl create -f -
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: net-calico
namespace: kube-system
EOF

# Execute following commands at all Kubernetes nodes (i.e. master and minions)
#根据实际情况修改ip地址域
#/etc/cni/multus/net.d/这个目录需要提前创建一下
mkdir -p /etc/cni/multus/net.d/
cat > /etc/cni/multus/net.d/calico.conf <<EOF
{
"name": "net-calico",
"cniVersion": "0.3.0",
"type": "calico",
"log_level": "info",
"datastore_type": "kubernetes",
"nodename": "node-001",
"mtu": 1440,
"ipam": {
"type": "host-local",
"ranges": [
[
{ "subnet": "192.168.0.0/16",
"rangeStart": "192.168.0.1",
"rangeEnd": "192.168.0.100" }
]
],
"routes": [
{ "dst": "0.0.0.0/0"},
{ "dst": "192.168.0.0/16" },
{ "dst": "10.96.0.0/12" },
{ "dst": "100.73.3.0/24" }
]
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
}
}
EOF

#笔者测试环境有3台机器,所以分别在三台机器上创建了对应的配置文件,修改内容如下:
#"nodename"修改成所在Node的hostname
#"ranges"修改成所在Node的pod ip范围
#自定义routes,单网卡其实只需要{ "dst": "0.0.0.0/0"}即可。

NOTE:特别注意,/etc/cni/multus/net.d/下的配置文件,是不支持CNI的级联CNI多插件配置,所以类似Calico原生的与portmap插件级联的plugins配置[12][13],是不可用的【如下这种配置,会报错无法找到plugin type,上文笔者提到的不准确报错,就是因为这个,后来查了很久,才找到原因,这里不赘述了】:

# 错误配置!!!
{
"name": "net-calico",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "calico",
"log_level": "info",
"datastore_type": "kubernetes",
"nodename": "node-001",
"mtu": 1440,
"ipam": {
"type": "calico-ipam"
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
}
},
{
"type": "portmap",
"snat": true,
"capabilities": {"portMappings": true}
}
]
}

OK,按照如上配置,创建Pod:

cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: samplepod-calico
spec:
containers:
- name: samplepod
command: ["/bin/bash", "-c", "sleep 2000000000000"]
image: dougbtv/centos-network
EOF

#查看一下Pod信息
kubectl describe pods samplepod-calico
--------------可以看到正确获取了calico ip------------------------
Node: node-003/100.73.3.3
Start Time: Wed, 17 Jul 2019 18:59:31 +0800
Labels: <none>
Annotations: cni.projectcalico.org/podIP: 192.168.0.211/32
k8s.v1.cni.cncf.io/networks-status:
[{
"name": "net-calico",
"ips": [
"192.168.0.211"
],
"default": true,
"dns": {}
}]
Status: Running
IP: 192.168.0.211
-------------

2、单独macvlan网路:

需要在/etc/cni/multus/net.d/下添加macvlan网路的配置文件(参考[11]),内容如下:

# Execute following command at Kubernetes master

cat <<EOF | kubectl create -f -
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: net-macvlan
EOF

cat > /etc/cni/multus/net.d/macvlan.conf <<EOF
{
"cniVersion": "0.3.0",
"type": "macvlan",
"name": "net-macvlan",
"master": "bond0.2734",
"mode": "bridge",
"isDefaultGateway": true,
"ipam": {
"expiredPeriod": 10,
"type": "host-local",
"subnet": "100.73.34.0/24",
"rangeStart": "100.73.34.20",
"rangeEnd": "100.73.34.49",
"gateway": "100.73.34.254",
"routes": [
{ "dst": "0.0.0.0/0", "gw": "100.73.34.254" }
]
}
}
EOF

#笔者测试环境有3台机器,所以分别在三台机器上创建了对应的配置文件,修改内容如下:
#"ranges"修改成所在Node的pod ip范围
#自定义routes,单网卡只需要{ "dst": "0.0.0.0/0"}即可。

创建Pod,这里因为需要修改Pod的默认网卡,所以需要加入annotation[14],如下:

cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: samplepod-macvlan
annotations:
v1.multus-cni.io/default-network: default/net-macvlan
spec:
containers:
- name: samplepod
command: ["/bin/bash", "-c", "sleep 2000000000000"]
image: dougbtv/centos-network
EOF

NOTE:v1.multus-cni.io/defaul这个annotation默认的namespace是kube-system,所以net-macvlan需要表示成default/net-macvlan,否则创建Pod时会报错,无法找到网路,参考[15]

#查看一下Pod信息
kubectl describe pods samplepod-macvlan
--------------可以看到正确获取了macvlan ip------------------------
Node: node-003/100.73.3.3
Start Time: Thu, 18 Jul 2019 09:42:07 +0800
Labels: <none>
Annotations: k8s.v1.cni.cncf.io/networks-status:
[{
"name": "net-macvlan",
"interface": "eth0",
"ips": [
"100.73.34.81"
],
"mac": "76:b6:6c:d6:aa:fb",
"default": true,
"dns": {}
}]
v1.multus-cni.io/default-network: default/net-macvlan
Status: Running
IP: 100.73.34.81
-------------

NOTE:multus-cni的官方文档里面一直在强调Pod的默认网路应该是cluster network(例如flannel、Calico),但其实使用macvlan这种网路也可以。

3、Calico+macvlan双网路,同时macvlan网路是默认网路(即默认路由走macvlan网卡)

也许大家认为可以用下面的方式,创建这个网路,但其实不可以,会报错,因为涉及一个默认路由冲突的问题。

# 错误的创建方式!!!
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: samplepod-macvlan-calico-error
annotations:
v1.multus-cni.io/default-network: default/net-macvlan
k8s.v1.cni.cncf.io/networks: kube-system/net-calico
spec:
containers:
- name: samplepod
command: ["/bin/bash", "-c", "sleep 2000000000000"]
image: dougbtv/centos-network
EOF

#执行后,Pod无法创建成功,describe报错如下:
Failed create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container
"5dcf6fbc2bdafbf806dc00ba0c272af0924a859aee5918629bb61c1cac5df1e0" network for pod
"samplepod-macvlan-calico-error": NetworkPlugin cni failed to set up pod "samplepod-macvlan-calico-error_default"
network: Multus: Err adding pod to network "net-calico": Multus: error in invoke Delegate add - "calico":
failed to add IPv4 route for 0.0.0.0/0 via 169.254.1.1: file exists

怎么办?现在来看,只能重新再创建一个不包含默认路由的calico网路,专门用来作macvlan的辅助网路。

# Execute following command at Kubernetes master

cat <<EOF | kubectl create -f -
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: net-calico-2
EOF

# Execute following commands at all Kubernetes nodes (i.e. master and minions)
#根据实际情况修改ip地址域
cat > /etc/cni/multus/net.d/calico2.conf <<EOF
{
"name": "net-calico-2",
"cniVersion": "0.3.0",
"type": "calico",
"log_level": "info",
"datastore_type": "kubernetes",
"nodename": "node-001",
"mtu": 1440,
"ipam": {
"type": "host-local",
"ranges": [
[
{ "subnet": "192.168.0.0/16",
"rangeStart": "192.168.1.1",
"rangeEnd": "192.168.1.100" }
]
],
"routes": [
{ "dst": "192.168.0.0/16" },
{ "dst": "10.96.0.0/12" },
{ "dst": "100.73.3.0/24" }
]
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
}
}
EOF

#笔者测试环境有3台机器,所以分别在三台机器上创建了对应的配置文件,修改内容如下:
#"nodename"修改成所在Node的hostname
#"ranges"修改成所在Node的pod ip范围
#自定义routes,因为多网卡,需要加入如上配置路由。

对于上面的路由配置,因为calico辅助网路主要是用于Pod之间、Pod与clusterip之间、Pod与Node之间的访问,所以加入了三个固定的路由,目标地址域分别为Pod地址域、clusterip地址域、Node地址域。(特别说明:这些路由会带来的附加影响,就是从这些目标地址域不能访问Pod的macvlan ip)

然后这里还有一个坑,就是不能指定默认网路v1.multus-cni.io/defaul为net-macvlan,辅助网路k8s.v1.cni.cncf.io/netw为net-calico-2,会造成Pod创建成功,但是calico网路其实不通【具体原因现在仍待查,怀疑是这种情况下calico网路作为辅助网路,会被少下发一些配置,造成无法正常使用】,错误的创建方式如下:

# 错误的创建方式!!!
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: samplepod-macvlan-calico-wrong
annotations:
v1.multus-cni.io/default-network: default/net-macvlan
k8s.v1.cni.cncf.io/networks: net-calico-2
spec:
containers:
- name: samplepod
command: ["/bin/bash", "-c", "sleep 2000000000000"]
image: dougbtv/centos-network
EOF

所以可用的创建方式,现在来看,只能是把默认网路v1.multus-cni.io/defaul配置成net-calico-2,然后把辅助网路k8s.v1.cni.cncf.io/netw配置成net-macvlan,具体如下:

cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: samplepod-macvlan-calico
annotations:
v1.multus-cni.io/default-network: default/net-calico-2
k8s.v1.cni.cncf.io/networks: net-macvlan
spec:
containers:
- name: samplepod
command: ["/bin/bash", "-c", "sleep 2000000000000"]
image: dougbtv/centos-network
EOF

# 查看一下Pod信息
--------------可以看到正确获取了macvlan和calico网卡的ip------------------------
Node: node-003/100.73.3.3
Start Time: Thu, 18 Jul 2019 15:39:29 +0800
Labels: <none>
Annotations: cni.projectcalico.org/podIP: 192.168.1.242/32
k8s.v1.cni.cncf.io/networks: net-macvlan
k8s.v1.cni.cncf.io/networks-status:
[{
"name": "net-calico-2",
"ips": [
"192.168.1.242"
],
"default": true,
"dns": {}
},{
"name": "net-macvlan",
"interface": "net1",
"ips": [
"100.73.34.107"
],
"mac": "5e:8c:13:a9:23:0d",
"dns": {}
}]
v1.multus-cni.io/default-network: default/net-calico-2
Status: Running
IP: 192.168.1.242
-------------------------
查看ip和路由信息,并验证通信,现在从任意外部网路,都可以ping通macvlan的100.73.34.107地址,用于外部网路访问。
# kubectl exec -it samplepod-macvlan-calico -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if862: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP
link/ether 12:d8:97:ab:6b:15 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.1.242/32 scope global eth0
valid_lft forever preferred_lft forever
5: net1@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 5e:8c:13:a9:23:0d brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 100.73.34.107/24 scope global net1
valid_lft forever preferred_lft forever

# kubectl exec -it samplepod-macvlan-calico -- route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 100.73.34.254 0.0.0.0 UG 0 0 0 net1
10.96.0.0 169.254.1.1 255.240.0.0 UG 0 0 0 eth0
100.73.3.0 169.254.1.1 255.255.255.0 UG 0 0 0 eth0
100.73.34.0 0.0.0.0 255.255.255.0 U 0 0 0 net1
169.254.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
192.168.0.0 169.254.1.1 255.255.0.0 UG 0 0 0 eth0

可以看到,上面这么做,有一个问题,就是calico的网卡会默认被命名成eth0,macvlan的网卡会被命名成net1,但其实这是可以改的,如果想让macvlan的网卡是eth0(因为是默认路由网卡),calico网卡是eth1,可以按如下配置创建[16],【但是这里要很遗憾的说,如果按照如下配置创建Pod,把net-macvlan网卡名字指定成eth0,这个Pod会跟上面把v1.multus-cni.io/defaul指定为net-macvlan的情形一样,calico网路会不通,看来calico的某种配置,跟eth0这个名字有某种微妙的关系(只要不把calico的网卡设置成eth0,要么calico网路不通,要么容器频繁重启),还有待研究】:

# 不可行的创建方式!!!
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: samplepod-macvlan-calico
annotations:
v1.multus-cni.io/default-network: default/net-calico-2@eth1
k8s.v1.cni.cncf.io/networks: net-macvlan@eth0
spec:
containers:
- name: samplepod
command: ["/bin/bash", "-c", "sleep 2000000000000"]
image: dougbtv/centos-network
EOF

#查看一下Pod信息
# kubectl exec -it samplepod-macvlan-calico -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: eth1@if863: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP
link/ether d6:60:42:a0:64:63 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.1.243/32 scope global eth1
valid_lft forever preferred_lft forever
5: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 9e:fd:eb:47:35:e2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 100.73.34.108/24 scope global eth0
valid_lft forever preferred_lft forever

终上,三种网路类型的创建方法已经说明完,总结一下,在一定程度上,multus-cni还是实现了在创建Pod的时候指定Pod网路类型的能力的,不要小看这个能力,个人觉得,docker的CNM网路模型,通过创建容器时的--network参数指定容器网路,还是很不错的,虽然k8s没有采用这种方式,而是把Pod的网路与Node节点做了紧耦合,或者说是与cluster集群做了紧耦合,这样做的初衷应该是希望一个cluster就是一个整体的网路,一切不需要再配置,自动化简洁化很好,但是这样做,确实没有考虑用户在某种特殊情况下的定制化网路需求(例如故障调试、测试应用等),google的深度自动化思维,可以理解,但是深度自动化不代表排斥定制化能力,这两个应该不是互斥的关系,所以,如果能够通过加入一层CNI插件,进行解耦,实现类似docker在创建容器时指定网路的能力,也是很不错的。

当然,对于这个定制能力,multus-cni做的显然还不够尽善尽美,希望看过这篇文章的朋友,可以思考这个问题,找出更好的解决方案,或者干脆全新开发一套为定制Pod网路而生的插件出来,相信一定会有人关注。

文末注:

另一个华为开发的多网路CNI插件:Huawei-PaaS/CNI-Genie[17]k8s多网卡规范:K8sNetworkPlumbingWG/multi-net-spec[18]关于Pod多网卡(定制网卡)的网路文章引用:多网路。 也许是 K8S 的「单 Pod 单 IP」的网路模型过于深入人心了,以至于在实现过程中都谨遵这一「金科玉律」。但我们知道,网路的世界纷繁复杂,一块网卡怎么可能 cover 所有场景呢?据最简单的例子,一般我们会为一个 IO 密集型的作业配两块网路,一块网卡作为数据信道,另一块网卡则作为控制信道。从单网路到多网路的迁移,道路并不平坦,甚至是处处荆棘和沼泽,且不说网路插件,Service,DNS,Ingress 等实现要大改,光 API 兼容性就让你头疼。好消息是经过整整两年的拉锯,社区 Network Plumbing WG终于取得了阶段性成果,如不出意外的话,应该是 CRD + 多网路插件的形式支持K8S的多网路,保持 K8S 原生 API 的稳定。支持多网路的 CNI 插件有几个,但真真落到生产的没几个,CNI-genie 是其中一个有众多粉丝基础和经过生产环境检验的 K8S 多网路插件,了解一下?引自:Kubernetes网路一年发展动态与未来趋势(下) - 掘金[19]pod多网路在HPC场景下,pod之间除了高性能网路之外,也可以有额外的网路,由此引入pod多网卡诉求,intel提供了一种解决方案multus(https://github.com/intel/multus-cni),该插件主要通过代理其它cni插件以实现,遵循k8s多网卡规范(https://github.com/K8sNetworkPlumbingWG/multi-net-spec)。利用multus插件,结合常规cni插件与SR-IOV cni插件,即可实现下图所示的pod网路

引自:Kubernetes与HPC:(1)RDMA网路[20]

参考

  1. ^https://zhuanlan.zhihu.com/p/67384482
  2. ^https://github.com/intel/multus-cni
  3. ^https://github.com/intel/multus-cni/blob/v3.2/README.md
  4. ^abhttps://github.com/intel/multus-cni/tree/v3.2
  5. ^https://docs.projectcalico.org/v3.8/introduction/
  6. ^https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#pod-network
  7. ^https://docs.projectcalico.org/v3.8/getting-started/kubernetes/installation/calico#installing-with-the-kubernetes-api-datastore50-nodes-or-less
  8. ^https://docs.projectcalico.org/v3.8/getting-started/calicoctl/install
  9. ^https://github.com/intel/multus-cni/blob/e723aabca8792ddd181167660e252a127a81b073/doc/quickstart.md#installation
  10. ^https://github.com/intel/multus-cni/blob/v3.2/doc/configuration.md
  11. ^abhttps://github.com/intel/multus-cni/blob/v3.2/doc/how-to-use.md#networkattachmentdefinition-with-cni-config-file
  12. ^https://docs.projectcalico.org/v3.8/reference/cni-plugin/configuration#cni-network-configuration-lists
  13. ^https://github.com/containernetworking/cni/blob/spec-v0.3.0/SPEC.md#network-configuration-lists
  14. ^https://github.com/intel/multus-cni/blob/v3.2/doc/configuration.md#specify-default-cluster-network-in-pod-annotations
  15. ^https://github.com/intel/multus-cni/blob/v3.2/doc/how-to-use.md#lauch-pod-with-text-annotation-for-networkattachmentdefinition-in-different-namespace
  16. ^https://github.com/intel/multus-cni/blob/v3.2/doc/how-to-use.md#lauch-pod-with-text-annotation-with-interface-name
  17. ^https://github.com/Huawei-PaaS/CNI-Genie
  18. ^https://github.com/K8sNetworkPlumbingWG/multi-net-spec
  19. ^https://juejin.im/post/5bd1bffd5188255ac26297b9
  20. ^https://www.meiwen.com.cn/subject/ckndaqtx.html

推荐阅读:

相关文章