前言

现在不管出现什么新技术、新框架,那有2个问题是大家都绕不开的,包括操作系统在内也绕不开这2个问题,而且是非常基础的问题——网络存储
回想以下以前学习过的框架,回想以下操作系统原理,是不是都不可能绕开这两点?这两点是所有程序的基础,同时也是Docker要解决的重点问题。今天我们就一起来学习下Docker的网络解决方案。

Docker中的网络解决方案

Docker中,网络问题主要有3种解决方案。如下:

  • Flannel
  • Weave
  • Calico

它们的目的无非就是为了解决同一个问题:如何让容器之间互相通信?这个问题再升级以下,放在kubernetes集群来看,它解决的也是同一个问题。不过在kubernetes中,它有一些约束,所有的网络实现都要遵循CNI标准(由kubernetes定义的标准,方便社区或公司进行扩展)。CNI规范总结起来可归纳成约法三章四大目标。如下:

约法三章:

  • podpod直接通信,无需显示使用NAT
  • nodepod直接通信,无需显示使用NAT
  • pod可见IP地址确为其它pod与其通信时所有,无需显示转换

四大目标:

  • 容器与容器的通信
  • podpod之间的通信
  • podservice之间的通信
  • 外部与service之间的通信

还有,一般各大云平台都会结合自己的网络方案实现一种解决方案,现在先不管这些。下面我们就来一一学习下上面提到的3中解决方案。

Flannel

flannel是由coreos团队开发,设计之初就是为了解决集群中所有节点重新规划ip地址的使用规则,从而使得不同节点上的容器能获得同一个内网不重复的IP地址,并且属于不同节点上的容器能够直接通过内网IP通信!

整体架构如下:

docker KAFKA_ADVERTISED_LISTENERS 配置 docker calico_weave

  • Flannel 使用etcd存储配置数据和子网分配信息。flannel 启动之后,后台进程首先检索配置和正在使用的子网列表,然后选择一个可用的子网,然后尝试去注册它。etcd也存储这个每个主机对应的ipflannel使用etcdwatch机制监视/coreos.com/network/subnets下面所有元素的变化信息,并且根据它来维护一个路由表。
  • 每个主机配置一个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协议是因为它能穿透防火墙。

一次完整的通信过程如下

  1. 数据包由源容器发出,经过docker0转发至flannel0
  2. flanneld监听到此数据包之后,解析到数据包应该发送给哪个flanneld?然后源flanneldetcd里查询该目的地址的路由信息
  3. 源主机的flanneld再将数据包使用UDP协议进行封装,然后根据路由表将数据包投递给对端flanneld
  4. 对端flanneld收到数据包,解包发送到flannel0网卡,接着再转发到docker0网卡
  5. 最后由docker0路由到最终容器

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

Weave

weave是由weaveworks公司开发的,其目的是要解决Docker跨主机通信,将多个节点上的容器连接起来,形成一个就像本地局域网一样。不需要KV Store存储。

一个weave网络由一系列peers构成(WRoute),这些WRoute存在不同的主机上。不同主机之间的WRoute通过weave connect命令进行连接。这意味着你可以自己指定集群的网络拓扑。

整体架构图如下:

docker KAFKA_ADVERTISED_LISTENERS 配置 docker calico_calico_02

  • 在每一个部署Docker的主机(可能是物理机也可能是虚拟机)上都部署有一个WRouter,它本身也可以以一个容器的形式部署。weave网络是由这些weave routers组成的对等端点(peer)构成,并且可以通过weave命令行定制网络拓扑。
  • 每个WRoute之间会建立2个连接
  1. 一个tcp连接,用于握手和网络拓扑关系信息交换。默认6783端口。
  2. 一个udp连接,用于数据面的信息传递。默认6783端口。
  • 在数据面上,weave通过udp封装实现L2 Overlay。数据封装支持2种模式
  1. sleeve mode:用户态,通过pcap设备在Linux bridge上截获数据包并由wRouter完成UDP封装,支持对L2 traffic进行加密,还支持Partial Connection,但是性能损失明显
  2. fastpath mode:内核态,通过OVSodp封装Vxlan完成转发,WRouter不直接参与转发,这种方式可以明显地提升吞吐量,不支持加密

