暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【连载】践行“配置即代码” ,看Facebook怎么做

持续交付2.0 2020-04-01
611

本连载内容来自 Facebook Research 网站(https://research.fb.com/),有感兴趣的同学可以搜索该英文网站。


我们在上一篇文章中提到,Facebook的配置项管理,主要应用于以下一些场景:

  • 新产品功能开关

  • 进行试验

  • 应用级别的流量控制

  • 拓扑设置和负载平衡

  • 监视、警报和补救

  • 对机器学习模型进行更新

  • 控制应用程序的内部行为


而所有这些配置项均使用下图的工具集进行管理。


图 中,Mobile Config支持移动应用程序。其它的工具用于支持在数据中心运行的应用程序。Configerator )提供了所有的基本功能,包括版本控制(version control)、配置编写(authoring )、代码审查( code review )、自动金丝雀测试和配置分发。Gatekeeper  控制了产品新功能的滚动发布(rolling out)。Package Vessel ,它是使用点对点文件传输技术,用来分发大型配置(例如,机器学习模型的GBs)。Sitevars 是一个shim层,是Facebook最早的一个配置工具,为前端PHP产品提供易于使用的配置API

今天,我们主要讨论的是最基础的配置工具 Configrator。Configerator解决了配置编写配置错误预防大规模配置分发方面的挑战。

一、配置就是代码

这个工具的两个基本假设前提是:

  1. 大多数工程师喜欢编写代码来生成配置(即配置文件),而不是手动编辑配置;
  2. 大多数配置程序比原始配置本身更易于维护。

关于这两个假设前提是否成立,我们将在后面文章会通过一些数据来验证。本文暂时放置在一旁。

我们认为“配置就是代码”。所以,Configerator  将配置作为代码一样对待。下图是配置代码的一个示例。所有配置项的data schema 是用平台无关的Thrift语言定义的(参见“job.Thrift”)。

图中,工程师编写两个 python 文件“create job.cinc”和“cache job.cconf”来操作thrift对象。调用“export if last()”将配置作为一个 JSON 文件写入。

为了防止无效的错误配置,工程师编写了另一个 python 文件 “job.thrift-cvalidator”来检查配置项的不变量。配置编译器把 Python 和 Thrift 编写的源代码生成一个 JSON 文件,并会自动调用验证器(Validator)来验证 “job” 类的每一个配置。 

配置程序和生成的 JSON 配置的源代码存储在版本控制工具(如 GIT )中。工程师使用“开发服务器”,其上有 git 的代码克隆。他编辑源代码,并调用  Configerator  编译器生成 JSON 配置。配置变更还可以由工程师通过Web UI,或者由调用“mutator”组件提供的API的自动化工具以编程方式启动。

示例中,将 create_job.cinc 与 cache_job.cconf 分开。这样的话,前者作为一个公共模块,可以被重用,为其他类的作业创建配置项。另外,可能还有三个不同的团队会编写或修改配置代码,它们是调度团队缓存团队安全团队

调度器团队实现了调度器,并提供出共享的配置代码,包括配置范式{config schema} job.thrift、可重用的create_job.cinc模块,以及一个验证器( job.thrift-cvalidator),用于确保其他团队提供的配置不会意外中断调度器的运行。

缓存团队通过简单地调用create作业(name=“cache”)来生成缓存作业的配置。

安全团队通过简单地调用create作业(name=“security”)来生成安全作业的配置。

二、维护配置代码比手工维护Json容易

为什么维护 配置代码 比手工编辑 JSON 配置要容易呢?关键就在于:代码可以模块化和重用。例如,通过 import thrift() 和 import python() 可以把配置依赖项显示地声明成代码依赖项。下面就是一个例子。

上图中,“app.cconf” 表示 某个应用要监听一个特定的端口。“ firewall.cconf ” 表示 操作系统允许那个端口的流量访问。二者都依赖于 “ app_port.cinc ”。Configrator 工具中包含的依赖服务( Dependency Service,见下图)会自动从两个源文件中抽取出依赖关系。如果在 app_port.cinc 文件中的 APP PORT 被修改了,Configerator 编译器会重新编译 “app.cconf ”和 “firewall.cconf ”。并将刚刚生成的所有JSON文件一次性提交到Git仓库,从而保证它们的一致性。依赖关系可以使用任何 Python 语言的结构表达,而不仅仅是常量。

三、通过 UI 和Sitevars改善易用性

