前言
现在不管出现什么新技术、新框架,那有2个问题是大家都绕不开的,包括操作系统在内也绕不开这2个问题,而且是非常基础的问题——网络和存储。
回想以下以前学习过的框架,回想以下操作系统原理,是不是都不可能绕开这两点?这两点是所有程序的基础,同时也是Docker要解决的重点问题。今天我们就一起来学习下Docker的网络解决方案。
Docker中的网络解决方案
在Docker中,网络问题主要有3种解决方案。如下:
FlannelWeaveCalico
它们的目的无非就是为了解决同一个问题:如何让容器之间互相通信?这个问题再升级以下,放在kubernetes集群来看,它解决的也是同一个问题。不过在kubernetes中,它有一些约束,所有的网络实现都要遵循CNI标准(由kubernetes定义的标准,方便社区或公司进行扩展)。CNI规范总结起来可归纳成约法三章和四大目标。如下:
约法三章:
pod与pod直接通信,无需显示使用NATnode与pod直接通信,无需显示使用NATpod可见IP地址确为其它pod与其通信时所有,无需显示转换
四大目标:
- 容器与容器的通信
pod与pod之间的通信pod与service之间的通信- 外部与
service之间的通信
还有,一般各大云平台都会结合自己的网络方案实现一种解决方案,现在先不管这些。下面我们就来一一学习下上面提到的3中解决方案。
Flannel
flannel是由coreos团队开发,设计之初就是为了解决集群中所有节点重新规划ip地址的使用规则,从而使得不同节点上的容器能获得同一个内网且不重复的IP地址,并且属于不同节点上的容器能够直接通过内网IP通信!
整体架构如下:

- Flannel 使用etcd存储配置数据和子网分配信息。flannel 启动之后,后台进程首先检索配置和正在使用的子网列表,然后选择一个可用的子网,然后尝试去注册它。
etcd也存储这个每个主机对应的ip。flannel使用etcd的watch机制监视/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协议是因为它能穿透防火墙。
一次完整的通信过程如下
- 数据包由源容器发出,经过
docker0转发至flannel0 - 源
flanneld监听到此数据包之后,解析到数据包应该发送给哪个flanneld?然后源flanneld从etcd里查询该目的地址的路由信息 - 源主机的
flanneld再将数据包使用UDP协议进行封装,然后根据路由表将数据包投递给对端flanneld - 对端
flanneld收到数据包,解包发送到flannel0网卡,接着再转发到docker0网卡 - 最后由
docker0路由到最终容器
Flannel总结
flannel实质上是一种"覆盖网络(overlay network)",即表示运行在一个网上的网(应用层网络),并不依靠ip地址来传递消息,而是采用一种映射机制,把ip地址和identifiers做映射来资源定位。也就是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持UDP、VxLAN、AWS VPC和GCE路由等数据转发方式。
Weave
weave是由weaveworks公司开发的,其目的是要解决Docker跨主机通信,将多个节点上的容器连接起来,形成一个就像本地局域网一样。不需要KV Store存储。
一个weave网络由一系列peers构成(WRoute),这些WRoute存在不同的主机上。不同主机之间的WRoute通过weave connect命令进行连接。这意味着你可以自己指定集群的网络拓扑。
整体架构图如下:

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

fastpath mode模式如下:

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

weave要求每个容器有两个网卡,一个就连在网桥上处理L2流量,另一个则连在docker0上weave-bridge:weave创建的网桥,桥的一端连接到容器,一端在weavedocker0:docker原生网络,用于同主机容器之间通信,Docker0背后仍是iptables nat实现
上图容器之间通信的步骤如下:
container1通过veth1将流量转到宿主机的weave-bridge网桥上WRoute使用pcap截获数据包,并排除由内核直接通过网桥转发的数据流量(本子网内部、本地容器、容器和主机之间的流量)。捕获的包通过WRoute封装成UDP数据包转到其他所有主机上- 在其他主机上,
WRoute收到数据包后解封装,然后通过pcap将包注入到网桥接口,然后通过网桥上的veth将流量转发到容器
Calico
calico把每个操作系统的协议栈认为是一个路由器,然后把所有容器都认为是连接在这个路由器上的终端,在路由器之间跑标准的路由协议——BGP协议,然后让它们自己去学习这个网络的拓扑该如何转发。
所以calico方案是一个纯三层的方案(不需要Overlay),也就是让每个节点的三层去确保本机两个容器之间、跨主机两个容器之间的三层连通性。需要etcd来存储网络元数据。
整体架构如下:

Felix:calico 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的网络方式分为两种,如下:
IPinIP:相当于一个基层的网桥。就是一个ip隧道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地址可以通信 |
本文深入探讨了Docker中解决容器间通信的三大网络方案:Flannel、Weave和Calico。详细介绍了每种方案的工作原理、架构特点及优缺点,为读者提供了全面的Docker网络配置指南。
446

被折叠的 条评论
为什么被折叠?



