当前位置: > Linux服务器 > Docker >

理解Docker(6):若干企业生产环境中的容器网络方案

时间:2016-11-27 01:14来源:oschina.net 作者:xrzs

  Docker 在早期只有单机上的网络解决方案,在 1.19 版本引入了原生的 overlay 网络解决方案,但是它的性能损耗较大,可能无法适应一些生产环境的要求。除了Docker 提供的解决方案外,还有其它一些开源的解决方案。本文首先会简介各种已有的方案,然后根据公开分享的资料,总结一下部分企业在生产环境中对容器网络的选型和考量。

1. 现有的跨主机容器网络解决方案

1.1 Flannel容器网络

Flannel 是由 CoreOS 主导的解决方案。Flannel 为每一个主机的 Docker daemon 分配一个IP段,通过 etcd 维护一个跨主机的路由表,容器之间 IP 是可以互相连通的,当两个跨主机的容器要通信的时候,会在主机上修改数据包的 header,修改目的地址和源地址,经过路由表发送到目标主机后解包。封包的方式,可以支持udp、vxlan、host-gw等,但是如果一个容器要暴露服务,还是需要映射IP到主机侧的。

1.2 Calico 网络方案

Calico 是个年轻的项目,基于BGP协议,完全通过三层路由实现。Calico 可以应用在虚机,物理机,容器环境中。在Calico运行的主机上可以看到大量由 linux 路由组成的路由表,这是calico通过自有组件动态生成和管理的。这种实现并没有使用隧道,没有NAT,导致没有性能的损耗,性能很好,从技术上来看是一种很优越的方案。这样做的好处在于,容器的IP可以直接对外部访问,可以直接分配到业务IP,而且如果网络设备支持BGP的话,可以用它实现大规模的容器网络。但BGP带给它的好处的同时也带给他的劣势,BGP协议在企业内部还很少被接受,企业网管不太愿意在跨网络的路由器上开启BGP协议。

1.3 总结

跨主机的容器网络解决方案不外乎三大类:

  • 隧道方案:比如Flannel的 VxLan。特点是对底层的网络没有过高的要求,一般来说只要是三层可达就可以,只要是在一个三层可达网络里,就能构建出一个基于隧道的容器网络。问题也很明显,一个大家共识是随着节点规模的增长复杂度会提升,而且出了网络问题跟踪起来比较麻烦,大规模集群情况下这是需要考虑的一个点。 
  • 路由方案:路由技术从三层实现跨主机容器互通,没有NAT,效率比较高,和目前的网络能够融合在一起,每一个容器都可以像虚拟机一样分配一个业务的IP。但路由网络也有问题,路由网络对现有网络设备影响比较大,路由器的路由表应该有空间限制一般是两三万条。而容器的大部分应用场景是运行微服务,数量集很大。如果几万新的容器IP冲击到路由表里,导致下层的物理设备没办法承受;而且每一个容器都分配一个业务IP,业务IP消耗会很快。  
  • VLAN:所有容器和物理机在同一个 VLAN 中。

1.4 一个网友的性能测试报告

来源:https://www.douban.com/note/530365327/

结论:

方案 结论 优势 劣势
weave(udp) 真是惨,生产环境就别考虑了。看了下他们的架构,觉得即便是 fast-data-path 也没多大意义。 就是个渣渣,概念好毛用都没
calico calico 的 2 个方案都有不错的表现,其中 ipip 的方案在 big msg size 上表现更好,但蹊跷是在 128 字节的时候表现异常,多次测试如此。bgp 方案比较稳定,CPU 消耗并没有 ipip 的大,当然带宽表现也稍微差点。不过整体上来说,无论是 bgp 还是 ipip tunnel,calico 这套 overlay sdn 的解决方案成熟度和可用度都相当不错,为云上第一选择。 性能衰减少,可控性高,隔离性棒 操作起来还是比较复杂,比如对 iptables 的依赖什么的
flannel flannel 的 2 个方案表现也凑合,其中 vxlan 方案是因为没法开 udp offload 导致性能偏低,其他的测试报告来看,一旦让网卡自行解 udp 包拿到 mac 地址什么的,性能基本上可以达到无损,同时 cpu 占用率相当漂亮。udp 方案受限于 user space 的解包,仅仅比 weave(udp) 要好一点点。好的这一点就是在实现方面更加高效。 部署简单,性能还行,可以兼容老版本 docker 的启动分配行为,避免 launcher  没法实现固定 IP 的容器漂移,没法多子网隔离,对上层设计依赖度高,没有 IPAM,对 docker 启动方法有绑定
docker 原生 overlay 方案 其实也是基于 vxlan 实现的。受限于 cloud 上不一定会开的网卡 udp offload,vxlan 方案的性能上限就是裸机的 55% 左右了。大体表现上与 flannel vxlan 方案几乎一致。 docker 原生,性能凑合 对内核要求高(>3.16),对 docker daemon 有依赖需求 ( consul / etcd ),本身驱动实现还是略差点,可以看到对 cpu 利用率和带宽比同样基于 vxlan 的 flannel 要差一些,虽然有 api 但对 network 以及多子网隔离局部交叉这种需求还是比较麻烦,IPAM 就是个渣