Configerator 被设计用来支持所有场景的统一平台。它必须有足够的灵活性和自表达性(expressive),以便支持比较复杂的配置项。然而,对于一些非常简单的配置项来说,使用这种 Python 和 Thrift 模式,并没有太多收益。所以,Configerator还提供一个界面,让工程师可以直接编辑某个 Thrift 配置项的数值,而不用编写代码。这个界面平台会自动生成 Configerator 所要求的代码。

Sitevars 工具在 Configerator 之上很薄的一层,用于支持前端 PHP 网站产品的简单配置。它提供了可配置的 key-value 键值对。这其实就是 PHP 表达式。工程师可以使用 Sitevars 界面轻松更新某个sitevar的PHP内容,而不需要写 Python 和 Thrift 代码。

一个sitevar( 其实就是一个配置项)可以使用一个用 PHP 实现的检查器(checker)去验证不变量(invariants),这种检查器类似于第二个图中的那个验证器( validator )。由于PHP的弱类型检查,sitevars 更容易出现配置错误,例如 笔误( typos)。

所以,我们鼓励工程师为新创建的 sitevar 定义其自用的数据模式(data schema),而工具自动从它的历史值中推断出数据类型。例如,它会推断这个 sitevar 字段是否为字符串。如果是字符串的话,它会进一步推断是一个 JSON 字符串,还是一个时间戳字符串,或一个通用字符串。如果工程师修改了系统推断出来的数据类型,这个UI会显示一个警告信息。

四、防止配置项变更的错误

配置错误是网站出现问题的主要原因。我们使用全方位方案来阻止配置错误,它包括:

  • 配置验证器来确保不变量(invariants)没有遭到破坏

  • 对配置程序和生成的 JSON 配置进行代码审查(Code Review);

  • 手工进行配置测试;

  • 自动化的集成测试

  • 自动化的金丝雀测试(灰度)。

以上这些手段彼此互相补充,用来捕获配置错误。我们用上面的图3来解释这件事。

例如,当对一个新增配置项进行手工测试时,工程师只要运行一个命令,就能临时将这个新的配置项部署到某些生产服务器或测试服务器上,去验证所有系统是否仍旧正常工作。

一旦验证通过,满足需求,工程师就会将这部分源代码,JSON配置,以及测试结果提交到 Code Review 系统,就是Facebook内部使用的 Phabricator工具平台。

假如这个配置项与前端网站 www.facebook.com 相关,那么我们有一个沙箱环境(叫“Sandcastle”的工具),就会使用这个新的配置项自动化地执行全面、综合且持续的网站集成测试。Sandcastle 会将测试结果发布到 Phabricator工具,Code Reviewer 就可以查看到结果。

一旦这次提交被批准,工程师就可以将这个配置变更发布到远程的 “金丝雀服务(Canary Service)”。

金丝雀服务( canary service )会在生产环境中的一个子集中使用真实流量自动化测试这个新配置。工程师要完成了手工测试和自动化集成测试。手工测试是执行那些很难做成自动化的测试用例,但是由于失察或在时间压力下的忽略,可能会导致遗漏了一些配置错误。在沙箱上的持续集成测试可能有比较大的覆盖率,但由于沙箱环境的机器少或与生产环境略有差异,也会遗漏了一些。

一个配置与一个金丝雀规格说明( spec)相关,这个规格说明描述了如何在生产环境上对这个配置进行自动化测试。而且,这个规格说明(spec)也定义了多个测试阶段(multiple testing phases)。

例如,阶段一是在20台机器上进行测试;阶段二是有上千台机器的整个集群上测试。针对每个阶段,它都指定了测试目标服务器、以及健康检查指标集( healthcheck metrics),以及判断这个测试是否成功的预期值。例如,从使用新配置项的服务上收集的点击率 (CTR)应该比使用旧配置的服务器的点击率多(或少)X%。

这个金丝雀服务与被测服务器上的代理(“Proxies”)通讯,临时部署这个新的配置项。如果新的配置通过了所有的测试阶段,这个金丝雀服务会要求远程的“Landing Strip”将这个配置变更提交到主仓库master中。


  1. 03.26:Facebook配置管理(一):海量服务配置项的管理挑战

  2. 03.30:Facebook配置管理(二):配置管理所用的工具集

  3. 04.01:Facebook配置管理(三):配置的编写和错误预防

  4. 04.03:Facebook配置管理(四):可靠的配置项分发

  5. 04.06:Facebook配置管理(五):强大的GateKeeper

  6. 04.08:Facebook配置管理(六):移动端配置工具MobileConfig

  7. 04.10:Facebook配置管理(七):配置项管理的经验与工程文化

  8. 04.14:Facebook配置管理(八):给业界提出的一些总结和建议



文章转载自持续交付2.0,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论