极狐Gitlab CI 的Terraform backend http管理

举报
kaliarch 发表于 2023/10/21 10:02:45 2023/10/21
【摘要】 Terraform是一款基础设施即代码的编排工具,可以使用代码定义和预建立基础设施,如GCE、AWS和Azure等平台。在使用Terraform管理基础设施的过程中,状态管理起着至关重要的作用。 Terraform状态用于源控Terraform管理的资源,如果丢失状态,Terraform将无法确定哪些资源已创建,将导致错误或重复创建资源。GitLab是一款基于Web的Git代码仓库管理工具,提供

一 背景

Terraform是一款基础设施即代码的编排工具,可以使用代码定义和预建立基础设施,如GCE、AWS和Azure等平台。在使用Terraform管理基础设施的过程中,状态管理起着至关重要的作用。 Terraform状态用于源控Terraform管理的资源,如果丢失状态,Terraform将无法确定哪些资源已创建,将导致错误或重复创建资源。GitLab是一款基于Web的Git代码仓库管理工具,提供Git仓库管理、代码审查、CI/CD管道、安全脚本等功能。GitLab可以很好的与Terraform进行集成,用于管理Terraform的状态。本文主要介绍如何在GitLab中管理Terraform的状态。

Terraform在执行基础设施编排过程中,为实现团队合作,其重要的state文件需要与基础设施配置代码分离,存储在外部共享存储中,默认情况下,Terraform使用名为local的后端,它将状态存储为磁盘上的本地文件。您还可以配置本文档中包含的一个内置后端。其中一些后端类似于状态文件的普通远程磁盘,而其他后端则支持在执行操作时锁定状态。这有助于防止冲突和不一致。

二 原理及功能

极狐Gitlab提供一个 Terraform HTTP 后端,以最少的配置安全地存储state文件。

在极狐GitLab 中,可以:

  • 版本化的 Terraform 状态文件。
  • 加密传输中和静止时的状态文件。
  • 锁定和解锁状态。
  • 远程执行 terraform planterraform apply 命令。

三 实现

在极狐Gitlab的CI/CD中运行terraform命令,在具体要实现的Terraform项目中,在backend.tf文件中定义HTTP后端:

terraform {
  backend "http" {
  }
}

在项目内编写.gitlab-ci.yml在其stage中执行terraform 命令

配置http 类型terraform后端状态

PROJECT_ID="<gitlab-project-id>"
TF_USERNAME="<gitlab-username>"
TF_PASSWORD="<gitlab-personal-access-token>"
TF_ADDRESS="https://jihu.com/api/v4/projects/${PROJECT_ID}/terraform/state"

terraform init \
  -backend-config=address=${TF_ADDRESS} \
  -backend-config=lock_address=${TF_ADDRESS}/lock \
  -backend-config=unlock_address=${TF_ADDRESS}/lock \
  -backend-config=username=${TF_USERNAME} \
  -backend-config=password=${TF_PASSWORD} \
  -backend-config=lock_method=POST \
  -backend-config=unlock_method=DELETE \
  -backend-config=retry_wait_min=5

配置完成后在后续基础设施执行编排过程后,可以在具体项目的基础设施->Terraform 中看到State状态文件。

四 实战

预知条件,在仓库上已经注册了gitlab runner,后期Gitlab CI/CD可以直接使用。

可以将源码仓库与Terraform State存储放在同一个仓库内

4.1 创建仓库token

创建对应权限的token,后期用于tf配置认证Gitlab进行state状态文件存储。

-iJh84Jy1bCyj4nu2vzS

4.2 配置变量

TENCENTCLOUD_SECRET_ID:为腾讯云密钥ID,用于编排腾讯云资源认证;

TENCENTCLOUD_SECRET_KEY:为腾讯云密钥KEY,用于编排腾讯云资源认证;

