基础设施作为应用程序的支柱,为之提供关键的运行环境、网络连接和资源调度等支持。一旦基础设施出现故障,整个应用生态系统都可能面临严重的连锁反应,如性能降低、数据丢失乃至系统崩溃。因此,基础设施的稳定性和可靠性对于运行在其上的应用程序至关重要。 持续测试可以在基础设施的整个生命周期中进行检查,确保一切运行正常,尽早发现并解决潜在问题,减少影响扩散。此外,持续测试通过为团队提供即时的状态反馈,有助于提高基础设施的可维护性和可扩展性,进而支持业务持续增长和变化的需求。 因此,持续测试不仅是持续交付高质量软件的必要保障,对于基础设施而言,其价值和影响更为深远。 本文来分享一下我们团队是如何对基础设施进行测试的。 首先我们要识别出需要测什么。在 IaC(基础设施即代码)的实践中,我们以测试金字塔和敏捷测试四象限为指导原则,适用的测试方案包括:
明确了测试方案,我们就需要识别测试优先级,在不同阶段开展相应的测试:
市面上有很多可以测试工具可以选择:
比较来看,shell 优点是原生,直接调用服务方提供的 CLI,如 AWS CLI, Kubectl;缺点是面对复杂场景编写起来费心费力; 使用封装起来的测试库看起来很简单,但开发者日常就要使用 CLI/Curl 命令来进行基础验证,而用封装库进行开发就需要多学习一套知识;而且在被测服务发布新功能后,平台想跟进却发现测试库没能跟进,导致最后还得用原生方式来写。比如 AWSpec 支持 RDS,但是很长时间都没有支持 Aurora。如果已经写了很多测试,就只能在 Aurora 这里使用其它方式验证,最后导致各处验证方式不统一。 所以我推荐选择团队熟悉的应用开发语言的测试框架,优点如下:
我的选择则是 Ruby/RSpec,因为 Ruby 简洁自然的语法和 RSpec 的强大验证器,让测试代码中很少出现语言自身导致的难懂和多余的代码。 组件测试加上人工验证是交付环境能够成功部署的主要信心来源,而在有逻辑分支的时候,单元测试可以用来成为对组件测试的补充:组件测试验证代码的主干,单元测试在部署前来验证分支,以实现对代码的测试全覆盖。 下面我们基于 Terraform 实现,以单元测试和组件测试为例进行测试。其它 IaC 实现和不依赖外部工具的测试都可以参考来实现。 注意这些由代码变化产生的测试都应在 Pipeline 的流水线中,而不是手动触发。任何不拦截在上线必经之路的测试,最终都将无人理睬。 单元测试 在 Terraform 中,通常需要人工来验证 terraform plan 的结果,但是它只能覆盖当前 state 和配置参数下的结果。当我们代码中包含逻辑时,我们就需要通过配置 local backend、不同配置和 state 文件来本地验证对应的 plan 结果。示例: 检查 plan 结果 在部署流水线中,通过 terraform plan 加人工验证。在测试环境中 apply 后,人工测试来保证正确性。验证完成后,对于后续环境来说在测试环境的 plan 结果就是其它环境的参考输入,由人工核对确认后进行 apply。 在资源生成后,我们便可以通过测试脚本调用 CLI/API 请求目标资源,来验证产生的结果与预期一致。比如服务可以被成功访问、数据库确实被创建出来并配有正确的参数,密钥管理器中被保存下来的数据库密钥我们可以成功连接到数据库等等。与应用测试一样,任何一条失败的测试都应让我们的 Pipeline 变红,向团队告警。并确保只有在前一个环境被验证通过后,我们才向下一个环境前进。 我们以 Ruby/RSpec 为例。在一个代码库中,以生成的目标资源上下文划分测试文件。 比如对于 RDS 数据库的创建,我们可以组织这三个文件:
一个文件中的组织结构如下: 下面是一个验证 RDS 的 DB parameter 按预期被创建的例子: 可以看出测试代码非常的语义化,没有额外的数据结构定义和难懂的语法。看明白了这个测试,其它命令行相关的测试也就全都会写了。平台开发者们可以专注于业务验证,而不会因为测试框架带来额外的负担。 当然,只需要我们能在编写功能代码之前被测内容是什么。我们可以通过各种文档来识别出被测内容,比如 Kubectl、AWS、Vault 等 CLI,或各种服务的 API。如果我们无法识别出被测内容时,那就需要通过拆解步骤、手动部署资源等方式分析出来。像在其它语言进行测试驱动开发时一样,小步验证,红绿重构。 进行测试驱动在其它语言中带来的优点,在 IaC 也一样大部分适用:
自动化测试是高代码质量和稳定开发效率的重要保障,应用服务开发如是,基础设施因为担负着更大的使命和责任更是如此。测试驱动能帮助开发者更好的设计和实现。在 IaC 开发过程也同样适用。在工具选型上,避免选择编写成本过高和太复杂的语言和工具,大部分 Ops 们更习惯编写动态语言的脚本,方便和顺手更重要。 希望本文能对你的工程实践带来启发,从下一个 IaC feature 开始测试驱动开发。 |
|