Help us learn about your current experience with the documentation. Take the survey.

Terraform 状态管理

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab Self-Managed

GitLab 可用作 Terraform 状态文件的后端。 这些文件在存储前会被加密。此功能默认启用。

这些文件的默认存储位置为:

  • Linux 包安装:/var/opt/gitlab/gitlab-rails/shared/terraform_state
  • 自行编译安装:/home/git/gitlab/shared/terraform_state

您可以使用下述选项来配置这些位置。

GitLab Helm chart 安装请使用 外部对象存储 配置。

禁用 Terraform 状态

您可以在整个实例中禁用 Terraform 状态。您可能希望禁用 Terraform 以减少磁盘空间占用,或者因为您的实例并未使用 Terraform。

当 Terraform 状态管理被禁用时:

  • 在左侧边栏中,您将无法选择 运维 > Terraform 状态

  • 任何访问 Terraform 状态的 CI/CD 作业都会因此错误而失败:

    Error refreshing state: HTTP remote state endpoint invalid auth

要根据您的安装方式禁用 Terraform 管理,请按以下步骤操作。

前提条件:

  • 您必须是管理员。

对于 Linux 包安装:

  1. 编辑 /etc/gitlab/gitlab.rb 并添加以下行:

    gitlab_rails['terraform_state_enabled'] = false
  2. 保存文件并重新配置 GitLab以使更改生效。

对于自行编译安装:

  1. 编辑 /home/git/gitlab/config/gitlab.yml 并添加或修改以下行:

    terraform_state:
      enabled: false
  2. 保存文件并重启 GitLab以使更改生效。

使用本地存储

默认配置使用本地存储。要更改 Terraform 状态文件的本地存储位置,请按以下步骤操作。

对于 Linux 包安装:

  1. 例如,要将存储路径更改为 /mnt/storage/terraform_state,请编辑 /etc/gitlab/gitlab.rb 并添加以下行:

    gitlab_rails['terraform_state_storage_path'] = "/mnt/storage/terraform_state"
  2. 保存文件并重新配置 GitLab以使更改生效。

对于自行编译安装:

  1. 例如,要将存储路径更改为 /mnt/storage/terraform_state,请编辑 /home/git/gitlab/config/gitlab.yml 并添加或修改以下行:

    terraform_state:
      enabled: true
      storage_path: /mnt/storage/terraform_state
  2. 保存文件并重启 GitLab以使更改生效。

使用对象存储

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab Self-Managed

我们建议不要将 Terraform 状态文件存储在磁盘上,而是使用受支持的对象存储选项之一。 此配置依赖于已预先配置的有效凭据。

进一步了解在 GitLab 中使用对象存储

对象存储设置

以下设置的格式为:

  • 在 Linux 包安装中,以 terraform_state_object_store_ 为前缀。
  • 在自行编译安装中,嵌套在 terraform_state: 下的 object_store: 中。
设置 描述 默认值
enabled 启用/禁用对象存储 false
remote_directory 存储 Terraform 状态文件的存储桶(bucket)名称
connection 下述的各种连接选项

迁移到对象存储

无法将 Terraform 状态文件从对象存储迁移回本地存储,因此请谨慎操作。目前有一个 issue旨在改变此行为。

要将 Terraform 状态文件迁移到对象存储:

  • 对于 Linux 包安装:

    gitlab-rake gitlab:terraform_states:migrate
  • 对于自行编译安装:

    sudo -u git -H bundle exec rake gitlab:terraform_states:migrate RAILS_ENV=production

您可以选择使用 PostgreSQL 控制台来跟踪进度并验证所有 Terraform 状态文件是否已成功迁移:

  • Linux 包安装:sudo gitlab-rails dbconsole --database main
  • 自行编译安装:sudo -u git -H psql -d gitlabhq_production

请验证下方的 objectstg(其中 file_store=2)是否包含所有状态的计数:

gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM terraform_state_versions;

total | filesystem | objectstg
------+------------+-----------
   15 |          0 |      15

请验证 terraform_state 文件夹中是否没有磁盘文件:

sudo find /var/opt/gitlab/gitlab-rails/shared/terraform_state -type f | grep -v tmp | wc -l

S3 兼容连接设置

