基于容器的自动构建:Docker 在美团的应用
自动构建系统是从美团的自动部署系统发展出来的一个新功能。每当开发人员提交代码到仓库后,系统会自动根据开发人员定制的构建配置,启动新的 Docker 容器,在其中对源代码进行构建(build),包括编译(如 Java、C++和 Go)、预处理(如 JavaScript 和 CSS)、压缩(如图片)等操作,生成最终需要上线的程序包。
题图来自:tutum.co
背景和问题
美团的代码自动部署系统承载着美团所有业务的代码上线工作。代码部署系统一开始基于简单的 Bash 脚本,从一个中央主机上通过 Rsync 和 SSH 进行文件传输和命令执行。
图 1 代码部署系统架构图
代码发布系统经过多番演进,增加了很多功能,但原来的中心式架构仍然保留了下来,见图 1。发布者通过 Web 界面或者 REST API 控制中控机,中控机负责从 Git 服务拉取代码,构建应用程序包,然后通过 Rsync 上传程序包到应用集群,并用 SSH 执行远程命令。
图 2 过去 15 个月的发布次数
自动部署系统为美团业务的快速发展提供了有力的支撑。由于我们采用了开发人员自助上线的方式,发布操作频繁,工作日每日上线达上千次。图 2 是过去 15 个月每个月的发布次数。为了持续优化发布速度,给发布人员提供良好的体验,我们把单次发布平均时间作为发布系统的一项重要的 KPI。
然而,随着美团业务的迅速扩张,服务增多,发布应用数目也增多,中心化的架构的问题也凸显了出来。
- 问题 1:资源竞争
多个构建任务同时进行,竞争中控机的资源,影响发布速度。有一次一个应用受到同时进行的某 Java 类应用发布的影响,通常两分钟的发布变成了十多分钟,严重影响发布体验。如果出现事故需要回滚,就是更严重的问题了。
- 问题 2:环境冲突
不同应用的构建依赖环境在一台发布机上,需要考虑环境冲突和隔离的问题。例如,Java 1.6/1.7 共存,应用需要通过 JAVA_HOME 变量指定使用的 Java 版本,Maven 2/3 也存在同样的问题。npm 的 global 包也需要兼容多个应用的构建。
- 问题 3:安全隐患
应用的构建脚本运行在公共发布机上,脚本的 Bug 可能会影响到发布机的正常运行。例如某次一个构建脚本里面的 sudo service nginx reload 命令,本应是在应用服务器上执行的,但开发人员错误配置到了在发布机上执行的构建脚本里面。
解决方案
解决上述三个问题,我们首先想到的方案自然是重构为多台中控机的可横向扩展的方式。但由于某些应用的特殊性,改动比较麻烦,所以开始并没有走这个方向(现在已实现多中控机)。
那么另外一个思路:能不能把构建过程从中控机分离出来?这个思路受到了 Travis CI(https://travis-ci.org)的启发。我们借鉴 Travis CI,在代码提交时自动在一个新的环境中触发应用的构建。
因此,我们的解决方案可以概括为如下三点:
- 把构建过程放到 Docker 容器;
- 提交代码时自动触发构建;
- 发布时直接使用构建好的应用包。
使用前配置如下:
- 在发布系统配置发布项(build.yml);
- 在 Stash 配置自动构建服务的 URL;
- 在私有 Docker registry 上传定制镜像(可选)。
使用过程比较简单,主要有如下几个步骤:
- 开发人员提交代码到 Stash;
- 触发自动构建;
- 自动构建根据配置生成任务;
- 在 Docker 服务器上启动容器完成构建;
- 将构建好的包上传到美团云对象存储服务(MSS);
- 发布时从 MSS 拉取软件包并发布。
每次提交代码时会触发自动构建 API。构建任务放进队列里,任务在 Docker 服务器执行。当发布时就不用再去编译,直接拉取软件包进行发布。从图 6、图 7 两幅图中可以看到在发布过程中直接使用了已自动构建好的文件进行部署。
图 3 自动构建的配置
图 4 发布系统的配置界面
图 5 自动构建架构图
图 6 自动构建的日志
图 7 嵌入了自动构建日志的发布日志
为什么没有用虚拟机?
美团的虚拟化比较彻底,自动构建也可以用虚拟机而非容器实现。但虚拟机都和业务相关,会长时间保留。其次,虚拟机和 CMDB 深度结合,创建后会上报基本信息,部署 Agent,配置监控项等。此外,虚拟机的创建是比较慢的。综合考虑以上几点,我们使用了 Docker 而不是虚拟机作为自动构建的基本单元。
效果和收益
基于 Docker 容器的自动构建很好地解决了之前提到的三个问题:资源竞争、环境冲突和安全隐患。构建任务移出发布机,构建用 Docker 服务器可横向扩展,解决了资源竞争问题。每个构建都是独立的镜像,环境冲突问题不复存在。构建脚本运行在独立于发布机的 Docker 服务器上,对发布机造成的安全隐患自然就消除了。
除解决了以上三个问题外,自动构建还显著改善了发布速度。经统计,自动构建任务的平均执行时间是 197s,而使用自动构建应用的平均发布时间是 99s。如果不使用自动构建,那么这些应用的发布时间就是 197s + 99s,大约是三百秒。可以看到,自动构建把应用的发布时间缩短了三分之二。
总结
自动构建是美团对 Docker 的首次应用。这个应用不是为了用 Docker 而用 Docker 的,而是在解决代码部署系统中的问题时,利用 Docker 很好地解决了我们遇到的问题。该应用只利用了 Docker 最核心的容器功能,并没有使用 Docker 集群管理、调度、自动扩容等高级的功能。自动构建的场景非常适合使用 Docker。希望本文能够对计划开始使用 Docker 的公司有所启发。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 如何交互式地创建一个 Docker 容器
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论