k8s自定义CNI插件实现指南
自定义CNI插件实现指南
Kubernetes CNI(Container Network Interface)插件负责容器网络的配置和管理。以下是一个实现自定义CNI插件的详细指南,包含Demo代码。
基本概念
CNI插件是一个可执行文件,通过标准输入接收JSON格式的配置,并通过标准输出返回结果。插件需实现以下操作:
- ADD:容器创建时调用,配置网络
- DEL:容器删除时调用,清理网络
- CHECK(可选):检查网络配置
实现步骤
1. 创建CNI插件目录结构
CNI插件通常安装在/opt/cni/bin
目录。创建以下目录结构:
mkdir -p /opt/cni/bin
2. 编写CNI插件代码
以下是一个简单的Demo插件(Go语言实现),仅打印日志并返回成功响应:
package mainimport ("encoding/json""fmt""os""runtime"
)type NetConf struct {CNIVersion string `json:"cniVersion"`Name string `json:"name"`Type string `json:"type"`
}func main() {runtime.LockOSThread()var conf NetConfif err := json.NewDecoder(os.Stdin).Decode(&conf); err != nil {fmt.Fprintf(os.Stderr, "Error decoding config: %v\n", err)os.Exit(1)}switch os.Args[1] {case "ADD":fmt.Printf(`{"cniVersion": "%s","interfaces": [{"name": "eth0"}],"ips": [{"version": "4", "address": "10.0.0.2/24"}]}`, conf.CNIVersion)case "DEL":// 清理逻辑fmt.Printf(`{"cniVersion": "%s"}`, conf.CNIVersion)case "CHECK":fmt.Printf(`{"cniVersion": "%s"}`, conf.CNIVersion)default:fmt.Fprintf(os.Stderr, "Unknown command: %s\n", os.Args[1])os.Exit(1)}
}
3. 编译插件
编译上述代码并安装到CNI目录:
go build -o /opt/cni/bin/my-cni
chmod +x /opt/cni/bin/my-cni
4. 创建CNI配置文件
在/etc/cni/net.d/
目录下创建配置文件10-my-cni.conf
:
{"cniVersion": "0.4.0","name": "my-cni-network","type": "my-cni"
}
5. 测试插件
手动调用插件测试功能:
echo '{"cniVersion": "0.4.0", "name": "test", "type": "my-cni"}' | CNI_COMMAND=ADD CNI_CONTAINERID=test123 CNI_NETNS=/proc/self/ns/net CNI_IFNAME=eth0 CNI_PATH=/opt/cni/bin /opt/cni/bin/my-cni
高级功能扩展
网络配置传递
CNI插件可以通过环境变量获取Kubernetes传递的额外信息:
CNI_ARGS
: 自定义键值对参数K8S_POD_NAMESPACE
: Pod命名空间K8S_POD_NAME
: Pod名称
多插件支持
CNI支持插件链式调用。在配置中通过plugins
字段定义多个插件:
{"cniVersion": "0.4.0","name": "my-chain","plugins": [{"type": "my-cni"},{"type": "portmap"}]
}
IPAM集成
CNI插件通常与IPAM插件配合使用。以下是一个集成Host-local IPAM的配置示例:
{"cniVersion": "0.4.0","name": "my-cni-with-ipam","type": "my-cni","ipam": {"type": "host-local","subnet": "10.0.0.0/24"}
}
部署到Kubernetes
1. 创建DaemonSet部署插件
将编译好的插件打包到容器镜像中,通过DaemonSet部署到每个节点:
apiVersion: apps/v1
kind: DaemonSet
metadata:name: my-cni-plugin
spec:selector:matchLabels:name: my-cni-plugintemplate:metadata:labels:name: my-cni-pluginspec:hostNetwork: truecontainers:- name: my-cni-pluginimage: my-cni-imagevolumeMounts:- name: cni-binmountPath: /opt/cni/bin- name: cni-netmountPath: /etc/cni/net.dvolumes:- name: cni-binhostPath:path: /opt/cni/bin- name: cni-nethostPath:path: /etc/cni/net.d
2. 配置kubelet
确保kubelet参数包含以下CNI配置:
--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin
调试与验证
查看CNI日志
CNI插件日志通常通过stderr
输出,可通过以下方式查看:
journalctl -u kubelet | grep cni
手动调用验证
使用cnitool
工具手动测试插件功能:
CNI_PATH=/opt/cni/bin cnitool add my-cni-network /var/run/netns/test-ns
通过以上步骤可以实现一个基本的CNI插件,并根据需求扩展更多功能。实际生产环境中需要考虑网络性能、安全性和可靠性等更多因素。