极狐GitLab 管理的 Terraform 状态

Terraform 使用状态文件来存储有关您的基础架构配置的详细信息。 使用 Terraform 远程后端,您可以将状态文件存储在远程和共享存储中。

极狐GitLab 提供了一个 Terraform HTTP 后端来以最少的配置安全地存储您的状态文件。

在极狐GitLab 中,您可以:

  • 版本化您的 Terraform 状态文件。
  • 加密传输中和静止时的状态文件。
  • 锁定和解锁状态。
  • 远程执行 terraform planterraform apply 命令。
caution灾难恢复计划 Terraform 状态文件在磁盘和对象存储中静止时使用密码箱 Ruby gem 进行加密。要解密状态文件,极狐GitLab 必须可用。 如果它处于脱机状态,并且您使用极狐GitLab 部署系统所需的基础架构(如虚拟机、Kubernetes 集群或网络组件),则您无法轻松访问状态文件或对其进行解密。 此外,如果极狐GitLab 提供引导系统所需的 Terraform 模块或其他依赖项,这些将无法访问。要解决此问题,请做出其他安排来托管或备份这些依赖项,或考虑使用没有共享故障点的单独极狐GitLab 实例。

先决条件

对于私有部署实例,在您可以将极狐GitLab 用于 Terraform 状态文件之前:

  • 管理员必须设置 Terraform 状态存储
  • 您必须为您的项目启用 基础设施 菜单。 转到 设置 > 通用,展开 可见性、项目功能、权限,然后在 运维 下,打开切换开关。

使用极狐GitLab CI/CD 将 Terraform 状态初始化为后端

执行 terraform init 命令后,您可以使用极狐GitLab CI/CD 运行 terraform 命令。

先决条件:

  • 要使用 terraform apply 锁定、解锁和写入状态,您必须至少具有维护者角色。
  • 要使用 terraform plan -lock=false 读取状态,您必须至少具有开发者角色。
caution与任何其他作业产物一样,Terraform 计划数据可由仓库中具有访客角色的任何人查看。 默认情况下,Terraform 和极狐GitLab 都不加密计划文件。如果您的 Terraform 计划包含敏感数据,例如密码、访问令牌或证书,您应该加密计划输出或修改项目可见性设置。

要将极狐GitLab CI/CD 配置为后端:

  1. 在您的 Terraform 项目中,在像 backend.tf 这样的 .tf 文件中,定义 HTTP 后端

    terraform {
      backend "http" {
      }
    }
    
  2. 在项目仓库的根目录中,创建一个 .gitlab-ci.yml 文件。使用 Terraform.gitlab-ci.yml 模板来填充它。
  3. 将您的项目推送到极狐GitLab。此操作触发一条流水线,该流水线运行 gitlab-terraform initgitlab-terraform validategitlab-terraform plan 命令。
  4. 从运行 gitlab-terraform apply 命令的上一个流水线触发手动 deploy 作业,以配置定义的基础设施。

上述 terraform 命令的输出应该可以在作业日志中查看。

gitlab-terraform CLI 是 terraform CLI 的包装器。

如果您更喜欢显式调用 terraform 命令,则可以覆盖模板,而是将其用作您可以实现的目标的参考。

自定义 Terraform 环境变量

使用 Terraform.gitlab-ci.yml 模板时,可以在定义您的 CI/CD 作业时,使用 Terraform HTTP 配置变量

要自定义 terraform init 并覆盖 Terraform 配置,请使用环境变量而不是 terraform init -backend-config=... 方法。 使用 -backend-config 时,配置为:

  • 缓存在 terraform plan 命令的输出中。
  • 通常传递给 terraform apply 命令。

此配置可能会导致问题,例如无法在 CI 作业中锁定 Terraform 状态文件

从本地机器访问状态

您可以从本地计算机访问极狐GitLab 管理的 Terraform 状态。

caution在极狐GitLab 的集群部署中,您不应使用本地存储。 节点之间可能会出现拆分状态,从而导致后续的 Terraform 执行不一致。相反,请使用远端存储资源。
  1. 确保 Terraform 状态已为 CI/CD 初始化
  2. 复制预先填充的 Terraform init 命令:

    1. 在左侧边栏中,选择 搜索或转到 并找到您的项目。
    2. 在左侧边栏中,选择 运维 > Terraform 状态
    3. 在您要使用的环境旁边,选择 操作 (),并选择 复制 Terraform init 命令
  3. 打开终端并在本地计算机上运行此命令。

