Flannel 是一个非常简单的 overlay 网络(VXLAN),是 Kubernetes 网络 CNI 的解决方案之一。Flannel 在每台主机上运行一个简单的轻量级 agentflanneld来监听集群中节点的变更,并对地址空间进行预配置。Flannel 还会在每台主机上安装 vtepflannel.1(VXLAN tunnel endpoints),与其他主机通过 VXLAN 隧道相连。
(相关资料图)
flanneld 监听在8472端口,通过 UDP 与其他节点的 vtep 进行数据传输。到达 vtep 的二层包会被原封不动地通过 UDP 的方式发送到对端的 vtep,然后拆出二层包进行处理。简单说就是用四层的 UDP 传输二层的数据帧。
vxlan-tunnel
在 Kubernetes 发行版K3S[1]中将 Flannel 作为默认的 CNI 实现。K3S 集成了 flannel,在启动后 flannel 以 go routine 的方式运行。
环境搭建Kubernetes 集群使用 k3s 发行版,但在安装集群的时候,禁用 k3s 集成的 flannel,使用独立安装的 flannel 进行验证。
安装 CNI 的 plugin,需要在所有的 node 节点上执行下面的命令,下载 CNI 的官方 bin。
sudo mkdir -p /opt/cni/bincurl -sSL https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz | sudo tar -zxf - -C /opt/cni/bin
安装 k3s 的控制平面。
export INSTALL_K3S_VERSION=v1.23.8+k3s2curl -sfL https://get.k3s.io | sh -s - --disable traefik --flannel-backend=none --write-kubeconfig-mode 644 --write-kubeconfig ~/.kube/config
安装 Flannel。这里注意,Flannel 默认的 Pod CIRD 是10.244.0.0/16,我们将其修改为 k3s 默认的10.42.0.0/16。
curl -s https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml | sed "s|10.244.0.0/16|10.42.0.0/16|g" | kubectl apply -f -
添加另一个节点到集群。
export INSTALL_K3S_VERSION=v1.23.8+k3s2export MASTER_IP= 查看节点状态。 kubectl get nodeNAME STATUS ROLES AGE VERSIONubuntu-dev3 Ready 运行两个 pod:curl和httpbin,为了探寻 NODE1=ubuntu-dev2NODE2=ubuntu-dev3kubectl apply -n default -f - < 接下来,一起看下 CNI 插件如何配置 pod 网络。 初始化 Flannel 是通过Daemonset的方式部署的,每台节点上都会运行一个 flannel 的 pod。通过挂载本地磁盘的方式,在 Pod 启动时会通过初始化容器将二进制文件和 CNI 的配置复制到本地磁盘中,分别位于/opt/cni/bin/flannel和/etc/cni/net.d/10-flannel.conflist。 通过查看kube-flannel.yml[2]中的ConfigMap,可以找到 CNI 配置,flannel 默认委托(见flannel-cni 源码 `flannel_linux.go#L78`[3])给bridge 插件[4]进行网络配置,网络名称为cbr0;IP 地址的管理,默认委托(见flannel-cni 源码 `flannel_linux.go#L40`[5])host-local 插件[6]完成。 #cni-conf.json 复制到 /etc/cni/net.d/10-flannel.conflist{ "name": "cbr0", "cniVersion": "0.3.1", "plugins": [ { "type": "flannel", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true } } ]} 还有 Flannel 的网络配置,配置中有我们设置的 Pod CIDR10.42.0.0/16以及后端(backend)的类型vxlan。这也是 flannel 默认的类型,此外还有多种后端类型[7]可选,如host-gw、wireguard、udp、Alloc、IPIP、IPSec。 #net-conf.json 挂载到 pod 的 /etc/kube-flannel/net-conf.json{ "Network": "10.42.0.0/16", "Backend": { "Type": "vxlan" }} Flannel Pod 运行启动flanneld进程,指定了参数--ip-masq和--kube-subnet-mgr,后者开启了kube subnet manager模式。 集群初始化时使用了默认的 Pod CIDR10.42.0.0/16,当有节点加入集群,集群会从该网段上为节点分配属于节点的 Pod CIDR10.42.X.1/24。 flannel 在kube subnet manager模式下,连接到 apiserver 监听节点更新的事件,从节点信息中获取节点的 Pod CIDR。 kubectl get no ubuntu-dev2 -o jsnotallow={.spec} | jq{ "podCIDR": "10.42.0.0/24", "podCIDRs": [ "10.42.0.0/24" ], "providerID": "k3s://ubuntu-dev2"} 然后在主机上写子网配置文件,下面展示的是其中一个节点的子网配置文件的内容。另一个节点的内容差异在FLANNEL_SUBNET=10.42.1.1/24,使用的是对应节点的 Pod CIDR。 #node 192.168.1.12cat /run/flannel/subnet.envFLANNEL_NETWORK=10.42.0.0/16FLANNEL_SUBNET=10.42.0.1/24FLANNEL_MTU=1450FLANNEL_IPMASQ=trueCNI 插件执行 CNI 插件的执行是由容器运行时触发的,具体细节可以看上一篇《源码解析:从 kubelet、容器运行时看 CNI 的使用》。 Flannel Plugin Flow flannelCNI 插件(/opt/cni/bin/flannel)执行的时候,接收传入的cni-conf.json,读取上面初始化好的subnet.env的配置,输出结果,委托给bridge进行下一步。 cat /var/lib/cni/flannel/e4239ab2706ed9191543a5c7f1ef06fc1f0a56346b0c3f2c742d52607ea271f0 | jq{ "cniVersion": "0.3.1", "hairpinMode": true, "ipMasq": false, "ipam": { "ranges": [ [ { "subnet": "10.42.0.0/24" } ] ], "routes": [ { "dst": "10.42.0.0/16" } ], "type": "host-local" }, "isDefaultGateway": true, "isGateway": true, "mtu": 1450, "name": "cbr0", "type": "bridge"}bridge 插件 bridge使用上面的输出连同参数一起作为输入,根据配置完成如下操作: 最后输出如下的结果: cat /var/li/cni/results/cbr0-a34bb3dc268e99e6e1ef83c732f5619ca89924b646766d1ef352de90dbd1c750-eth0 | jq .result{ "cniVersion": "0.3.1", "dns": {}, "interfaces": [ { "mac": "6a:0f:94:28:9b:e7", "name": "cni0" }, { "mac": "ca:b4:a9:83:0f:d4", "name": "veth38b50fb4" }, { "mac": "0a:01:c5:6f:57:67", "name": "eth0", "sandbox": "/var/run/netns/cni-44bb41bd-7c41-4860-3c55-4323bc279628" } ], "ips": [ { "address": "10.42.0.5/24", "gateway": "10.42.0.1", "interface": 2, "version": "4" } ], "routes": [ { "dst": "10.42.0.0/16" }, { "dst": "0.0.0.0/0", "gw": "10.42.0.1" } ]} port-mapping 插件 该插件会将来自主机上一个或多个端口的流量转发到容器。 让我们在第一个节点上,使用tcpdump对接口cni0进行抓包。 tcpdump -i cni0 port 80 -vvv 从 podcurl中使用 podhttpbin的 IP 地址10.42.1.2发送请求: kubectl exec curl -n default -- curl -s 10.42.1.2/get cni0 从在cni0上的抓包结果来看,第三层的 IP 地址均为 Pod 的 IP 地址,看起来就像是两个 pod 都在同一个网段。 tcpdump-on-cni0 host eth0 文章开头提到 flanneld 监听 udp 8472 端口。 netstat -tupln | grep 8472udp 0 0 0.0.0.0:8472 0.0.0.0:* - 我们直接在以太网接口上抓取 UDP 的包: tcpdump -i eth0 port 8472 -vvv 再次发送请求,可以看到抓取到 UDP 数据包,传输的负载是二层的封包。 tcpdump-on-host-eth0 在系列的第一篇中,我们研究 pod 间的通信时提到不同 CNI 插件的处理方式不同,这次我们探索了 flannel 插件的工作原理。希望通过下面的图可以对 overlay 网络处理跨节点的网络通信有个比较直观的认识。 当发送到10.42.1.2流量到达节点 A 的网桥cni0,由于目标 IP 并不属于当前阶段的网段。根据系统的路由规则,进入到接口flannel.1,也就是 VXLAN 的 vtep。这里的路由规则也由flanneld来维护,当节点上线或者下线时,都会更新路由规则。 #192.168.1.12Destination Gateway Genmask Flags Metric Ref Use Ifacedefault _gateway 0.0.0.0 UG 0 0 0 eth010.42.0.0 0.0.0.0 255.255.255.0 U 0 0 0 cni010.42.1.0 10.42.1.0 255.255.255.0 UG 0 0 0 flannel.1192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0#192.168.1.13Destination Gateway Genmask Flags Metric Ref Use Ifacedefault _gateway 0.0.0.0 UG 0 0 0 eth010.42.0.0 10.42.0.0 255.255.255.0 UG 0 0 0 flannel.110.42.1.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 flannel.1将原始的以太封包使用 UDP 协议重新封装,将其发送到目标地址10.42.1.0(目标的 MAC 地址通过 ARP 获取)。对端的 vtep 也就是flannel.1的 UDP 端口 8472 收到消息,解帧出以太封包,然后对以太封包进行路由处理,发送到接口cni0,最终到达目标 pod 中。 响应的数据传输与请求的处理也是类似,只是源地址和目的地址调换。 [1]K3S:https://k3s.io/ [2]kube-flannel.yml:https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml [3]flannel-cni 源码flannel_linux.go#L78:https://github.com/flannel-io/cni-plugin/blob/v1.1.0/flannel_linux.go#L78 [4]bridge 插件:https://www.cni.dev/plugins/current/main/bridge/ [5]flannel-cni 源码flannel_linux.go#L40:https://github.com/flannel-io/cni-plugin/blob/v1.1.0/flannel_linux.go#L40 [6]host-local 插件:https://www.cni.dev/plugins/current/ipam/host-local/ [7]多种后端类型:https://github.com/flannel-io/flannel/blob/master/Documentation/backends.md
X 关闭
X 关闭
- 15G资费不大降!三大运营商谁提供的5G网速最快?中国信通院给出答案
- 2联想拯救者Y70发布最新预告:售价2970元起 迄今最便宜的骁龙8+旗舰
- 3亚马逊开始大规模推广掌纹支付技术 顾客可使用“挥手付”结账
- 4现代和起亚上半年出口20万辆新能源汽车同比增长30.6%
- 5如何让居民5分钟使用到各种设施?沙特“线性城市”来了
- 6AMD实现连续8个季度的增长 季度营收首次突破60亿美元利润更是翻倍
- 7转转集团发布2022年二季度手机行情报告:二手市场“飘香”
- 8充电宝100Wh等于多少毫安?铁路旅客禁止、限制携带和托运物品目录
- 9好消息!京东与腾讯续签三年战略合作协议 加强技术创新与供应链服务
- 10名创优品拟通过香港IPO全球发售4100万股 全球发售所得款项有什么用处?