TF_ADDRESS:为极狐Gitlab的state认证地址,(https://jihu.com/api/v4/projects/111969/terraform/state)

TF_USERNAME:为极狐Gitlab的state认证用户名;

TF_PASSWORD:为极狐Gitlab的state认证token;

4.3 代码

  • .gitlab-ci.yml
variables:
  # PHASE: BUILD|DESTROY
  PHASE: BUILD
  REGION: "ap-beijing"
  PLAN_JSON: plan.json

before_script:
  - apk add --no-cache jq
  - export TENCENTCLOUD_SECRET_KEY=${TENCENTCLOUD_SECRET_KEY}
  - export TENCENTCLOUD_SECRET_ID=${TENCENTCLOUD_SECRET_ID}
  - export TF_REGISTRY_CLIENT_TIMEOUT=120000
  - export CHECKPOINT_TIMEOUT=500000
  - export TF_REGISTRY_DISCOVERY_RETRY=5
  - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"
  - terraform init -backend-config=address=${TF_ADDRESS} -backend-config=username=${TF_USERNAME} -backend-config=password=${TF_PASSWORD} -backend-config=lock_address=${TF_ADDRESS}/lock -backend-config=unlock_address=${TF_ADDRESS}/lock  -backend-config=lock_method=POST

# 配置缓存
cache:
  key: $CI_COMMIT_REF_SLUG
  paths:
    - .terraform/

stages:
  - init
  - validate
  - plan
  - deploy

Init:
  image:
    name: hashicorp/terraform:1.3.7
    entrypoint: [""]
  stage: init
  retry:
    max: 1
    when:
      - script_failure
  tags:
    - gitlab-runner
  script:
    - terraform version
    - terraform init -backend-config=address=${TF_ADDRESS} -backend-config=username=${TF_USERNAME} -backend-config=password=${TF_PASSWORD}
      

      # -backend-config=lock_address=${TF_ADDRESS}/lock \
      # -backend-config=unlock_address=${TF_ADDRESS}/lock \
      # -backend-config=lock_method=POST \
      # -backend-config=unlock_method=DELETE \
      # -backend-config=retry_wait_min=5

Validate:
  image:
    name: hashicorp/terraform:1.3.7
    entrypoint: [""]
  stage: validate
  tags:
    - gitlab-runner
  retry: 2
  script:
    - terraform validate
    - terraform fmt -check -recursive || echo 0
  cache:
    paths:
      - .terraform/
    policy: pull
  allow_failure: true

Plan:
  image:
    name: hashicorp/terraform:1.3.7
    entrypoint: [""]
  stage: plan
  retry: 2
  tags:
    - gitlab-runner
  cache:
    paths:
      - .terraform/
    policy: pull
  artifacts:
    paths:
      - plan.bin
      - app_config.zip
    expire_in: 2 week
  script:
    - terraform plan -input=false -out=plan.bin -var region=${REGION}
    - terraform show --json "plan.bin" | convert_report > ${PLAN_JSON}
    - cat ${PLAN_JSON}
  only:
    variables:
      - $PHASE == "BUILD"

Apply:
  image:
    name: hashicorp/terraform:1.3.7
    entrypoint: [""]
  when: manual
  stage: deploy
  cache:
    paths:
      - .terraform/
  retry: 2
  tags:
    - gitlab-runner
  script:
    - terraform apply -auto-approve -input=false
  only:
    variables:
      - $PHASE == "BUILD"


Destroy:
  image:
    name: hashicorp/terraform:1.3.7
    entrypoint: [""]
  stage: deploy
  cache:
    paths:
      - .terraform/
  retry: 2
  tags:
    - gitlab-runner
  script:
    - terraform destroy -auto-approve -var region=${REGION}
  only:
    variables:
      - $PHASE == "DESTROY"
provider "tencentcloud" {
  region = var.region
}

terraform {
  required_providers {
    tencentcloud = {
      source  = "registry.terraform.io/tencentcloudstack/tencentcloud"
      version = ">=1.61.5"
    }
  }
  backend "http" {}
}
variable "region" {
  type = string
  default = "ap-beijing"
}


//data "tencentcloud_instances" "cvm" {
//}
locals {
  cidr_block_vpc_name = "10.0.0.0/16"
}

resource "tencentcloud_vpc" "sampletfvpc" {
  cidr_block = local.cidr_block_vpc_name
  name       = "sampletfvpc"
}

output "result" {
  value = {
//    cvm_result = { for k, v in data.tencentcloud_instances.cvm : k => v },
//    count      = data.tencentcloud_instances.cvm.instance_list[*]
    vpc = {for k,v in tencentcloud_vpc.sampletfvpc :k=>v}
  }
}

4.4 查看流水线

推送代码至Gitlab后,查看流实现CI/CD

查看plan

手动apply进行资源 编排

查看编排云资源

4.5 State文件

可以使用web页面进行后端state管理,也可以通过API进行操作。

五 其他

同样的可以使用极狐Gitlab后端 作为terraform的远端数据源,使用 data.terraform_remote_state.example.outputs.<OUTPUT-NAME> 在 Terraform 资源中引用数据源的输出。

在CI/CD流程中使用cache进行provider相关文件缓存,方便后续工作流快速高效运行。

六 总结

通过在GitLab CI中集成Terraform并使用HTTP backend管理状态,可以实现对Terraform基础设施编排的CI/CD。但同时也带来了一定的挑战

  1. Terraform server作为单点故障,其可用性直接影响GitLab CI中Terraform作业。需要考虑高可用方案。
  2. Terraform状态安全性直接决定基础设施的安全,需要严格控制对Terraform server的访问权限。
  3. Terraform exec模块的使用会使环境变得难以重现。需要考虑使用Packer等工具来标准化环境。
  4. 大规模环境的管理可能导致Terraform server性能瓶颈,需要测试环境大小与Terraform server配置的匹配性。
  5. 与其他CI工具的集成还需要深入研究。例如,支持从Jenkins或CircleCI中调用Terraform HTTP API。

总之,使用HTTP backend可以很好的在GitLab CI中管理Terraform状态在单独使用Gitlab CI不失为一个比较优选的解决方案,另外有待进一步改进的是提高Terraform server的可靠性、严密控制其安全性和改进Terraform状态API的实现。

参考链接

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。