迁移到极狐GitLab 管理的 Terraform 状态

Terraform 支持在后端更改或重新配置时复制状态。使用这些操作从另一个后端迁移到极狐GitLab 管理的 Terraform 状态。

您应该使用本地终端运行迁移到极狐GitLab 管理的 Terraform 状态所需的命令。

以下示例演示如何更改状态名称。从不同的状态存储后端迁移到极狐GitLab 管理的 Terraform 状态需要相同的工作流程。

设置初始后端

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

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
Initializing the backend...

Successfully configured the backend "http"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
re-run this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

更改后端

现在 terraform init 已经创建了一个 .terraform/ 目录,它知道旧状态在哪里,您可以告诉它新位置:

TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/new-state-name"

terraform init \
  -migrate-state \
  -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
Initializing the backend...
Backend configuration changed!

Terraform has detected that the configuration specified for the backend
has changed. Terraform will now check for existing state in the backends.


Acquiring state lock. This may take a few moments...
Do you want to copy existing state to the new backend?
  Pre-existing state was found while migrating the previous "http" backend to the
  newly configured "http" backend. No existing state was found in the newly
  configured "http" backend. Do you want to copy this state to the new "http"
  backend? Enter "yes" to copy and "no" to start with an empty state.

  Enter a value: yes


Successfully configured the backend "http"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

如果您键入 yes,它会将您的状态从旧位置复制到新位置。然后,您可以返回到极狐GitLab CI/CD 中运行它。

使用极狐GitLab 后端作为远端数据源

您可以使用极狐GitLab 管理的 Terraform 状态后端作为 Terraform 数据源

  1. 在您的 main.tf 或其他相关文件中,声明这些变量。 将值留空。

    variable "example_remote_state_address" {
      type = string
      description = "Gitlab remote state file address"
    }
    
    variable "example_username" {
      type = string
      description = "Gitlab username to query remote state"
    }
    
    variable "example_access_token" {
      type = string
      description = "GitLab access token to query remote state"
    }
    
  2. 要覆盖上一步中的值,请创建一个名为 example.auto.tfvars 的文件。此文件应该在您的项目仓库中进行版本控制。

    example_remote_state_address = "https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>"
    example_username = "<GitLab username>"
    example_access_token = "<GitLab Personal Access Token>"
    
  3. .tf 文件中,使用 Terraform 输入变量定义数据源:

    data "terraform_remote_state" "example" {
      backend = "http"
    
      config = {
        address = var.example_remote_state_address
        username = var.example_username
        password = var.example_access_token
      }
    }
    
    • address:要用作数据源的远端状态后端的 URL。例如,https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>
    • username:向数据源进行身份验证的用户名。如果您使用个人访问令牌进行身份验证,则此值是您的极狐GitLab 用户名。如果您使用的是极狐GitLab CI/CD,则此值为 'gitlab-ci-token'
    • password:用于对数据源进行身份验证的密码。如果您使用个人访问令牌进行身份验证,则此值是令牌值(令牌必须具有 API 范围)。如果您使用的是极狐GitLab CI/CD,则此值是 ${CI_JOB_TOKEN} CI/CD 变量的内容。

现在可以使用 data.terraform_remote_state.example.outputs.<OUTPUT-NAME> 在 Terraform 资源中引用数据源的输出。

要读取目标项目中的 Terraform 状态,您至少需要开发者角色。

管理 Terraform 状态文件

引入于 13.8 版本。

查看 Terraform 状态文件:

  1. 在左侧边栏中,选择 搜索或转到 并找到您的项目。
  2. 在左侧边栏中,选择 运维 > Terraform 状态

管理单个 Terraform 状态版本

引入于 13.4 版本。

可以使用极狐GitLab REST API 管理各个状态版本。

如果您至少具有开发者角色,则可以使用其序列号检索状态版本:

curl --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>/versions/<version-serial>"

如果您至少具有维护者角色,则可以使用其序列号删除状态版本:

curl --header "Private-Token: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>/versions/<version-serial>"

删除状态文件

如果您至少具有维护者角色,则可以删除状态文件。

  1. 在左侧边栏中,选择 基础设施 > Terraform 状态
  2. 操作 列中,选择 操作 (),然后选择 删除状态文件和版本

使用 API 删除状态文件

您可以通过向 REST API 发出请求来删除状态文件。例如:

curl --header "Private-Token: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>"