随着用户在 UCloud 上资源用量的指数增长,传统 API/SDK 手动编写脚本的资源管理方式已经无法满足其需要。为此,UCloud 研发团队基于 Terraform 编写了一套自己的资源编排工具,帮助用户降低云上资源的管理成本,为其提供安全可靠、高度一致的产品使用体验,尽可能消除迁移上云时的风险。
Terraform 代表了业界前沿的技术和标准,我们基于此,并配合 UCloud CLI 等工具,编写了新一代 UCloud 资源编排工具,进一步拓展 Terraform 的功能,实现基础设施可编程。在一个通过 ULB 卸载流量至云主机的案例中,相比于传统方式,新方案下的构建时间从原先的 3 分 20 秒缩短至 43 秒,编排的效率、稳定性和可描述性都得到了显著提升。
Terraform 是 Hashicorp 公司开源的一种多云资源编排工具,目前已经形成完整生态,并与多家主流云厂商建立合作。
使用者通过一种特定的配置语言(HCL, Hashicorp Configuration Language)来描述基础设施,由 Terraform 工具统一解析,构建资源之间的关系,生成执行计划,并通过调用 UCloud 公有云 API 来完成整个基础设施生命周期的管理。
相对于其它的云上资源管理方式,Terraform 的主要特点有:
1. 有广泛的兼容性,目前海内外累计已有超过 40 家公有云厂商支持,其中包括 UCloud 在内的 4 家国内云厂商,另有 200 多个软件服务商为其提供支持。
2. 基于 IaC(基础设施即代码,Infrastructure as Code)的设计,可以将基础设施以一种领域特定语言描述出来,消除了在基础设施自动化时描述语义上的歧义,同时减轻人为因素造成的不确定影响。
3. Terraform 在执行编排动作前,会生成一份可读性良好的执行计划,关键基础设施的变更可以得到充分审查,保证了基础设施的可靠性。
4. 基于 DAG(有向无环图,Directed Acyclic Graph)描述资源与资源之间的关系,由于 DAG 良好的拓扑性质,当资源属性与资源关系发生改变时,变更动作将被充分并行地执行。
(图片来源于Terraform)
下图是一张资源编排与传统资源管理方式的对比表:
表格1:资源编排与传统资源管理方式对比
可以看出,在自动化 DevOps 环境下,资源编排相对传统资源管理方式具有明显优势,目前已覆盖了 IaaS 层的核心产品,但随着时间的推移,将来 UCloud 资源编排会支持更多的产品。
用户可以很容易的从Terraform受益,因为初始化云服务时若缺少资源编排工具,将投入大量的时间成本,而且对于云上资源的变更,往往需要很复杂的变更逻辑以保证基础设施的安全性。
UCloud 资源编排工具能够很好地解决如下常见的问题:
- CI/CD 自动化资源管理
- 高峰期应用缩扩容
- 部署复杂资源拓扑(例如两地三中心的应用架构)
例如,驿氪作为一家SaaS解决方案提供商,已经将UCloud Terraform编排系统接入自身业务。
下图是驿氪业务架构的示意图。它同时使用了多家云服务,需要统一的资源管理平台进行多云管理,而独立研发一套资源管理平台,需要对接各云厂商接口,同时还要研发人员深入了解各家云服务的产品细节,这无疑会加重企业的研发成本和运营成本。
而在应对SaaS 业务时,Terraform可以灵活的动态调整资源,用户只需要调整部分参数,就可以利用模板进行非常快速的资源管理,相较于自建管理平台,UCloud Terraform可以极大节省用户的运营成本和效率。
以首次执行 Terraform 创建 UCloud 云上资源为例,这一资源编排动作的生命周期如下图所示:
图:Terraform 生命周期
图中立方体所示分别为:
- Terraform 核心进程:负责资源定义文件,构建有向无环图,管理状态存储;
- Provider 进程:即提供资源编排能力的进程,包括由云厂商实现的能力(比如 UCloud 的资源编排实现),和应用程序提供的能力(比如 TLS 自签名证书)等;
- Provisioner 进程:即提供资源编排后处理操作的进程,比如执行 Shell 命令,上传文件等。
以中央的有向无环图为分界线,左侧的部分是 Terraform 本身提供的能力,右侧是由云厂商提供的能力。
Terraform 核心的良好抽象,保证了资源编排的安全和稳定,为 UCloud 资源编排提供了坚实的工程基础。
在一个生产环境的资源编排系统中,往往要依赖数目庞大的云资源后台管理服务。资源编排的工程实现中,以下几个方面的根本诉求需要首先得到保障:
- 保障资源编排在复杂终端环境下的成功率。这个是最基本也是最核心的诉求。
- 保障产品的一致性。使用户可以平滑迁移,变更无感知。
- 保障产品的工程质量。资源编排作为关键基础设施的接入方式,本身需要足够稳定可靠。
下文,我们将详细分享 UCloud 在基于 Terraform 的资源编排工具研发中,在容错能力、接入能力和工程能力优化上的一些实践。
容错能力是衡量系统可用性的一个重要维度,资源编排作为 UCloud 服务的入口,本身必须足够稳定,具有对故障可以做出合理应对的能力,包括对上游服务异常的容错能力,以及对于输入异常的纠错能力。
首先,Terraform 的杀手级特性是执行计划与过程分离,用户在执行真正的资源编排动作变更现网基础设施之前,可以先生成执行计划,比较资源定义文件和当前资源状态的差异,检查关键基础设施的变更。
UCloud 在实现资源编排的过程中,借助 Terraform 执行计划的 CustomDiff 特性,自定义了部分资源的 Diff 过程。比如,两个地域之间仅能存在一条高速通道(UDPN),如果执行编排动作前已经存在了一条高速通道(UDPN),将会把所有的编排动作阻止在执行计划阶段,提高终端用户的使用效率。
图:自定义 Diff 以在执行计划中检查输入
对于错误的处理,UCloud 编排工具通过梳理整个编排工作流的生命周期,将错误信息严格压缩在(动词、附加动作、资源名、ID)这个形式化的四元组中,转化为人类可读的描述信息反馈给使用者,对于输入异常可以在提供一定的交互纠错能力的前提下,精确定位到源码行。
图:错误信息四元组的自然语言表示样例
其次,UCloud 通过下文介绍的 API 一致性工程,识别出了所有操作的幂等性质(即该操作是否存在副作用,导致真正的资源创建),并对所有幂等(无副作用的)操作执行自动重试,大幅提升了编排工具的容错能力,同时保证了自动重试机制是真正安全的。对于非幂等操作,得益于 Terraform 的状态管理机制,可以简单地重新执行编排计划,仅重试失败的创建过程。
UCloud 编排工具还提供对于异步操作的同步封装,使用 Terraform 内建的等待机制,创建资源后,将会轮询等待资源完成可以查询方才返回成功,保证操作的原子性和资源状态的一致性。
最后,对于上述的重试或等待机制,使用指数级增长的间隔(Exponential Backoff),以及优雅退出(Gracefully Shutdown)的方案,进一步提升资源编排的容错能力。
基于 Terraform 的资源编排有一定固有的局限性,比如其本身更适合基础设施的构建,不适合 adhoc 的临时日常工作,比如列表查询和开关机这样的操作。
如要批量重启主机,使用 Terraform 的做法是使用 data source 查询出对应的数据,定义输出变量,再将输出变量值作为参数传递给外部的脚本。在这样的即席查询场景下,相对于 Ansible 等配置管理工具并没有明显的优势。
因此 UCloud 在资源编排之外,开发了 UCloud CLI 工具来扩展资源编排的能力。例如,使用 CLI 来查询和重启通过 UCloud 编排工具创建的资源:
UCloud 实现了资源编排与 UCloud CLI 的集成,资源编排工具可以直接使用 CLI的权限配置信息。也可以通过编排工具的特性,调用 UCloud CLI 进行额外的资源管理操作。
图:Terraform 与 CLI 集成用法示例
打通资源编排与 UCloud CLI 之后,资源编排可以复用 CLI 即席查询的能力,而CLI 可以复用资源编排所持有的资源拓扑信息,例如主机列表,网络 CIDR 信息等,极大拓展了双方的的产品接入能力。
UCloud 资源编排从立项之初,就将终端用户使用上的一致性和可用性作为核心诉求。要满足这些诉求,在工程上必须攻破几个关键的技术难关:
1. 尽可能使用户实现跨版本、跨云的平滑迁移。
2. 同时对资源编排工具所依赖的基础 API 的实现自动化管理,从源头上提高编排工具的可用性。
3. 资源编排作为关键基础设施的接入方式,本身需要足够的质量保障措施。
平滑迁移
首先,对于资源编排工具的升级,UCloud 严格按照 Terraform 的 Schema 变更策略,每当资源的属性有破坏性的变更,都会随之提供版本迁移的实现,使终端用户在升级工具时,自动将其资源状态平滑迁移至新版本。
其次,对于云平台之间的迁移,UCloud 实现了通用的风格转换函数,通过将 UCloud 接口的大写驼峰(Camel)命名,统一映射成 Terraform 常用的小写下划线(Snake)风格,并使用 Terraform 建议的产品命名法,降低用户的跨云迁移成本。终端用户只需要少量改动模板,即可通过资源编排工具平滑接入 UCloud。
变更自动化
资源编排作为 UCloud 重要的产品接入方式,对于 UCloud 全线产品都有很强的依赖,接口变更对接时的一点微小错误,都可能导致破坏性的后果。
所以一致性工程的重要目标是,快速响应产品新特性的变更,同时尽可能降低人工成本,使变更自动化,减少错误的发生。
为了使 API 能够得到统一管理,同时防止产品间竖井式的信息隔离,UCloud 很早以前就打造了公共、统一的 API 管理平台,将所有现网 API 的定义收敛至统一的 API 注册中心上,使用自定义的格式来形式化地描述 API Schema。API 管理平台将 API 的场景抽象成测试集(Test Set),一次 API 的调用抽象成测试用例(Test Case),并使用自定义的表达式语法构造随机的参数注入到用例中执行。
图:API 管理平台示意图
基于 API 管理平台,UCloud 资源编排团队编写了 API SDK 的自动化生成程序,通过严格形式化的 API 定义,转译成 Go SDK 代码。同时通过编写一个递归下降的表达式解析器,将测试用例中表达式语法,转译成等价的 Go 代码。实现了 API 定义和 Go 代码的直接映射,低成本同步上游变更。
图:通过编写 API 建模工具转译 API SDK 代码
此外在这个过程中,UCloud 通过在 API 管理平台与 SDK 之间编写 API 建模工具,用以抽象出一个中间层,在该层统一标注出 API 的幂等性质,为资源编排工具提供了真正安全的重试机制。
这样就完成了整个调用链路上的接口一致性工程建设,实现了从 API 管理平台到 SDK 到 Terraform 的完整语义映射,降低了 SDK 的开发和维护成本,同时消除了人为变更带来的不确定影响。
质量工程建设
资源编排作为大规模云上资源管理的推荐方式,涉及到关键基础设施的操作与管理,编排工具本身的质量十分关键。
表格2:资源编排持续集成检查表
如表2所示,作为一个开源项目,UCloud 资源编排工具共有三个质量周期,
- 开源协作周期,使用 Travis CI 进行代码风格检查和单元测试,不会发起真正的 API 请求;
- 合并主分支周期,UCloud 使用 Gitlab CI on Kubernetes 进行风格检查、单元测试和集成测试,其中集成测试会调用现网 API 操作真正的云上资源,并在每天凌晨进行 Daily Regression;
- 发布正式 Release 到 Terraform 官方仓库周期,合作方 Hashicorp 使用 TeamCity 进行全量验收测试,当所有测试完成后,发布新版本。
为了保证代码不会随时间腐化,提前清除一些隐患,比如拼写错误、安全密钥泄露、抽象不合理等等,UCloud 接入产品团队选取了三种不同维度的静态检查工具来量化代码质量,其中包括:
- GoReportCard,用来做最基本的风格检查
- SonarCloud,发现代码的 Bug 和安全问题
- Gocyclo,计算函数的圈复杂度(圈复杂度是用来衡量一个函数复杂程度的指标,和控制流的复杂程度相关)
并通过周期性的代码优化,将代码质量的量化指标始终维持在 A+ 评级。
经过长时间的发展,Terraform 已经成为一个业内通用的资源编排工具,且近年来海内外的友商也陆续开始支持基于 Terraform 的资源编排系统,证明了业内对通用资源编排系统的强需求。
UCloud 深入研究了 Terraform 的内部机理,并基于此为 UCloud 下一代资源编排系统进行了深度的探索,在研发过程中多次优化,打通整个链路上的基础工程建设,最后通过充分的质量工程实践,为资源编排的可靠性与稳定性保驾护航。UCloud Terraform 的具体使用细节和样例请点击阅读原文至 UCloud 资源编排官方文档查阅。