GitLab 与 Terraform 集成的故障排除
当你使用 GitLab 与 Terraform 的集成时,可能会遇到需要排查的问题。
刷新子组状态时未检测到 gitlab_group_share_group 资源
由于 “User with permissions cannot retrieve share_with_groups from the API” 的问题,GitLab Terraform 提供程序可能无法检测到现有的 gitlab_group_share_group 资源。这会导致运行 terraform apply 时出错,因为 Terraform 尝试重新创建已存在的资源。
例如,考虑以下组/子组配置:
parent-group
├── subgroup-A
└── subgroup-B其中:
- 用户
user-1创建了parent-group、subgroup-A和subgroup-B。 subgroup-A与subgroup-B共享。- 用户
terraform-user是parent-group的成员,对两个子组都继承拥有owner访问权限。
当 Terraform 状态刷新时,提供程序发出的 API 查询 GET /groups/:subgroup-A_id 不会在 shared_with_groups 数组中返回 subgroup-B 的详细信息。这会导致错误。
要解决此问题,请确保应用以下条件之一:
terraform-user创建所有子组资源。- 在
subgroup-B上为terraform-user用户授予 Maintainer 或 Owner 角色。 terraform-user继承对subgroup-B的访问权限,且subgroup-B包含至少一个项目。
Terraform 状态故障排除
无法使用先前作业的计划在 CI 作业中锁定 Terraform 状态文件以进行 terraform apply
当将 -backend-config= 传递给 terraform init 时,Terraform 会将这些值持久化到计划缓存文件中。这包括 password 值。
因此,要创建计划并在另一个 CI 作业中使用相同的计划,在使用 -backend-config=password=$CI_JOB_TOKEN 时可能会收到 Error: Error acquiring the state lock 错误。这是因为 $CI_JOB_TOKEN 的值仅在当前作业期间有效。
作为替代方案,在 CI 作业中使用 http backend configuration variables,这是遵循 Get started using GitLab CI 说明时后台发生的情况。
错误:“address”:必需字段未设置
默认情况下,我们将 TF_ADDRESS 设置为 ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME}。如果在作业中没有设置 TF_STATE_NAME 或 TF_ADDRESS,作业会失败并显示错误消息 Error: "address": required field is not set。
要解决此问题,确保在返回错误的作业中可以访问 TF_ADDRESS 或 TF_STATE_NAME:
- 为作业配置 CI/CD environment scope。
- 设置作业的 environment,与上一步的环境范围相匹配。
错误:刷新状态时,HTTP 远程状态端点需要身份验证
要解决此问题,请确保:
- 你使用的访问令牌具有
api范围。 - 如果设置了
TF_HTTP_PASSWORDCI/CD 变量,请确保你:- 设置与
TF_PASSWORD相同的值 - 如果你的 CI/CD 作业不明确使用
TF_HTTP_PASSWORD,请删除该变量
- 设置与
启用 Developer 角色对破坏性命令的访问权限
要允许具有 Developer 角色的用户运行破坏性命令,你需要一个替代方案:
- 创建具有
api范围的项目访问令牌。 - 将
TF_USERNAME和TF_PASSWORD添加到你的 CI/CD 变量中:- 将
TF_USERNAME的值设置为你项目访问令牌的用户名。 - 将
TF_PASSWORD的值设置为你项目访问令牌的密码。 - 可选。保护这些变量,使它们仅在受保护分支或受保护标签上运行的管道中可用。
- 将
如果状态名称包含句点,则找不到状态
GitLab 15.6 及更早版本,如果状态名称包含句点且 Terraform 尝试锁定状态,会返回 404 错误。
你可以通过在 Terraform 命令中添加 -lock=false 来解决此限制。GitLab 后端接受请求,但内部会从状态名称中删除句点及其后的任何字符。例如,名为 foo.bar 的状态会被存储为 foo。但是,不建议使用此替代方案,甚至可能导致状态名称冲突。
在 GitLab 15.7 及更高版本中,支持包含句点的状态名称。如果你使用 -lock=false 替代方案并升级到 GitLab 15.7 或更高版本,你的作业可能会失败。失败的原因是 GitLab 后端使用完整的状态名称存储新状态,这与现有状态名称不一致。
要修复失败的作业,请重命名你的状态名称,排除句点及其后的任何字符。
如果设置了你的 TF_HTTP_ADDRESS、TF_HTTP_LOCK_ADDRESS 和 TF_HTTP_UNLOCK_ADDRESS,请确保更新那里的状态名称。
或者,你可以 迁移你的 OpenTofu 状态。
错误:保存状态时出现 HTTP 错误:404
如果状态名称包含正斜杠 (/) 字符,可能会发生此错误。要解决此问题,请确保状态名称不包含任何正斜杠 (/) 字符。