3 分钟带你搞定 Kubernetes CNI 插件开发
本文介绍 CNI 插件调用的时机、CNI 插件配置的读取,以及 CNI 插件的调用、执行。读完此文,您将清楚 CNI 插件的运行机制、调用细节,并能够自信地写出一个简单的 CNI 插件。
- CRI:containerd
- CNI plugin:flannel
CNI 的调用时机
源码位置:containerd -
pkg/cri/server/service.go#L61
CRI 的RunPodSandbox()
实现中。
RunPodSandbox
的启动流程
- 生成 container id,名称;
- 确保 Infra 容器用的镜像存在,不存在的话就拉取;
- 确定 ociRuntime,比如 runC;
- 创建 Infra 容器将要托管的网络;
- 按照 ociRuntime 规范创建所要求的 spec;
- 生成 spec opts;
- 创建容器;
- 基于容器配置来创建 Task
- 启动 Task;
因此,Network Namespace 的创建,早于容器的创建。
CNI 配置文件的读取
源码位置:containerd -
pkg/cri/server/service.go#L149
先在 containerd 的配置文件中,配置 CNI 的配置路径,如下。
1 | [plugins."io.containerd.grpc.v1.cri".cni] |
在 containerd 启动时读取该目录下的配置文件,封装成一个网络插件,最终保存在 libcni
里。
1 | type libcni struct { |
libcni
中有个 Network
数组,通常这个数组有两个元素,最终分别用来设置 loopback
、eth0
这两个网卡。
总结一下这里的过程,可以概述为以下 3 点:
containerd 会读取
conf_dir
下的内容,生成默认的网络插件(还可以添加其他路径,来生成其他网络插件);如果
conf_dir
下面有N
个配置文件,会生成N + 1
个Network
;Network
会生成相应的网络设备,默认名称为eth0
、eth1
…。
CNI 配置文件示例 (flannel)
在 K8s 节点上的路径:/etc/cni/net.d/10-flannel.conflist
1 | { |
CNI 插件的调用
源码位置:containerd -
pkg/cri/server/sandbox_run.go#L377
总体流程
获取网络插件;
调用网络插件(
libcni
)的Setup()
方法。创建 namespace;
创建网络设备;
遍历所有的网络
Network
;- lo
- eth0
调用 CNI 接口
AddNetworkList
。遍历该
Network
中所有的Plugins
- flannel
- portmap
- 检查 plugin 是否存在。(默认:
/opt/cni/bin/{type}
) - 校验参数
- 执行插件命令。(环境变量
CNI_COMMAND
值为ADD
)
整理创建结果。
整理结果;
给 CNI 插件所传环境变量的分类:
CNI 保留字段
- CNI_COMMAND
- CNI_CONTAINERID
- CNI_NETNS
- CNI_ARGS
CNI 自定义参数
由 map 转成 string 后的字符串 - CNI_IFNAME
- CNI_PATH
CNI 自定义参数
调用 CNI 插件时,详细的传参如下:
1 | exec.ExecPlugin(ctx, pluginPath, netconf, args.AsEnv()) |
pluginPath
插件的完整路径;netconf
plugin 配置;args.AsEnv()
将所有上述环境变量转换成 key=value 后得到的数组。
CNI 插件的执行
插件作为二进制直接被调用,执行时,根据 CNI_COMMAND
取值不同,走不同的处理流程(由 switch
分发逻辑)。还有一套对这种操作的封装,只需提供 ADD
、DEL
、CHECK
的实现函数。
ADD
操作
总结为两个步骤:
- 填充
delegate
字段的参数;- 以填充后的
delegate
字段作为参数去调用其他的组件,来完成目标。
此时,插件拿到的网络配置数据
1 | { |
设置 delegate
将要调用的命令为 bridge
,插件填充完数据之后,得到的 delegate
字段如下:
1 | { |
调用其他组件来完成配置
1 | ExecPluginWithResult(ctx, pluginPath, netconf, delegateArgs("ADD"), realExec) |
3 分钟带你搞定 Kubernetes CNI 插件开发