一、 原理简介
关于 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/bin
2.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"
}
EOF
2.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 网络的调用原理了。