扯犊子:双11,女人们疯狂的时候,也是电商网站技术人员接受考验的时候。2016双11,阿里完成了1207亿的成交额,交易峰值17.5万单每秒。阿里技术大咖们做了什么样部署和准备?且看阿里平台架构部负责人林昊为你解密!


在基础设施方面,今年双11最大的变化是支撑双11的所有交易核心应用都跑在了Docker容器中。几十万Docker容器撑起了双11交易17.5万笔每秒的下单峰值。

众所周知Docker技术这几年大热,但是过去相当长的一段时间内,阿里内部技术人员只能自己私下玩玩,没法在阿里内部生产环境使用Docker,因为Docker要求的OS版本和内核版本都比较高,阿里内部的AliOS5u7和AliKernel2.6.32内核是在CentOS-5.7和linux-2.6.32内核基础上做了很多定制而来,没法运行Docker。如果将内部OS从5u、6u升级到7u,将内核从2.6.32升级到Docker官方推荐的3.10,除了之前众多的内核、OS补丁需要和高版本做合并和功能对齐之外,还必须和上层应用经过足够多的磨合,这可不是一朝一夕就能完成的事情。阿里的应用数量庞大,种类众多,光兼容性的验证没个1、2年的时间没人敢把核心应用放上去。因此虽然Docker能给研发和运维带来的好处,作为技术人员大家都心领神会,但是面对Docker浪潮却只能是坐观弄潮者,徒有羡鱼情。

所幸的是,这个状况在去年7月份有了改变,这事要从阿里内部的容器技术产品T4说起。T4是阿里在2011年的时候基于Linux Container(LXC)开发的容器技术基础设施。从12年到15年3年时间里用的应用越来越多,实际上已经覆盖了电商领域大部分App。相比Docker的模式和理念,T4其实更适合阿里内部的运维现状。T4是从阿里内部的资源管理和日常运维中土生土长出来的产品,在诞生的第一天就针对内部基础设施、运维工具甚至是运维习惯做了很多特别的设计。T4在LXC容器的基础上,对容器资源和各种统计的可见性做了很多卓有成效的隔离,使得在容器内部看到的资源就是分配给这个容器的资源,内部看到的负载就是这个容器的负载等等。同时在LXC之外还做了容器的磁盘空间配额限制和隔离,容器内看到的那块磁盘大小就是创建容器时分配给他的磁盘配额大小。这样在CPU、网络、内存、磁盘等资源使用和统计监控上做到了容器内和物理机上基本没有区别。原来跑在物理机,或者KVM、Xen中的应用,能够平滑无感知的迁移到T4中。当年从Xen、Kvm迁移到T4的过程中,很多应用的开发者和Owner确实不知道什么时候完成迁移的,可能在某次常规的应用发布中,后台工具系统已经自动做完迁移了。甚至直到去年在和一个应用研发的沟通中,他坚信自己的应用是跑在KVM中的,我们到后台查了一下,其实已经在T4上了。

于是我们从去年6月份开始对Docker和T4都做了一些修改整合后,将两者融合为了一个产品,相当于既让T4具备了Docker的镜像能力,又让Docker具备了T4对内部运维体系的友好性,并且能够运行在内部的AliOS5u7和2.6.32内核上。这个产品在内部称为AliDocker,在去年8月份推出了第一个雏形版本。另外这个版本还解决了Docker当时很严重的一个问题,就是Daemon退出其上所有的容器都会退出,这一点在真正生产环境大规模部署时是无法接受的。Docker官方直到1.10版本才开始部分解决这个问题。我们当时的Docker版本从1.5一直跟进到后来大规模部署的1.9版本,通过Docker的Daemon管控进程和容器的解耦,Daemon重启后对之前运行容器的自动识别和重新接管,解决了这个问。这样Docker在阿里内部大规模应用就有了可能。

从这个版本发布到能够替换T4大规模部署还走了很长的路,首先T4和Docker毕竟是两个不同的产品,除了大家耳熟能详的容器机制之外,其实还有非常多的细节和特性。为了让应用在迁移中无感知,AliDocker对原先T4容器的细节功能做了全面的兼容,同时对上层的运维系统做了大量改造,使其支持Docker场景下的发布和运维模式,从Docker镜像构建到分发启停、扩容迁移都做了完备的工具和流程支持。其次在T4到AliDocker切换的过程中,我们做了2者混跑的支持,也就是说同一台物理机上可以同时跑原来的T4容器和新的AliDocker容器,互不干扰并且能统一运维。因为众多应用的实例是交错部署在众多物理机上,同一个物理机上往往有十几个不同应用的实例混跑。这种兼容机制就保证了不同应用可以按各自的节奏逐步完成Docker化,而不需要在某个时间和空间做一刀切,避免了大规模升级Docker的过程中不必要的应用腾挪和迁移。然后在我们将AliDocker和T4功能完全对齐,从实例级别到应用级别做了足够的灰度后,推送了一个开关,使得从那一刻开始创建新T4实例时会自动创建为AliDocker实例,从而完成了增量实例的切换。对于存量的T4实例,我们选择了一个完整的深圳交易单元,分批次做了批量切换,在切换期间如果发生大的问题,可以把深圳单元的流量全部切换到上海。这一保障要得益于阿里的异地多活灾备架构,对于这类底层基础设施的升级能够提供理想的兜底方案,使我们敢于放开手脚去做,而又能有效的控制风险。所幸在整个升级洗牌的过程中,没有动用到这个大杀器的功能,虽然出了一些小问题但都能及时修复,影响不大,也让我们的系统更加健壮,让各个部门的人对交易核心流量切换到AliDocker这件事情更有信心。