您应使用统一的对象存储设置。 本节描述的是较早的配置格式。

请参阅不同提供商的可用连接设置

  1. 编辑 /etc/gitlab/gitlab.rb 并添加以下行;将其中的值替换为您想要的值:

    gitlab_rails['terraform_state_object_store_enabled'] = true
    gitlab_rails['terraform_state_object_store_remote_directory'] = "terraform"
    gitlab_rails['terraform_state_object_store_connection'] = {
      'provider' => 'AWS',
      'region' => 'eu-central-1',
      'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
      'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY'
    }

如果您使用的是 AWS IAM 配置文件,请务必省略 AWS 访问密钥和秘密访问密钥的键值对。

gitlab_rails['terraform_state_object_store_connection'] = {
  'provider' => 'AWS',
  'region' => 'eu-central-1',
  'use_iam_profile' => true
}
  1. 保存文件并重新配置 GitLab以使更改生效。
  2. 将所有现有的本地状态迁移到对象存储
  1. 编辑 /home/git/gitlab/config/gitlab.yml 并添加或修改以下行:

    terraform_state:
      enabled: true
      object_store:
        enabled: true
        remote_directory: "terraform" # The bucket name
        connection:
          provider: AWS # Only AWS supported at the moment
          aws_access_key_id: AWS_ACCESS_KEY_ID
          aws_secret_access_key: AWS_SECRET_ACCESS_KEY
          region: eu-central-1
  2. 保存文件并重启 GitLab以使更改生效。

  3. 将所有现有的本地状态迁移到对象存储

查找 Terraform 状态文件路径

Terraform 状态文件存储在相关项目的哈希目录路径中。

路径格式为 /var/opt/gitlab/gitlab-rails/shared/terraform_state/<path>/<to>/<projectHashDirectory>/<UUID>/0.tfstate,其中 UUID 是随机定义的。

要查找状态文件路径:

  1. get-terraform-path 添加到您的 shell:

    get-terraform-path() {
        PROJECT_HASH=$(echo -n $1 | openssl dgst -sha256 | sed 's/^.* //')
        echo "${PROJECT_HASH:0:2}/${PROJECT_HASH:2:2}/${PROJECT_HASH}"
    }
  2. 运行 get-terraform-path <project_id>

    $ get-terraform-path 650
    20/99/2099a9b5f777e242d1f9e19d27e232cc71e2fa7964fc988a319fce5671ca7f73

系统将显示相对路径。

从备份恢复 Terraform 状态文件

要从备份恢复 Terraform 状态文件,您必须有权访问加密的状态文件和 GitLab 数据库。

数据库表

以下数据库表有助于将 S3 路径追溯到特定项目:

  • terraform_states:包含基础状态信息,包括每个状态的通用唯一标识符(UUID)。

文件结构和路径组成

状态文件存储在特定的目录结构中,其中:

  • 路径的前三个部分派生自项目 ID 的 SHA-2 哈希值。
  • 每个状态都有一个存储在 terraform_states 数据库表中的 UUID,该 UUID 构成了路径的一部分。

例如,对于一个项目,其:

  • 项目 ID 为 12345
  • 状态 UUID 为 example-uuid

如果 12345 的 SHA-2 哈希值为 5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5,则文件夹结构将为:

terraform/                                                                 <- 配置的 Terraform 存储目录
├─ 59/                                                                     <- 项目 ID 哈希值的第一和第二个字符
|  ├─ 94/                                                                  <- 项目 ID 哈希值的第三和第四个字符
|  |  ├─ 5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5/ <- 完整的项目 ID 哈希值
|  |  |  ├─ example-uuid/                                                  <- 状态 UUID
|  |  |  |  ├─ 1.tf                                                        <- 单个状态版本
|  |  |  |  ├─ 2.tf
|  |  |  |  ├─ 3.tf

解密过程

状态文件使用 Lockbox 进行加密,解密需要以下信息:

  • db_key_base 应用程序密钥
  • 项目 ID

加密密钥由 db_key_base 和项目 ID 共同派生而来。如果您无法访问 db_key_base,则无法进行解密。

要了解如何手动解密文件,请参阅 Lockbox 的文档。

要查看加密密钥的生成过程,请参阅状态上传器代码