Flannel之所以可以搭建k8s依赖的底层网络,是因为它能实现以下两点。
(1)它能协助Kubernetes,给每一个Node上的Docker容器都分配互不冲突的IP地址。
(2)它能在这些IP地址之间建立一个覆盖网络(OverlayNetwork),通过这个覆盖网络,将数据包原封不动地传递到目标容器内。
通过下图看看Flannel是如何实现这两点的。
![](https://img.haomeiwen.com/i24834454/d4e0e61036008935.jpeg)
可以看到,Flannel首先创建了一个名为flannel0的网桥,而且这个网桥的一端连接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是如何做到为不同Node上的Pod分配IP而不产生冲突的。其实想到Flannel使用了集中的etcd存储就很容易理解了。它每次分配的地址段都在同一个公共区域获取,这样大家自然能够相互协调,不产生冲突了。而且在Flannel分配好地址段后,后面的事情是由Docker完成的,Flannel通过修改Docker的启动参数将分配给它的地址段传递进去:
--bip=172.17.18.1/24
通过这些操作,Flannel就控制了每个Node上的docker0地址段的地址,也就保障了所有Pod的IP地址都在同一个水平网络中且不产生冲突了。
Flannel完美地实现了对Kubernetes网络的支持,但是它引入了多个网络组件,在网络通信时需要转到flannel0网络接口,再转到用户态的flanneld程序,到对端后还需要走这个过程的反过程,所以也会引入一些网络的时延损耗。
另外,Flannel模型默认采用了UDP作为底层传输协议,UDP本身是非可靠协议,虽然两端的TCP实现了可靠传输,但在大流量、高并发的应用场景下还需要反复测试,确保没有问题。
网友评论