综上,云上能用 BGP 就果断上 calico bgp 方案,不能用 BGP 也可以考虑 calico ipip tunnel 方案,如果是 coreos 系又能开 udp offload,flannel 是不错的选择。Docker overlay network 还有很长一段路要走,weave 就不用考虑了。

2. 若干企业生产环境中的容器网络方案

2.1 PPTV Docker网络解决方案 - 基于 linux bridge

(0)PPTV 容器云架构

(1)网络需求

  • 网络组人力不足以维护一个Overlay网络,Overlay网络出问题排查复杂,会出现失控的状态。
  • 隧道技术影响性能,不能满足生产环境对网络性能的要求。
  • 开启bgp对现有网络改动太大,无法接受。
  • 运维组同学希望能通过网络桥接的方案解决容器网络。 

(2)选中的方案

最终 PPTV 选中基于docker的bridge模式,将默认的docker bridge网桥替换为 linuxbridge,把 linuxbridge 网段的 ip 加入到容器里,实现容器与传统环境应用的互通。

  1. 首先会在该主机上添加一个linux bridge,把主机网卡,可以是物理机的,也可以是虚拟机的,把这个网卡加入bridge里面,bridge配上网卡原本的管理IP。
  2. 创建一个新的docker bridge网络,指定bridge子网,并将该网络的网桥绑定到上一步创建的网桥上。

docker network create --gateway10.199.45.200 --subnet 10.199.45.0/24 -o com.docker.network.bridge.name=br-oak--aux-address"DefaultGatewayIPv4=10.199.45.1" oak-net

  1. 容器启动时候,指定容器网络为第二步中创建的bridge网络,同时为容器指定一个该网络子网内的IP。容器启动后网络IP默认即可与外界互通。

(3)问题及解决方案

通过网桥的方式解决容器网络有两个问题:

  1. 容器跨主机漂移要求宿主机在同一个VLAN 中:linux bridge 只能添加跟 slavehost 同一个vlan的IP,也就是说容器IP必须要和宿主机在同一vlan下,这在一定程度上就限制了容器跨宿主机漂移的范围。不过这个问题在PPTV 的生产环境中天然不存在,因为我们的生产环境中,每个数据中心的主机都在一个很大的子网内,基本能满足容器在整个数据中心的任意节点下漂移。
  2. 跨主机的 IP 地址分配需要避免地址冲突:要让容器 IP 在不同的宿主机上漂移,宿主机的 docker 网络需要使用同一个CIDR,也就是各宿主机的容器使用同一个网段。而不同宿主机的使用同一个容器网段就会涉及到IPAM的问题,因为宿主机的docker daemon只知道他本机上的容器使用了哪些IP,而这些IP在其他宿主机上有没有被使用,是不知道的。在默认的docker bridge中,因为这些ip不会直接与外部通信,所以容器使用相同IP也不会有问题,但是当容器网络通过linux bridge打通以后,所有容器都是2层互通的,也就是会出现IP冲突的问题。为了解决上边提到的问题,实现全局的IP管控,我们开发了IP池管理平台,实现对容器IP的分配管理。
  3. 需要更新服务自动注册、自动发现:因为原先的方案是基于NAT的模式做的,而现在实现了独立IP的功能。我们需要将现有的平台与PPTV内部的DNS做自动化对接,每当有容器创建和生成时,都会自动对容器的IP做DNS解析。
  4. 负载均衡:PPTV的负载均衡基本都是通过LVS + nginx实现的,但对于后台的容器应用来说,每次扩容和缩容、或者创建新的应用,负载均衡的后端配置也是需要自动更新的。

2.2 宜信的容器网络解决方案 - 基于 Calico

(1)网络需求

  • 让每个容器拥有自己的网络栈,特别是独立的 IP 地址

  • 能够进行跨服务器的容器间通讯,同时不依赖特定的网络设备

  • 有访问控制机制,不同应用之间互相隔离,有调用关系的能够通讯

(2)调研过程和最终的选择

