深入理解 k8s 的 CNI 网络
从 0 实现一个 CNI 网络插件
// 在 /etc/cni/net.d/ 目录下新建个 .conf 结尾的文件, 输入以下配置项
{
"cniVersion": "0.3.0",
"name": "testcni",
"type": "testcni",
"bridge": "testcni0",
"subnet": "10.244.0.0/16"
}
- 把 /etcd/client.go 下的用来初始化 etcd 客户端的 ip 地址改成自己集群的 etcd 地址
- go build main.go
- mv main /opt/cni/bin/testcni
- 每台主机上都重复以上三步
- kubectl apply -f test-busybox.yaml
- 查看集群 pod 状态
- 可通过 /test 目录下的 main_test.go 进行测试
- 测试之前先 ip netns add test.net.1 创建一个命令空间
- 然后 go test ./test/main_test.go -v
- 之后在另外的节点上也执行同样的步骤
- ip netns exec test.net.1 ping 另外一台节点上的 ns 下的网卡 ip
- 切换到 test/cni-test 分支
- 进入到 ./cnitool 目录
- go build cnitool.go
- ip netns add test.net.1 创建一个 net ns
- 在 /etc/cni/net.d/ 目录下创建和上面一样的配置
- ./cnitool add testcni /run/netns/test.net.1
- journalctl -xeu kubelet -f 通过命令查看 kubelet 日志
- 在 ./utils/write_log.go 文件中修改 log 输出地址, 关键的报错信息会自动打到这个地址中
- 如果明明编译完的 main.go 已经被拷贝到 /opt/cni/bin/testcni 了但是 kubelet 还报错什么类似 "找不到" 之类的, 尝试看看给环境变量添加 "export CNI_PATH=/opt/cni/bin"
- 如果 kubelet 日志显示什么 "配置文件有非法字符" 之类的, 检查所有代码中是否出现过使用 fmt 直接往标准输出中输出了什么日志. cni 通过标准输出读取配置, 所以一旦有任何非配置相关的信息被输出, 则一定会 gg
- 当前是直接把 etcd 地址写死在代码里了, 可更改为动态替换
- 有些需要获取集群信息的地方是直接通过 etcd 裸读出来的, 最好改成通过连接 api-server 读
- 当前为主机路由模式, 之后有时间研究研究 vxlan 模式
- 还没实现 del, 目前需要手动删一些资源以及 etcd 释放
- ipam 当前是直接裸读的 etcd, 更好的方法是创建 crd
- 当前是直接手动把编译后的二进制干到 /opt/cni/bin 下, 更好的方法应该是通过 daemonset 把二进制和配置拷贝到对应路径