1.4.5.1. 持续集成流水线的治理
目前持续集成流水线已经成为了许多软件项目的标准配置,也是要推进我们所说的大规模 Terraform 模块治理的基础,没有持续集成流水线,我们我们就无法强制所有模块遵循我们确立的各种标准和规范。
市面上有许多非常优秀的持续集成解决方案,考虑到 Terraform Registry 默认从 GitHub 仓库同步 Terraform 模块,以及 GitHub Actions 本身已经是一个非常成熟和被广泛应用的流水线方案,所以本书将以 GitHub Actions 为主。
凭借直觉,我们可以利用各种成熟的 Action 拼接一个简单的流水线,例如:
name: Terraform CI
on:
pull_request:
jobs:
terraform:
name: Terraform Validation and Planning
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Terraform
uses: hashicorp/setup-terraform@v3
- name: Terraform Validate
run: terraform validate
- name: Terraform Plan for each example
run: |
has_error=false
if [ ! -d "examples" ]; then
echo "No 'examples' folder found."
exit 0
fi
cd examples
for d in */; do
if [ -d "$d" ]; then
if ls "$d"/*.tf > /dev/null 2>&1; then
echo "==> Checking $d"
cd "$d" || { echo "Failed to enter directory $d"; has_error=true; cd ..; continue; }
terraform init -input=false || has_error=true
terraform plan -input=false || has_error=true
cd ..
else
echo "No Terraform configuration files found in $d, skipping."
fi
fi
done
cd ..
if [ "$has_error" = true ]; then
echo "At least one 'examples' folder failed."
exit 1
fi
echo "All 'examples' folders passed."
exit 0
上述工作流在维护单个 Terraform 模块的代码仓库时还可以勉强发挥作用,然而当我们要同时维护数百个模块的代码仓库时,这种方法就会暴露出以下问题:
- 重复维护:每次需要更新工作流程逻辑时,必须在所有仓库中手动修改,工作量巨大,容易出错。
- 一致性问题:手动更新可能导致不同仓库之间的工作流程版本不一致,增加了维护难度。
- 扩展性差:难以快速引入新的功能或最佳实践,因为需要在所有仓库中逐一实施。
试想一下,假如我们决定要在 terraform init
之前添加一条检查,确认所有 Terraform 代码都已经被正确格式化了,我们就需要向数百个代码仓库提交相同的变更,这将是一个非常糟糕的体验。
1.4.5.1.1. 可复用工作流程和复合操作
GitHub Actions 提供了两种机制来实现工作流程的复用和模块化:
1.4.5.1.1.1. 可复用工作流(Reusable Workflows)
可复用工作流允许我们将整个工作流程定义为一个独立的 YAML 文件,并在其他工作流程中通过 uses
关键字引用它。这使得多个仓库可以共享同一个工作流程定义,从而实现集中管理。
优势:
- 集中管理:所有的工作流程逻辑集中在一个仓库中,便于维护和更新。
- 减少重复:避免在多个仓库中复制相同的工作流程代码。
- 版本控制:可以通过 Git 标签或分支来控制工作流程的版本,确保不同项目使用兼容的版本。
使用方法:
- 在一个仓库中创建可复用工作流程文件(例如
.github/workflows/terraform.yml
),并在on
字段中添加workflow_call
触发器。 - 在其他仓库的工作流程中,通过
uses
关键字引用该可复用工作流程,例如:
jobs:
terraform:
uses: org-name/repo-name/.github/workflows/terraform.yml@v1
secrets: inherit
这样,所有引用该工作流程的仓库都会自动使用最新的定义,简化了维护工作。
1.4.5.1.1.2. 复合操作(Composite Actions)
复合操作允许我们将多个步骤组合成一个自定义的操作,可以在工作流程的步骤中调用。这对于封装常用的步骤组合非常有用,例如 Terraform 的初始化、格式检查和验证等。
优势:
- 模块化:将常用的步骤组合成一个操作,便于复用。
- 简化工作流程:调用复合操作可以使工作流程文件更简洁。
- 易于维护:更新复合操作的逻辑会自动影响所有引用它的工作流程。
使用方法:
- 在仓库中创建复合操作目录(例如
.github/actions/terraform-setup
),并在其中创建action.yml
文件,定义操作的输入和步骤。 - 在工作流程中,通过
uses
关键字调用该复合操作,例如:
steps:
- uses: ./.github/actions/terraform-setup
通过这种方式,我们可以将常用的操作封装成模块,供多个工作流程复用,提高了工作流程的可维护性和一致性。
1.4.5.1.2. 中央操作仓库 (Centralized Actions Repository)
如果我们只是把可复用工作流和复合操作的定义 YAML 文件保存在每一个 Terraform 模块的代码仓库中,那么我们实际上没有任何改善,每一次的更新还是需要同时升级数百个代码仓库。我们可以采用集中式管理的策略,将可复用的工作流程和复合操作集中存放在一个专用的仓库中。这样,所有的模块仓库都可以引用这些集中管理的工作流程,实现统一的 CI/CD 流程。
1.4.5.1.3. 实践案例:集中管理 Terraform 模块的 GitHub Actions 工作流程
在大规模维护 Terraform 模块时,集中管理 GitHub Actions 工作流程可以显著提高效率和一致性。以下是两个采用集中式管理策略的组织案例:
1.4.5.1.3.1. Cloud Posse 的集中式工作流程管理
Cloud Posse 通过 cloudposse/github-actions-workflows 仓库,集中管理其组织内的可复用 GitHub Actions 工作流程。这些工作流程涵盖了从构建、测试到部署的各个阶段,供多个仓库引用,确保了 CI/CD 流程的一致性和可维护性。
此外,Cloud Posse 还提供了 cloudposse/github-actions-workflows-terraform-module 仓库,专门用于管理 Terraform 模块的工作流程。通过在模块仓库中引用这些集中管理的工作流程,Cloud Posse 实现了工作流程的标准化和集中维护。
1.4.5.1.3.2. Azure Verified Modules 的 Scaffold 项目
Azure Verified Modules 提供了 Azure/tfmod-scaffold 项目,作为 Terraform 模块的模板,包含了标准的 GitHub Actions 工作流程、Makefile 和脚本。开发者可以基于该模板快速创建新的模块仓库,确保了项目结构和工作流程的一致性。