Flannel 之所以可以搭建 Kubernetes 依赖的底层网络,是因为它能实现以下两点:
(1) 它能协助 Kubernetes, 给每 一 个 Node 上的 Docker 容器都分配互不冲突的 IP 地址 。
(2) 它能在这些 IP 地址之间建立一个覆盖网络 (Overlay Network) ,通过这个覆盖网络,将数据包原封不动地传递到目标容器内 。
下图展示了 Flannel 是如何实现这两点的。
Flannel 首先创建了一个名为 flanne0 的网桥,这个网桥的一端连接 docker0 网桥,另一端连接一个叫作 flanneld 的服务进程 。
flanneld 进程并不简单,它上连 etcd, 利用 etcd 来管理可分配的 IP 地址段资源 ,同时监控 etcd 中每个 Pod 的实际地址,并在内存中建立了一个 Pod 节点路由表;它下连 docker0 和物理网络,使用内存中的 Pod 节点路由表,将 docker0 发给它的数据包包装起来,利用物理网络的连接将数据包投递到目标 flanneld 上,从而完成 Pod 到 Pod 之间的直接地址通信 。
Flannel 之间底层通信协议的可选技术包括 UDP 、 VxLan 、 AWS VPC 等多种方式 。通过源 flanneld 封包、目标 flanneld 解包, docker0 最终收到的就是原始数据,对容器应用来说是透明的,应用感觉不到中间 Flannel 的存在 。
Flannel 完美地实现了对 Kubernetes 网络的支持,但是它引入了多个网络组件,在网络通信时需要转到 flannel0 网络接口,再转到用户态的 flanneld 程序,到对端后还需要走这个过程的反过程,所以也会引入一些网络的时延损耗 。
另外, Flannel 模型默认采用了 UDP 作为底层传输协议, UDP 本身是非可靠协议,虽然两端的 TCP 实现了可靠传输,但在大流量 、高并发的应用场景下还需要反复测试,确保没有问题。