云资源自动化 for Terraform Terraform 在 Github 中的应用

这篇说说如何将 Terraform 与 GitHub Actions 结合,实现基础设施的自动化部署,涵盖项目结构、流水线配置及检查部署流程。 项目结构:通过 environments 目录隔离环境,modules 目录封装复用资源。 流水线配置:在 GitHub 设置密钥,通过 Actions 配置检查与部署流水线。 检查与部署:按分支触发检查(fmt、init、validate、plan),合并后触发部署(app。

相关产品
云资源自动化 for Terraform 产品页,含版本规格、价格与购买入口。

这篇说说如何将 Terraform 结合 Github action 实现自动化部署。

一、前置条件

1. 注册 Github 账号。

2. 注册腾讯云账号,并完成 实名认证。

3. 获取凭证,在 API密钥管理 页面中创建并复制 SecretId 和 SecretKey。

二、创建项目

在 GitHub 中新建代码仓库,目录结构如下:

.├── README.md├── environments│ ├── dev│ │ ├── main.tf│ │ └── provider.tf│ └── prod│ ├── cicd│ │ └── main.tf│ ├── local.tf│ ├── main.tf│ ├── provider.tf│ └── qta│ └── main.tf└── modules ├── network │ ├── main.tf │ ├── outputs.tf │ ├── provider.tf │ └── variables.tf ├── security_group │ ├── main.tf │ ├── outputs.tf │ ├── provider.tf │ └── variables.tf └── tke ├── main.tf ├── outputs.tf ├── provider.tf └── variables.tf

目录结构说明:

1. 项目结构主要分为environments和modules两个目录。

2. environments为目录方式隔离环境dev和prod,用来给不同环境设置各自的配置,每个环境目录都是独立的根模块。

注意:说明:

3. modules为封装的资源信息,用以复用。本目录中包含 vpc、安全组和容器服务 TKE 的 Module 演示。

4. 完整代码请参考 gitops-terraform。

三、流水线配置

1. 为防止 AKSK 等安全信息泄流造成安全问题,你需要在https://github.com/${USER}/${PROJECT}/settings/secrets/actions设置环境变量。请替换为已复制的 SecretId 和 SecretKey。


2. 通过 GitHub Actions 配置流水线。

你可以在项目中的 actions 选项处单击 New workflow,也可以在.github/workflows/目录里通过添加 yml 文件创建,流水线配置详情可以参考相关操作。


四、检查流水线

1. Terraform 根模块资源不能过多。同理,在执行检查的时候也应该尽可能的避免全部资源的读取,需要以细粒度的方式触发检查。

2. 这篇档采用按分支区分触发的环境。例如,dev 中的配置需要更新时,只能在 dev 分支上进行更新。配置更新完成后提交 PR 将代码合入到 main(主分支)。目的是每次更新的检查不需要全量扫描 environments 下的所有子目录(环境),减少不必要的状态同步消耗。

3. 该流水线主要通过执行terraform fmt、terraform init、terraform validate、terraform plan来检查代码和展示构建计划,方便判断是否执行部署。

五、部署流水线

1. 如果检查流水线中的检查操作都成功且terraform plan的输出符合预期,那么就可以进行 merge 操作。

2. 在 merge 完成的时候触发部署(即terraform apply)的操作。示意图如下:

六、相关操作

在进入 environment 的指定环境目录后,会判断是否还有子目录,如果有则通过 workspace 隔离不同业务环境(例如 qta,ci),如果没有则等价于普通的根模块。

七、创建校验流水线

参考以下代码,下载 Terraform 和校验 Terraform 代码:

# This is a basic workflow to help you get started with Actionsname: CI# Controls when the workflow will runon: pull_request:# A workflow run is made up of one or more jobs that can run sequentially or in paralleljobs: # This workflow contains a single job called "build" build: # The type of runner that the job will run on runs-on: ubuntu-latest env: TENCENTCLOUD_SECRET_KEY: ${{ secrets.TENCENTCLOUD_SECRET_KEY }} TENCENTCLOUD_SECRET_ID: ${{ secrets.TENCENTCLOUD_SECRET_ID }} # Steps represent a sequence of tasks that will be executed as part of the job steps: – uses: actions/checkout@v3 – uses: hashicorp/setup-terraform@v2 with: terraform_wrapper: false – name: check env run: | if [ ! -d "environments/$GITHUB_HEAD_REF" ]; then echo "*************************SKIPPING************************************" echo "Branch '$GITHUB_HEAD_REF' does not represent an oficial environment." echo "*********************************************************************" exit 1 fi – name: terraform fmt id: fmt run: terraform fmt -recursive -check – name: terraform init id: init working-directory: environments/${{ github.head_ref }} run: terraform init – name: terraform validate id: validate working-directory: environments/${{ github.head_ref }} run: terraform validate – name: terraform plan id: plan if: github.event_name == 'pull_request' working-directory: environments/${{ github.head_ref }} run: | plan_info="" dir_count=`ls -l | grep "^d" | wc -l` if [ $dir_count -gt 0 ]; then for dir in ./*/ do env=${dir%*/} env=${env#*/} echo "" echo "========> Terraform Plan <========" echo "At environment: ${{ github.head_ref }}" echo "At workspace: ${env}" echo "==================================" terraform workspace select ${env} || terraform workspace new ${env} plan_info="$plan_info\\n$(terraform plan -no-color)" done else plan_info="$(terraform plan -no-color)" fi plan_info="${plan_info//'%'/'%25'}" plan_info="${plan_info//$'\\n'/'%0A'}" plan_info="${plan_info//$'\\r'/'%0D'}" echo "::set-output name=plan_info::$plan_info" continue-on-error: true – uses: actions/github-script@v6 if: github.event_name == 'pull_request' with: script: | const output = `#### Terraform Format and Style \\`${{ steps.fmt.outcome }}\\` #### Terraform Initialization \\`${{ steps.init.outcome }}\\` #### Terraform Validation \\`${{ steps.validate.outcome }}\\` #### Terraform Plan \\`${{ steps.plan.outcome }}\\` <details><summary>Show Plan</summary> \\`\\`\\`\\n ${{ steps.plan.outputs.plan_info }} \\`\\`\\` </details> *Pushed by: @${{ github.actor }}, Action: \\`${{ github.event_name }}\\`*`; github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: output })

八、创建部署流水线

name: Applyon: pull_request: types: – closed branches: – mainjobs: build: if: github.event.pull_request.merged == true runs-on: ubuntu-latest env: TENCENTCLOUD_SECRET_KEY: ${{ secrets.TENCENTCLOUD_SECRET_KEY }} TENCENTCLOUD_SECRET_ID: ${{ secrets.TENCENTCLOUD_SECRET_ID }} steps: – uses: actions/checkout@v3 – uses: hashicorp/setup-terraform@v2 – name: terraform init id: init working-directory: environments/${{ github.head_ref }} run: terraform init – name: terraform apply working-directory: environments/${{ github.head_ref }} run: | dir_count=`ls -l | grep "^d" | wc -l` if [ $dir_count -gt 0 ]; then for dir in ./*/ do env=${dir%*/} env=${env#*/} echo "" echo "========> Terraform Apply <========" echo "At environment: ${{ github.head_ref }}" echo "At workspace: ${env}" echo "==================================" terraform workspace select ${env} || terraform workspace new ${env} terraform apply -auto-approve done else terraform apply -auto-approve fi

赞 (0)
上一篇 4天前
下一篇 4天前