背景
当前社区支持多个cni插件,当前集群底层网络实现变化后存在切换CNI插件的需求。由于cni插件主要在pod网卡创建和删除流程中使用,切换CNI插件后,要求pod重建,服务和网络都会中断
这里需要一种更加平滑的切换方式,在保证页面和网络不中断的情况下切换CNI
架构
上图可以看到,一个pod可以同时有多个网卡,其中eth0是默认网卡,也就是默认路由指向的网卡
net0和net1是通过在pod的annotation中指定的网络创建的网卡
这里通过创建pod来看multus-cni的实现方法:
- multus-cni实际是一个CNI插件,实现的接口也是CmdAdd CmdCheck CmdDel,这里通过提供CRD:NetworkAttachmentDefinition来定义其他CNI插件的内容,格式见下文
- 在kubelet调用cni创建网卡时,multus-cni会通过查询pod annotation定义的key获取是否有指定使用的cni插件,并通过调用k8s api获取crd的具体数据
- 将指定的pod和crd中定义的cni数据进行处理,最终得到符合CNI规范的格式,这个配置实际是保存在内存中的
- 调用cni提供的AddNetwork方法,将内存中第三方的cni配置作为参数传递过去(默认网络在内存中也是一种CNI配置)
- 最终实现动态创建POD网卡
annotations key:
- k8s.v1.cni.cncf.io/resourceName:创建网络CRD时指定的资源名称,一般用来指定底层物理设备的名称,比如sriov场景
- v1.multus-cni.io/default-network:配置pod的默认网络,只能配置一个。用来替换k8s集群中原来默认的网络
- k8s.v1.cni.cncf.io/networks:配置pod的网络,支持配置多个
注意:
- 这里的网络是指通过multus crd建出来的network-attachment-definition对象
- 指定网络时支持指定ip、mac、ifname、qos、portmap、gateway、device id
- 默认路由对应的网卡名称不支持指定
部署
1
2
3
git clone https://github.com/k8snetworkplumbingwg/multus-cni.git
cd multus-cni
kubectl apply -f images/multus-daemonset.yml
打包
编译可执行文件
1
2
cd multus-cni
./build
打包镜像,使用分支:release-3.7
1
2
3
cd multus-cni
docker build --file ./Dockerfile -t harbor.huayun.org/huayun-kubernetes/multus-cni:dev .
docker push harbor.huayun.org/huayun-kubernetes/multus-cni:dev
功能验证
创建macvlan NetworkAttachmentDefinition
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: macvlan-conf
spec:
config: '{
"cniVersion": "0.3.0",
"type": "macvlan",
"master": "ens192",
"mode": "bridge",
"ipam": {
"type": "host-local",
"subnet": "192.168.1.0/24",
"rangeStart": "192.168.1.200",
"rangeEnd": "192.168.1.216",
"routes": [
{ "dst": "0.0.0.0/0" }
],
"gateway": "192.168.1.1"
}
}'
创建pod并指定使用macvlan cni
1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Pod
metadata:
name: samplepod
annotations:
k8s.v1.cni.cncf.io/networks: macvlan-conf
spec:
containers:
- name: samplepod
command: ["/bin/ash", "-c", "trap : TERM INT; sleep infinity & wait"]
image: alpine
查看pod中网卡创建情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@node1 multus]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 213 8d 10.244.1.12 node2 <none> <none>
samplepod 1/1 Running 0 8s 10.244.2.22 node3 <none> <none>
[root@node1 multus]# kubectl exec -it samplepod -- 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@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1440 qdisc noqueue state UP
link/ether a2:3e:de:3e:fd:d0 brd ff:ff:ff:ff:ff:ff
inet 10.244.2.22/32 scope global eth0
valid_lft forever preferred_lft forever
5: net1@if14: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 32:b2:70:77:50:df brd ff:ff:ff:ff:ff:ff
inet 192.168.1.201/24 brd 192.168.1.255 scope global net1
valid_lft forever preferred_lft forever
总结
优点
- 创建pod时支持指定多种cni
- pod中存在多种cni的网卡,默认路由使用默认网络的
缺点
- 不支持更新,pod如果已经创建,不支持动态创建其他cni的网卡
查看代码发现multus实际也是走的CNI的流程,实现CmdAdd和CmdDelete接口 也就是说在pod创建完成后,CNI是不响应增加和删除网卡操作的,只响应创建和删除POD的操作