sleeve mode模式如下:

docker KAFKA_ADVERTISED_LISTENERS 配置 docker calico_weave_03

fastpath mode模式如下:

docker KAFKA_ADVERTISED_LISTENERS 配置 docker calico_flannel_04

上面的都真是介绍下weave的基本信息和大致架构,下面我们来一张更加详细的流程图,如下:

docker KAFKA_ADVERTISED_LISTENERS 配置 docker calico_docker_05

  • weave要求每个容器有两个网卡,一个就连在网桥上处理L2流量,另一个则连在docker0
  • weave-bridgeweave创建的网桥,桥的一端连接到容器,一端在weave
  • docker0docker原生网络,用于同主机容器之间通信,Docker0背后仍是iptables nat实现

上图容器之间通信的步骤如下:

  1. container1通过veth1将流量转到宿主机的weave-bridge网桥上
  2. WRoute使用pcap截获数据包,并排除由内核直接通过网桥转发的数据流量(本子网内部、本地容器、容器和主机之间的流量)。捕获的包通过WRoute封装成UDP数据包转到其他所有主机上
  3. 在其他主机上,WRoute收到数据包后解封装,然后通过pcap将包注入到网桥接口,然后通过网桥上的veth将流量转发到容器

Calico

calico把每个操作系统的协议栈认为是一个路由器,然后把所有容器都认为是连接在这个路由器上的终端,在路由器之间跑标准的路由协议——BGP协议,然后让它们自己去学习这个网络的拓扑该如何转发。

所以calico方案是一个纯三层的方案(不需要Overlay),也就是让每个节点的三层去确保本机两个容器之间、跨主机两个容器之间的三层连通性。需要etcd来存储网络元数据。

整体架构如下:

docker KAFKA_ADVERTISED_LISTENERS 配置 docker calico_calico_06

  • Felixcalico agent,负责配置路由及ACL(访问控制)等
  • etcd:网络元数据存储,确保calico网络状态一致
  • BGP Client(BIDR):主要负责把 Felix 写入 kernel 的路由信息分发到当前 Calico 网络,确保 workload 间的通信的有效性
  • BGP Route Reflector(BIRD): 大规模部署时使用,摒弃所有节点互联的 mesh 模式,通过一个或者多个BGP Route Reflector来完成集中式的路由分发
  • calico-ipam:主要用于kubernetes-cni插件,这里没有写出来

它每个节点上会运行两个主要的程序,一个是Felix,它会监听ECTD中心的存储,从它获取事件,比如说用户在这台机器上加了一个IP,或者是分配了一个容器等。接着会在这台机器上创建出一个容器,并将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。BGP Client是一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,你们路由的时候得到这里来。

Calico的网络方式:

calico的网络方式分为两种,如下:

  1. IPinIP:相当于一个基层的网桥。就是一个ip隧道
  2. BGP:边界网关协议,互联网上的一个核心去中心化自治路由协议

Calico总结:

由于Calico是一种纯三层的实现,因此可以避免与二层方案相关的数据包封装的操作,中间没有任何的NAT,没有任何的overlay,所以它的转发效率可能是所有方案中最高的,因为它的包直接走原生TCP/IP协议栈,它的隔离也因为这个栈而变得好做。因为TCP/IP协议栈提供了一整套的防火墙的规则,所以它可以通过`IPTABLES的规则达到比较复杂的隔离逻辑。

总结

三种方案的优缺点:

方案

优点

缺点

Flannel

1、简单、稳定

2、无需NAT

3、有overlay模式,也有纯3层模式

1、不提供DNS功能,容器之间只能通过ip访问

2、需要etcd

3、不支持网络策略

Weave

1、支持hostname访问

2、无需NAT

3、自己交换网络信息,不需要存储

4、支持加密

1、overlay网络

2、配置复杂,需要weave connect或者weave launch来加入网络

Calico

1、纯三层,无overlay,效率高

2、支持hostname访问

3、无需NAT

4、网络策略完善

1、需要存储

2、由于在三层,目前支持tcp、udp

3、对底层网络有要求,要求二层MAC地址可以通信