但是仅仅将运行容器从T4切换到Docker其实对我们带来的改变并不大。Docker真正的核心价值在于镜像机制,以及镜像机制带来的研发与运维模式的变革。应用镜像化大致来说有2种方式,一种是比较保守的方式,镜像中只包含基础环境,容器起来后,再登录到容器中部署应用包。这种方式和原先的T4类似,镜像化上不够彻底。为了彻底根治环境不一致的沉疴,从机制上杜绝非标准变更,让每个环境改变都沉淀下来,我们采取了另一种更激进的方式:镜像中除了包含基础环境外,还包含应用程序。应用新版本发布时,直接销毁原有的容器,用新版本的镜像启动新的容器提供服务。这样任何在上一个容器中做的小动作都会随着下一次发布全部清洗掉,如果想要保留下来,就必须固化到应用的Dockerfile中。一个应用镜像就代表了应用的所有依赖环境和当前版本。任何时间任何地点将应用最新镜像拉起,都能得到和线上其他实例一致的服务和行为。我们在推广AliDocker的过程中,一直和所有的应用方强调这个理念,也获得了大家的认同。

于是在今年5月底,我们成立了专门的项目组,快速推进这个事情,目标是把双十一流量覆盖的核心应用全部升级为镜像化模式的Docker应用。由于我们做到了运行态与T4保持一致,改造过程比较顺利,但实际上线中也遇到了许许多多即在意料之外又在情理之中的问题。最终交易全链路所有核心应用全部在AliDocker容器中圆满完成了1207亿成交额的答卷,证明了AliDocker技术体系在电商交易级别的大规模应用中能够担负重任!

Docker化之前

a)触发我们Docker化的主要原因一:Docker最重要的一点是镜像化,可以做到拿着镜像就可以从一台完全空的机器的应用环境搭建起来,可以把单机环境完全从零搭好。Docker化之前,阿里巴巴的应用部署方式主要由Java、C来编写的,不同的业务BU可能采用完全不同的部署方式,没有统一标准。内部尝试通过基线来建立部署标准,定义的基线包括应用依赖的基础环境(OS、JDK版本等)、应用依赖的脚本,基础环境的配置(启动脚本、Nginx配置等)、应用目录结构、应用包、应用依赖的DNS、VIP、ACI等,但不成功。部署标准做不了,直接导致自动化很难做到。

Docker化目标

  • 交易核心应用100%Docker化;
  • DB其中一个交易单元全部Docker化。

    推进Dcoker之前,我们有一个准备的过程。在准备阶段,我们需要Docker更像VM和更贴合阿里运维体系的Docker,我们将改造过的Docker称为AliDocker;除了AliDocker以外,我们需要支持AliDocker的工具体系,比如编译、镜像库、镜像分发机制,在完成这些准备工作后,我们认为可以一帆风顺地开始大规模的AliDocker上线。但事实并非如此。

    我们碰到了很多问题:

    镜像Build后上传,以前阿里一个应用转成多个,很多时候需要在自己的机器上做Build,然后自己上传,导致做应用时很痛苦;

    第二轮Docker化

    我们在Docker的镜像模式基础上做出一个crofix的模式,这个模式不是绕开镜像,而是从镜像中拉起我们需要的文件,去做覆盖等动作,这样就可以完成整个发布。Docker化镜像模式是必须坚持的,否则失去了Docker化的意义。

    继续推进到很多应用切换到Docker的时候,我们又遇到了更大的问题:

    对此,我们在编译层做了很多优化,尽可能让你每次都在之前编译的基础上进行编译。第二,镜像压缩问题,Go在1.6以前的版本压缩是单线程,意味着压缩整个镜像时效率会非常低,所以我们选择暂时把镜像压缩关闭掉。

    阿里制定了镜像分发多机房优化,比如打包后将所有镜像同步到所有机房;阿里也做了发布优化(P2P、镜像预分发、流式发布),还通过Docker Volume将目录绑定到Dockerfile中,可以保证镜像文件每次拉起时不会被删掉。

    第四轮Docker化

    由于规模比较大,开源软件很容易碰到支撑规模不够,稳定性差的问题。目前我们使用Swarm来管理,Swarm的规模能力大概可以支撑1000个节点、50000个容器,而我们需要单Swarm实例健康节点数在3W+,对此,我们对Swarm进行了优化。

    规模我们做到从支撑1000到3W+,压力减小了很多。而Swarm的稳定性对我们来讲,最大的问题在HA上,一个Swarm实例如果挂掉,重新拉起需要时间,所以我们在用Swarm时进行了改造。在前面加了一层Proxy,不同业务、不同场景都可以通过Proxy转换到自己不同的Swarm实例上。另外,所有的Swarm节点我们都会用一个备方案在旁边,而且都是不同机房去备。

    Bugfix和功能增强

  • Daemon升级或crash后,所有容器被自动销毁的问题;
  • Cpuset、cpuacct和CPU子系统mount到一起时CGroup操作错误的bug;
  • 支持基于目录的磁盘配额功能(依赖内核patch);
  • 支持制定IP启动容器,支持通过DHCP获取IP;
  • 支持启动容器前后执行特定脚本;
  • 支持镜像下载接入各种链式分发和内部mirror的机制;
  • 增加Docker Build时的各种参数优化效率和适应内部运维环境;
  • 优化Engine和Registry的交互。

    未来

  • 所有软件AliDocker化;
  • 和Docker公司紧密合作回馈社区;
  • AliDocker生态体系逐渐输出到阿里云。

    作者:林昊(毕玄),阿里巴巴研究员,平台架构部负责人,淘宝服务框架(HSF)作者,异地多活项目负责人,目前致力于资源统一管理调度系统建设。

    来源:http://www.dajiangtai.com/community/18134.do?origin=csdn-blog
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