flannel网络概述

**

flannel网络概述

**
flannel 是 CoreOS 开发的容器网络解决方案。flannel 为每个 host 分配一个 subnet(子网),容器从此 subnet 中分配 IP,这些 IP 可以在主机间路由,容器间无需 NAT 和 port mapping(端口映射) 就可以跨主机通信。

flannel的作用
因为flannel实现跨主机的子网通信是通过主机中的dr0网卡进行通信的,由flannel分配的子网都是从手动指定的一个大的子网中划分出来分配的。

flannel 会在每个主机上运行一个叫 flanneld 的代理。其职责就是从池子中分配 subnet。为了在各个主机间共享信息,flannel 用 etcd(与 consul 类似的 key-value 分布式数据库)存放网络配置、已分配的 subnet、host 的 IP 等信息。

数据包转发原理
数据包如何在主机间转发是由 backend 实现的。flannel 提供了多种 backend,最常用的有 vxlan 和 host-gw

其他 backend 请参考 https://github.com/coreos/flannel

跨主机容器网络通信实现工具
Docker跨主机容器间网络通信实现的工具有pipework、flannel、weave、open vswitch(虚拟交换机)、calico

其中flannel和weave的区别是:

weave的思路
在每个宿主机上布置一个特殊的route的容器,不同宿主机的route容器连接起来。 route拦截所有普通容器的ip请求,并通过udp包发送到其他宿主机上的普通容器。这样在跨机的多个容器端看到的就是同一个扁平网络。 weave解决了网络问题,不过部署依然是单机的。不是跨主机的。

flannel的思路
flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,也就是说使用k8s一般都会使用flannel。简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。也就是前面说过的指定一个大的网段来划分子网,所有的容器ip都包含在大网段之内,所以可以进行通信,而ip不重复。最终可以通过内网ip桥接到dr0与外网通信

flannel实质上是一种”覆盖网络(overlay network)”,即表示运行在一个网上的网(应用层网络),并不依靠ip地址来传递消息,而是采用一种映射机制,把ip地址和identifiers(标识符)做映射来资源定位。也就是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持UDP、VxLAN、AWS VPC和GCE路由等数据转发方式。

flannel 使用etcd存储配置数据和子网分配信息。flannel 启动之后,后台进程首先检索配置和正在使用的子网列表,然后选择一个可用的子网,然后尝试去注册它。etcd也存储这个每个主机对应的ip。flannel 使用etcd的watch机制监视/coreos.com/network/subnets下面所有元素的变化信息,并且根据它来维护一个大路由表,在flannel网络中只有这一个路由表。为了提高性能,flannel优化了Universal TAP/TUN设备,对TUN和UDP之间的ip分片做了代理。

如果将TCP数据包封装在UDP包中,他们的MTU(最大传输单元)值是不同的,也就是说发送的每个数据包的大小是不同的,TCP为1500,UDP为1450。

flannel工作原理
每个主机配置一个ip段和子网个数。例如,可以配置一个覆盖网络使用 10.100.0.0/16段,每个主机/24个子网。因此主机a可以接受10.100.5.0/24,主机B可以接受10.100.18.0/24的包。flannel使用etcd来维护分配的子网到实际的ip地址之间的映射。

对于数据路径,flannel 使用udp来封装ip数据报,转发到远程主机。选择UDP作为转发协议是因为他能穿透防火墙。例如,AWS Classic无法转发IPoIP or GRE 网络包。是因为它的安全组仅仅支持TCP/UDP/ICMP

Flannel工作原理流程图如下 (默认的节点间数据通信方式是UDP转发; flannel默认使用8285端口作为UDP封装报文的端口,VxLan使用8472端口

flannel工作原理
在这里插入图片描述

如图所示中

为flanneld指定了ip地址池后,如:10.10.0.0/16,并指定每台主机以/24的子网掩码来划分子网,当启动了flanneld服务之后,集群中每台物理机会生成一个flannel.1的网卡,且网段为已经分配好的网段,如图中所示,且在主机路由也会出现该地址池的路由条目,来自该地址池中的ip都会通过flannel.1网卡来转发数据包。

然后将docker0与flannel.1通过在docker启动项里面增加bip和mtu的方式,使得子网网段由docker0来转发,也就是docker0作为了子网的网关,如图docker0所示

此时如果1.12的容器要去与1.13的容器进行互发ping包测试,容器中的ip会通过docker0的桥接到flannel.1来转发ping包,并由flanneld服务对数据包进行UDP封装,根据路由表发送到1.13的flanneld服务解封装,再次由目的主机的docker0桥接转发到目标容器中实现互通。

flanneld中管理了一张大的路由表,里面存储了整个集群中使用了由他分配的ip的路由条目及网段信息等等。