SRE:Google运维解密
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

持续构建与部署

Google开发了一个自动化的发布系统:Rapid。该系统利用一系列Google内部技术执行可扩展的、密闭的,以及可靠的发布流程。下面几小节描述了Google内部的软件生命周期,以及我们是如何利用Rapid和其他相关工具管理这种周期的。

构建

Blaze[24]是Google的构建工具,它支持多种编程语言,如Google内部标准的 C++、Java、Python、Go 以及JavaScript。工程师利用Blaze定义构建目标,即构建的输出结果,例如Jar文件,同时给每个目标指定依赖关系。当进行具体构建时,Blaze会自动构建目标的全部依赖。

构建目标(二进制文件,以及对应的测试等)定义在Rapid的项目配置文件中。某个项目特有的功能开关,例如一些特有的构建标识符等,会由Rapid传递给Blaze。所有二进制文件都支持用一个命令显示自身的构建时间、构建源代码版本,以及构建标识符,这样我们就可以很容易地将一个二进制文件与构建过程对应起来。

分支

所有的代码都默认提交到主分支上(mainline)。然而,大部分的项目都不会直接从主分支上进行直接发布。我们会基于主分支的某一个版本创建新分支,新分支的内容永远不会再合并入主分支。Bug修复先提交到主分支,再cherry picking到发布分支上。这种方式可以避免在第一次构建之后,再引入主分支上的其他的无关改动。利用这种分支与cherry picking的方法,可以明确每个发布版本中包含的全部改动。

测试

一个持续测试系统会在每个主分支改动提交之后运行单元测试,这样我们可以快速检测构建错误和测试错误。建议使用项目中定义的构建目标及测试目标的执行结果来决定是否发布某个版本。同时建议使用最后一个测试全部通过的软件版本来进行最新的发布。这些方法可以降低在真正发布时由于主分支上其他无关改动造成问题的几率。

在发布过程中,我们会使用该发布分支重新运行全部单元测试,同时为测试结果创建审核记录。这一个步骤非常重要,因为如果一个发布过程需要cherry picking,发布分支可能会包含主分支上不存在的一个代码版本。我们必须确保在发布分支上全部测试确实通过。

为实现持续测试系统,我们使用一套独立的测试环境来在打包好的构建结果上运行一些系统级别测试。这些测试可以从Rapid网站上手工启动。

打包

软件通过Midas Package Manager(MPM)系统分发到生产机器上。MPM基于Blaze规则中列出的构建结果和权限信息构建MPM包。每个包有固定名称(如search/shakespeare/frontend),记录构建结果的哈希值,并且会加入签名以确保真实完整性。MPM同时支持给某个版本的包打标签。Rapid也会加入一个构建ID标签,这样某个包可以用名字和这个标签来唯一识别。

我们可以给某个MPM包加标签,标记该MPM包在整个发布过程中的位置(如dev、canary或production等)。如果将某个现有标签应用到新包上,这个标签会自动从原来的包上移除。例如,如果一个包标记为canary,之前的canary包上的标签就被自动去掉了,后续安装canary版本的包的人会自动使用最新的包版本。

Rapid系统

图8-1 展示了Rapid系统中的主要组件。Rapid是用Blueprint文件配置的。Blueprint文件是一种利用Google内部配置语言写成的,用来定义构建目标和测试目标、部署规则,以及一些管理用信息(例如项目负责人信息)。基于角色的访问控制列表可以决定谁能执行哪些动作。

图8-1:简化版Rapid架构,展示了系统的主要组件。

每个Rapid项目都有一些工作流,定义了发布流程中的具体动作。工作流可以线性或者并发执行,某个工作流也可以启动另外一个工作流。Rapid将工作请求分发给运行在Borg系统上的生产服务器。因为Rapid使用Google的生产基础设施,我们可以同时处理几千个发布请求。

典型的发布流程按如下顺序进行:

1.Rapid使用集成版本号(通常自动从持续测试系统获取)创建新的发布分支。

2.Rapid利用Blaze编译所有的二进制文件,同时执行所有的单元测试,这两个过程通常是并发进行的。编译和测试各自在独立的环境中进行,而非Rapid工作流运行的环境中。这种隔离使得并发更容易一些。

3.构建结果随后可以用来运行系统级集成测试,同时进行测试部署。典型的测试部署过程是在系统测试完成之后,在生产环境中启动一系列Borg任务。

4.每一步的结果都有日志记录。另外产生一份与上次发布对比包含的所有新的改动列表的报告。

Rapid可以管理发布分支与cheery picking。每个具体的cherry picking请求可以被单独批准和拒绝。

部署

Rapid经常被用来直接驱动简单的部署流程。它可以根据Blueprint文件定义的部署规则,利用具体的任务执行器(executor)来用新构建的MPM包更新Borg任务。

我们使用Sisyphus,SRE开发的一个通用的发布自动化框架,来执行更为复杂的部署任务。一个发布(rollout)是由一个或多个任务组成的一个逻辑工作单元。Sisyphus提供了一系列可扩展的Python类,以支持任意部署流程。同时,它还有一个监控台,可以用来详细控制每个发布的执行,以及监控发布流程。

在典型的集成流程中,Rapid在某个Sisyphus系统中创建一个新的发布。Rapid知道自己构建的MPM包的build标签,可以在创建发布时指定这个标签。Sisyphus可以利用这个build标签来指定究竟使用哪个MPM版本进行部署。

Sisyphus,可以支持简单的发布流程,也可以支持复杂的发布流程。例如,我们可以立即更新所有的相关任务,也可以在几个小时的周期内,一个接一个地更新集群版本。

我们的目标是让部署流程与服务的风险承受能力相结合。在开发环境或者预生产环境中,我们可能会每小时构建一次,同时在所有测试通过之后自动发布更新。对于大型面向用户的服务来说,我们可能会先更新一个集群,再以指数速度更新其他集群直到全部完成。对敏感的基础设施服务来说,我们可能会将发布扩展到几天内完成,根据这些实例所在的地理位置交替进行。