tencent cloud

文档反馈

Terraform 在 Github 中的应用

最后更新时间:2023-04-20 10:30:20

    本文介绍如何将 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. 项目结构主要分为environmentsmodules两个目录。

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

      说明:

      • dev 中演示创建一个 vpc。
      • prod 中演示通过 workespace 进行业务隔离。在 cicd 目录中创建 vpc, 在 qta 目录下创建容器集群。
    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 fmtterraform initterraform validateterraform 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 
                        
                    
                
    

    创建部署流水线

    name: Apply
    on:  pull_request:    types:      - closed    branches:      - main
    
    jobs:  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
    
    联系我们

    联系我们,为您的业务提供专属服务。

    技术支持

    如果你想寻求进一步的帮助,通过工单与我们进行联络。我们提供7x24的工单服务。

    7x24 电话支持