亚马逊AWS官方博客
使用Terraform与事件驱动的AWS CodeBuild提升云上数据应用运维效率
背景信息
企业客户在云上部署的一系列数据应用的过程中,数据开发团队往往负责脚本内容,而其背后一系列云上资源的管理通常由一支云运维职能团队通过IaC(Infrastructre as Code)实现。然而,当数据开发团队开发及部署相应脚本内容时,不可避免会涉及到云上资源的变动,如Glue、Lambda的资源增改等。这就造成了两个团队在职能边界上的紧耦合:数据开发团队的迭代内容都需要提报需求至云运维团队进行相应IaC的运维,双方都增加了工作量。
优化方案概述
为了减轻数据应用代码增改给双方带来的额外压力,本文通过一个案例入手,优化数据应用增改及部署过程中的关键流程:数据开发团队通过接口化的形式调用相应Terraform module,配合AWS CodePipeline或EventBridge驱动的事件模式来实现CI/CD流水线。
此案例中,云运维团队负责IaC模块的部署和运维,使用Terraform Cloud Workspace进行IaC代码发布与管理。数据开发团队负责针对具体的ETL任务场景开发Glue脚本,使用CodeCommit进行代码管理,使用CodeBuild实现CI/CD内容,最后通过CodePipeline或EventBridge实现CI/CD流水线的串联。两支团队配合实现以下场景:
“某企业hr部门需要将某数据源摄取至MySQL中供下游数据应用使用。在数据工程师完成Glue脚本开发后,使用云运维团队开发的Glue模版批量新建Glue脚本(Python shell模版)资源。在后续数据工程师新建或修改Glue脚本时,这一套流水线能自动捕获CodeCommit中的变更内容,并同步内容至s3。s3的变更将会直接反应至Terraform中触发新建/更新资源的功能,不需要IaC开发/云运维团队的介入。”
下文的优化方案将会清晰定义云运维团队和数据开发团队在开发、维护云上数据应用时的责任边界。
实施步骤
(1) 统一流程与规范
数据开发团队与云运维团队间确认关键流程及步骤,包括CI/CD流水线如何实现,Glue脚本的上传方式和存储位置,资源所需的配置信息(如实例类型,所需的IAM权限,网络)等。
(2) Terraform脚本开发
云运维团队负责Glue资源的IaC脚本开发,内容包括:配置参数,新增/变更资源的代码。开发好的内容会统一放置在glue-etl目录下。此目录中内容示例如下:
云运维团队对glue-etl模块进行封装(module)以及发布至Terraform Cloud相应的Workspace内。
上述glue-etl模块中包含以下内容:
- tf中包含了此module输出的一系列参数。
- tf包含了对AWS环境中已有的一些资源的引用,如:当前所在区域,当前用户信息,Glue脚本所需要访问的数据库所在的Secret Manager密钥串,和部署Glue资源所需的子网组等必要信息。
- tf中包含了Glue执行时所需的IAM角色对应的相关IAM Policy集合。
- tf中包含了需要用户调用此module需要传入的一系列配置参数。
- tf文件中包含了根据上述配置批量创建Glue资源的主要流程。使用for_each和count关键词,可以实现批量新建单规格的Glue Connection、Glue作业以及Glue Crawler、Catalog等。
由于篇幅问题,上述.tf具体代码内容已略去。
(3) 监听s3内容变更
在云运维团队完成glue-etl module的开发与上传至Terraform Workspace后,数据开发团队需要初始化一份.tf文件,使用local关键词将脚本上传路径(如下方代码块中的变量bucket_name, job_path_prefix和line_of_business中)添加到.tf文件中。
第二步,通过Terraform提供的data.aws_s3_bucket_objects获取Glue脚本在s3上的存放路径。
下一步,配置Glue module所需的输入参数。以下示例中展现了如何通过字符串操作将Glue作业名与上传的脚本名进行对应(映射规则可以自定,本例中以.py文件前缀作为Glue作业名,见Figure 8),并放入job-name-map的local变量中。在实际应用中,您有可能需要配置不止一个local变量作为module的输入参数。
最后,通过调用在Terraform Cloud Workspace中的module(此例中为glue-etl)批量创建某一规格下的Glue Python shell脚本。
(4) 实现CodeBuild驱动的CI/CD流水线
本文使用EventBridge来串联CodeCommit与CodeBuild,您也可以根据使用习惯选择AWS CodePipeline实现同样的功能。在开始之前,请您务必确保相应的AWS CodeCommit与CodeBuild已经被初始化。
设置CodeCommit仓库增、改事件触发的EventBridge规则,如下所示。
为此规则配置Input Transformer,分别定义输入路径及输入模版,如下所示:
配置buildspec.yml,体现CI/CD流水线具体流程。本例中,流水线内容包括:
- 安装git-remote-codecommit以及其他代码中所需的Python依赖包(本例中使用Makefile安装依赖)或命令(如本例中的Terraform)
- 实现对ETL脚本或.tf文件代码的CI过程,如代码质量检查,语法检查,安全漏洞扫描,Unit Test等
- 当CI过程结束后,同步CodeCommit中更新的代码至存放Glue内容的s3路径中。当s3收到更新代码后,进行以下操作:
- Terraform的语法检查(terraform fmt, validate & lint)
- 资源变更检查(terraform plan)
- 最终发布(terraform apply)
将buildspec.yml文件上传至CodeCommit对应仓库内,新建CodeBuild项目并指向该仓库,使用EventBridge作为事件触发器监听CodeCommit内容变更,并将事件输出至CodeBuild,实现一整套CI/CD流水线。架构如下所示:
注意事项
- 为了实现上述解决方案,您需要注意各AWS服务间的访问权限,所需的IAM角色执行权限是否足够等问题。
- 本文讨论的方法对于不同配置的Glue脚本,无法实现资源新建的完全自动化。需要数据开发团队重新调用对应Terraform module并按需重复上述流程。
- 本文提供的方案仅针对使用Amazon Code组件管理代码版本以及发布的场景。对于外部代码管理组件及CI/CD工具,本文不做进一步探讨。
总结
本文通过一个具体的案例,展现了数据开发人员通过Terraform Cloud Workspace调用远端IaC模块(module),结合EventBridge驱动的AWS CodeCommit和AWS CodeBuild开发CI/CD流水线,自动捕获数据应用脚本内的变更内容并批量创建相应的云上资源。通过对数据应用相关的资源管理与代码变更发布流程的自动化,云运维团队减轻了代码资产新增/变更带来的管理压力 – 他们不再需要关心数据应用中的代码增改带来的额外工作量,而数据开发团队也可以专注于ETL脚本的代码开发及运维,不需要担心代码变更对云上资源带来的后续影响。
参考文档
[2] 利用Input Transformer定制EventBridge的事件信息