一、 原理简介
关于 Kubernetes 网络插件,要从其初始化配置讲起,
即 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf ,
该配置文件定义了 Kubernetes 系统启用的网络模式,默认网络参数是:
--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin
--network-plugin=cni 表明 k8s 使用实现标准CNI (容器网络接口)的网络插件
--cni-conf-dir=/etc/cni/net.d 是存放 CNI 网络插件配置信息的文件夹路径
--cni-bin-dir=/opt/cni/bin 是存放 CNI 网络插件可执行文件的文件夹路径
当 k8s 需要操作网络时(如创建网络),会通过 cni-conf-dir 中的配置信息,
去 cni-bin-dir 中寻找命令文件并执行相关命令
该命令文件的接收参数与返回值遵循 CNI 接口规范,达到统一接口的效果,下边我们通过实例进行验证。
二、 示例验证
2.1 开发环境
Ubuntu 16.04 LTS ,Docker 1.12.6, Golang 1.9.2
2.2 下载和编译 CNI Plugin
CNI Plugin 是 CNI 官方提供的一些网络操作命令集合,是 CNI 插件工作的基础
# cd $GOPATH/src # git clone https://github.com/containernetworking/plugins.git # cd plugins # ./build.sh # cp ./bin/* /opt/cni/bin2.3 编写 CNI 配置信息
# mkdir -p /etc/cni/net.d # cat >/etc/cni/net.d/10-mynet.conf <<EOF { "cniVersion": "0.2.0", "name": "mynet", "type": "bridge", "bridge": "cni0", "isGateway": true, "ipMasq": true, "ipam": { "type": "host-local", "subnet": "10.22.0.0/16", "routes": [ { "dst": "0.0.0.0/0" } ] } } EOF # cat >/etc/cni/net.d/99-loopback.conf <<EOF { "cniVersion": "0.2.0", "type": "loopback" } EOF2.4 运行容器测试
为了让 Docker 使用 CNI 网络,CNI 官方提供了相关脚本,我们通过该脚本运行容器
注意,需要通过环境变量告知脚本 CNI 配置文件和执行命令的路径
# cd $GOPATH/src # git clone https://github.com/containernetworking/cni.git # cd cni/scripts # export CNI_PATH=/opt/cni/bin/ # export NETCONFPATH=/etc/cni/net.d # ./docker-run.sh --rm busybox ifconfig | grep -Pi "(eth0|lo|inet addr)"
可以看到,docker 容器的网络地址是我们配置的 CNI 网络 10.22.0.0/16(这里底层直接使用的 bridge)
2.5 我们可以使用自己编写的 CNI 脚本插件,来查看容器启动和结束时向 CNI 插件到底传递了什么信息
首先,删除之前的 CNI 配置文件
# rm -f /etc/cni/net.d/*conf然后,编写新的 CNI 配置文件
# cat >/etc/cni/net.d/10-mynet.conf <<EOF { "cniVersion": "0.2.0", "name": "my_dummy_network", "type": "dummy" } EOF编写,CNI 执行脚本 (注意,信息的接收既包含环境变量方式,也包含标准输入方式,即参数接收有两个途径)
# cat >/opt/cni/bin/dummy <<EOF #!/bin/bash logit () { >&2 echo \$1 } logit "CNI method: \$CNI_COMMAND" logit "CNI container id: \$CNI_CONTAINERID" logit "-------------- Begin config" while read line do logit "\$line" done < /dev/stdin logit "-------------- End config" EOF
# chmod 0755 /opt/cni/bin/dummy测试,查看 CNI 调用情况
# cd $GOPATH/src/cni/scripts # ./docker-run.sh --rm busybox ifconfig
可以看到,方法分别执行了 ADD(增加网络) DEL(移除网络),同时传入了容器 ID 等网络相关信息,
CNI 插件根据这些信息执行实际的任务,这就是 CNI 网络的调用原理了。