容器网络背景 如果只是容器在一台机器上使用Docker,或许你基本不用关心网络配置,网络因为Docker Daemon默认模式还是模式比较友好的,直接帮你们生一个Bridge命名为Bridge0,容器这样你可以通过端口映射的网络模式或是主机模式就可以让容器与外部互联互通了,而不用使用任何网络工具(brctl,模式 iptables)手工创建。但是容器如果将容器放到一个集群环境中(如使用Mesos或者K8S编排工具),这个网络问题就比较痛苦了。网络因为需要保证如何暴露容器给外部访问,模式同时又没有过多的容器额外性能开销,网络方案又是网络比较可控稳定,这成为了一个基于容器的模式PaaS平台的成功的关键因素。 我们的容器需求:独立IP 除了网络性能和网络稳定性的问题需要考量外,我们内部有个很重要的网络要求就是一定要确保每个容器获得一个独立的IP,并且确保每个容器间可以相互访问。模式因为我们有自己的基于RPC的服务化体系,源码下载需要一个平面的通讯网络,并且关联系统如APM系统,都是依赖这个独立IP做分析的。 网络方案选型 ***次做容器化的架构(半年前),选择网络方案的要点是简单和成熟的方案。网络选型主要有两个大方向,一个是物理机器方案即通过交换机的方式做方案如VLAN模式,VxLan模式等。另一个是软件方案SDN,如Overlay网络等。因为是我们***次做容器方案,为了保险起见,我们更信任物理设备的方式,所以我们选择了VLAN的模式作为***次选择,而VxLan对于物理设备有要求,先暂时放弃。不过如果有硬件基础的,则可以有限考虑VxLan方式。 ***版的云服务器VLAN网络方案 对于使用VLAN的模式,一开始我们都没有找到合适的资料,都是自己摸索出来的,后来新版本的docker支持docker network命令后,这些就简单一些。而我们是无需用docker create network的。主要方案如下: "vlan mode" ***版方案的缺陷 从***版的方案上看,虽然简单而且也比较稳定,我们在生产上跑了4个多月了,没有出现过问题。但是从管理监控的角度看,这个方案还是有明显的缺陷,只是在容器规模还没有达到一定的量的时候,这个缺陷是可以忍受的。但是亿华云对于这些缺陷,我们在做下一版的平台的时候就需要寻找合适的解决方案了。 这些缺陷主要是: 第二版的VLAN网络方案 第二版网络需求 动态IP管理方案 对于要使容器有独立的IP,又要使每个主机的IP的管理动态化,那么就需要将IP分配放在docker daemon/mesos+marathon的外部管理,通过插件plugin的方式集成。目前可选的方式是docker daemon的IPAM接口,或者是mesos slave的IPAM接口。虽然都叫IPAM,但是他们基于的机制不同。 Docker的IPAM(IP address management)是在Docker daemon的CNM(Container Network Model)机制下的IP管理驱动。CNM的设计模型,可以参考CNM Design。 Docker IPAM可以参考Docker IPAM 而对于Mesos则是遵循CNI的规范。CNI规范可以参看CNI Spec。 不过对于只需要动态管理IP地址的话,基于任何一种IPAM的接口都是可以的。所以我们经过老肖(@熟人云)介绍,参考了Talking Data公司的Shrike来做动态的IP管理。Shrike是基于Docker deamon的IPAM的方案, 所以只能用于基于Docker容器的方案,如果是用mesos unified container,则需要自己去改造成对接CNI的IPAM的接口。 虽然Shrike比较简单,但是目前Shrike有些局限,所以我们需要在上面做一些改造,以支持后续的扩展。主要包括: 网络限流方案 对于网络限流,一开始的思路是想利用mesos+marathon方案的自定义资源管理的方式,但是因为marathon迟迟不支持自定义资源调度,所以这个方式暂时放下了。希望用这样的方式管理的原因是想把网卡变成类似cpu/mem的资源同等对待,只要分配了带宽给容器的综合超过一定数就不再这个主机启动容器了。Mesos的自定义资源参考mesos attr resource 在这里还是要吐槽一下Marathon,开发的进度和Mesos太不一致了,希望Mesosphere的同学好好push一下。 这条路暂时走不通,那么在用Shrike做动态IP分配的时候,我想能不能在IP动态分配的时候就同时做了这个容器的带宽限制呢?所以就有了以下方案 "shrike" 主要的流程如下: 这个方案还有后续几个事宜我们还没有处理的: 我们还在构思,如图所示提供一个Console的管理控制台,实时展示容器的网络配置以及使用情况,因为net_id和net_out多会写入到Etcd中,所以完全可以在界面直接调整这两个值,然后Throttling的模块watch到变化就直接执行wondershape对容器进行更改就可。 减少ARP广播包的方案 ARP广播的目的是确定IP所在的主机的MAC地址,用于二层网络的寻址。但是容器的创建的时候,通常MAC地址是通过一定的规则生成的,所以每次有容器启动,都会广播这个MAC地址和它的IP的对应关系。但是如果MAC-IP的对应关系建立后没有关变,则ARP是无需再次广播的。这是通俗的说法。具体可以看RFC826规范。 既然是这样,我们是否可以找到一种手段来控制ARP包的量呢?有的,就是预先设置好IP-MAC的关系,也就是只要IP相同,它的MAC地址就是相同的。所以对于容器方案,可以预先初始化好规划的容量的所有IP和MAC的对应关系。然后每个容器启动时主动的去拉取这个表,并通过arp命令设置到容器中。(这里有个细节没有去实验,就是如果有几万个容器,arp命令执行这个表的时间是多少,是否影响容器启动的时间?) 这样容器启动后就有所有容器的IP-MAC对应关系,就无需发送过多的ARP包了。 不过这里还有另外一个问题,那就是无法使用IPAM接口,因为IPAM接口没有提供对应的容器的MAC的指定手段。(看CNI的源码历史,MAC设置原来是可以在IPAM中设置的,但是后来被挪到外层了) 所以如果需要在容器启动后直接更新一个大的固定的IP-MAC列表,就只能通过CNM/CNI的接口方式设置IP和MAC地址了 核心交换机的MAC地址的承载能力方案 这个只能是找硬件厂商解决了。据说京东下一代的方案是直接定制核心交换机以支持容器方案。具体细节不太清楚。如果有更好的方案,请记得告诉我 小结 到此为止,基本就涵盖我们第二版的网络改进方案的大体思路了。或许你会问,怎么不考虑用现在热门的几个三层网络方案呢?其实理由很简单,就是还是不能完全掌握的了,特别是如果问题定位,如何调试都是比较困难的。但是依赖与硬件交换机和Linux的特性,这个还是比较有信心的。所以建议如果不是技术有足够的掌控力,不要轻易尝试SDN的方案,除非你买专业的技术服务。 【本文是专栏作者“VIPDOCKER-了哥 ”的原创文章,如需转载请通过与作者联系】 戳这里,看该作者更多好文