调研了几个主流的网络模型:

  • Docker 原生的 Bridge 模型:NAT 机制导致无法使用容器 IP 进行跨服务器通讯(后来发现自定义网桥可以解决通讯问题,但是觉得方案比较复杂)

  • Docker 原生的 Host 模型:大家都使用和服务器相同的 IP,端口冲突问题很麻烦

  • Weave OVS 等基于隧道的模型:由于是基于隧道的技术,在用户态进行封包解包,性能折损比较大,同时出现问题时网络抓包调试会很蛋疼

  • Project Calico 是纯三层的 SDN 实现,它基于 BPG 协议和 Linux 自己的路由转发机制,不依赖特殊硬件,没有使用 NAT 或 Tunnel 等技术。能够方便的部署在物理服务器,虚拟机(如 OpenStack)或者容器环境下。同时它自带的基于 Iptables 的 ACL 管理组件非常灵活,能够满足比较复杂的安全隔离需求。

各种方案的限制:

  • Docker Bridge:每个容器里面都有一个虚拟网卡,和主机上的虚拟网卡做配合,所有容器内的虚拟网卡都可以和主机通信。通过端口映射,我调用对方的容器服务的时候,不能使用该容器直接的地址,必须使用它主机的地址。因为有了这样一个转发,网络通讯的性能有所损耗。当然,还有一个问题更严重,访问你的容器先要搞清楚你的主机是什么,这样网络通讯会跳来跳去。不但麻烦,还会带来端口冲突。每创建一个容器会绑定一个端口,怎么管理好这些端口是一个很大的挑战。
  • Fannel:这个方法有几个问题,第一个是要做封包的操作,这会带来网络性能损失。第二个问题是每个主机上的容器是固定的,容器的不同主机之前的迁移必然带来IP的变化。
  • Weave:它的思路是共享IP而非绑定。在传输层先找到目标地址,然后把包发到对端,节点之间互相通过协议共享信息。Flannel和Weave的特点是类似的,都用的是UDP或者是VxLAN的技术。事实上使用UDP性能是很差的,VxLAN和UDP差不多,它有一个网络切隔,而且在里面可以跑二层协议。还有一种是IPIP封包,直接把一个IP包封装在一个IP包里面。以上不难看出,原生网络性能比较差,使用UDP的时候性能损失在50%以上,使用VxLAN也会有20%~30%的损耗。所以我要在内核上封包,使用硬件来解决这些问题。而且容器和容器之间出现通讯故障,调试的时候非常困难

(3)Calico 使用总结

  • Calico 的应用场景主要是IDC内部,推荐部署在二层网络上,这样所有路由器之间是互通的。这种场景是大二层的解决方案,所有服务器都在里面。但大二层主要的问题是弹性伸缩的问题。频繁开关机的时候,容器启停虽然不影响交换机,但容易产生广播风暴。网络规模太大的时候,一旦出现了这样的问题,整个网络都会有故障,这个问题还没有解决的特别好。
  • Calico作为一个纯二层的应用问题不大。我们可以把集群分成了很多网段,对外是三层网络的结构。集群内部分成多个自制域,比如一个机柜是一个自制域,之间通过交换路由的方式实现在三层容器到容器的互通。瓶颈在于容器的路由信息容量。所以说本质上它不是一个应对互联网规模的解决方案,但对宜信场景是够用的。
  • 我们实施的时候遇到一些坑,比如容器在启动时没有网络、操作ETCD的时候BGP配置频繁加载,等等,最后我们多一一解决了。我们也发现了driver方案功能方面的弱点,现在还继续使用劫持API的方法。如果要在云上使用,如果支持BGP,直接可以用;如果不支持BGP可以用IPIP。现在英特尔的网卡支持两个协议,一个是GRE、一个是VxLAN。如果真的把它放在云上,我们可以考虑一下把VxLAN引进来,性能上的差别不是很大。

2.3 京东和魅族都是采用 OVS + VLAN 方案

根据 2016 北京容器大会 《魅族云容器化建设》 文档的一些总结:

(1)使用 OVS port 替代 OVS veth 可以带来较大的性能提升

  

(2)使用 SR-IOV

   

(3)使用 DPDK

 3. 小结

上面的几个生产环境中的网络解决方案,它们的目的都是为了把容器当作虚机用,因此都有共同的需求,比如:

  • 每个容器有独立的 IP,这样运维就可以象通过 ssh 连接到虚机一样连接进容器
  • 需要跨服务器之间的容器通信
  • 安全性,包括访问控制和隔离性
  • 性能保证和优化
  • 对现有物理网络改动和影响较小
  • 使用和调试都比较方便

要满足以上要求,可能 OVS/Linux-bridge + VLAN 方案应用的比较多,同时看起来 Calico 方案看起来前景不错。

 

参考链接:



(责任编辑:IT)
------分隔线----------------------------
栏目列表
推荐内容