这里主要研究 flannel-vxlan ,flannel-vxlan 是 overlay 类型的网络。本次实操无需安装 Kubernetes,直接调用插件来配置容器网络。
CNI 插件的本质工作有两个:
- 工作一:配置容器网络命名空间的网络
- 工作二:路由各个网络命名空间的网络流量
工作一需要实现 CNI 相关的接口,从而可以通过外部对插件进行调用。工作二常常需要额外的守护进程来完成,在 Kubernetes 中一般以 DaemonSet 的形式部署,同时以 Kubernetes 的 etcd 作为数据存储的后端。
环境介绍
- 节点0,10.211.55.2(用于部署 etcd)
- 节点1,10.211.55.32
- 节点2,10.211.55.57
事前准备
在节点0上部署 etcd 为网络插件提供存储服务,这里使用 Docker 部署,暴露端口为 2379,相关官网教程见 https://etcd.io/docs/v3.4/op-guide/container/ ,启动参数见 https://etcd.io/docs/v3.4/op-guide/configuration/。
1 | docker run -p 2379:2379 quay.io/coreos/etcd:v3.3.1 /usr/local/bin/etcd --advertise-client-urls http://10.211.55.2:2379 --listen-client-urls http://0.0.0.0:2379 |
安装 etcdctl 工具,相关教程见 https://gist.github.com/sanjid133/fffaae1c7deb7c3d6c5f6bae549d6380,当然,也可以使用 docker exec 登录到 etcd 容器中使用它自带的 etcdctl。
安装 cni 基础网络插件至 /opt/cni/bin 下,插件仓库在 https://github.com/containernetworking/plugins 上,直接下载编译好的 release https://github.com/containernetworking/plugins/releases 然后解压到 /opt/cni/bin 下即可。
直接使用 https://www.cni.dev/docs/cnitool/ 或者自己编写如下程序调用 CNI 插件,这里采用第二种方式,该程序最终会被编译为 cnidemo
1 | package main |
flannel-vxlan
flannel 网络插件分为两个部分,第一部分为 https://github.com/containernetworking/plugins 自带的 flannel ,用于完成工作一,通过调用 bridge 插件完成对容器命名空间网络的配置,而 https://github.com/flannel-io/flannel 用于完成工作二,使用 vxlan 实现容器跨节点通信。
手动部署的官网文件见 https://github.com/flannel-io/flannel/blob/master/Documentation/running.md
首先,利用 etcdctl 向 etcd 中添加相关的网络配置,注意这里使用的 etcd api 版本为 v2。
1 | etcdctl --endpoints=http://10.211.55.2:2379 set /coreos.com/network/config '{ "Network": "10.5.0.0/16", "Backend": {"Type": "vxlan"}}' |
在节点1和节点2上下载 https://github.com/flannel-io/flannel/releases 二进制程序并启动。
1 | ./flanneld-amd64 -etcd-endpoints http://10.211.55.2:2379 |
在节点1和节点2的 /etc/cni/net.d/ 下编写 flannel 配置文件 11-flannel.conf。此处的配置信息参考 https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml 中 ConfigMap 的 cni-conf.json 部分。
1 | { |
在 节点1 和 节点2 上分别创建网络命名空间 ns-2,ns-3。
1 | ip netns add ns-x |
使用自己编写的 cnidemo 调用 flannel 插件来配置 ns-2,ns-3。
1 | # 节点1 |
程序会输出容器网络命名空间的 ip ,我这里是 10.5.67.4 和 10.5.7.2。可以在 ns-2 中启动一个 http server,在 ns-3 中测试是否可以访问。如果可以成功访问,则表示 flannel 网络插件正常运行了。
1 | # 节点1 |
分析
flannel 利用 etcd 来对数据进行存取,利用 etcdctl 插件它在 etcd 中存储的数据。
1 | etcdctl --endpoints=http://10.211.55.2:2379 ls /coreos.com/network |
输出如下:
1 | /coreos.com/network/config |
第一个就是之前配置的内容,这里查看第二个 key 的数据:
1 | etcdctl --endpoints=http://10.211.55.2:2379 ls /coreos.com/network/subnets |
输出如下:
1 | /coreos.com/network/subnets/10.5.67.0-24 |
可以看出,这是当前两个节点在容器网络中的子网信息,挑选第一个进行查看:
1 | etcdctl --endpoints=http://10.211.55.2:2379 get /coreos.com/network/subnets/10.5.67.0-24 |
输出如下:
1 | {"PublicIP":"10.211.55.32","BackendType":"vxlan","BackendData":{"VtepMAC":"92:3a:42:4a:9a:a9"}} |
由于 vxlan 构建的是一个二层 overlay 网络,所以这里 BackendData 数据记录的是 flannel 守护进程创建的网卡 flannel.1 的物理 MAC 地址。这个 flannel.1 是 VTEP(VXLAN Tunnel Endpoints),输入命令查看其相关信息:
1 | ip -d link show flannel.1 |
输出如下:
1 | flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default |
在另一个节点节点2上查看转发表:
1 | bridge fdb show dev flannel.1 |
输出如下:
1 | 92:3a:42:4a:9a:a9 dst 10.211.55.32 self permanent |