前言
现在不管出现什么新技术、新框架,那有2
个问题是大家都绕不开的,包括操作系统在内也绕不开这2
个问题,而且是非常基础的问题——网络
和存储
。
回想以下以前学习过的框架,回想以下操作系统原理,是不是都不可能绕开这两点?这两点是所有程序的基础,同时也是Docker
要解决的重点问题。今天我们就一起来学习下Docker
的网络解决方案。
Docker中的网络解决方案
在Docker
中,网络问题主要有3
种解决方案。如下:
Flannel
Weave
Calico
它们的目的无非就是为了解决同一个问题:如何让容器之间互相通信?这个问题再升级以下,放在kubernetes
集群来看,它解决的也是同一个问题。不过在kubernetes
中,它有一些约束,所有的网络实现都要遵循CNI
标准(由kubernetes
定义的标准,方便社区或公司进行扩展)。CNI
规范总结起来可归纳成约法三章和四大目标。如下:
约法三章:
-
pod
与pod
直接通信,无需显示使用NAT
-
node
与pod
直接通信,无需显示使用NAT
-
pod
可见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
创建的网桥,桥的一端连接到容器,一端在weave
-
docker0
: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地址可以通信 |