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

Terraform 模块注册表

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

通过 Terraform 模块注册表,您可以:

  • 使用 GitLab 项目作为 Terraform 模块的私有注册表。
  • 使用 GitLab CI/CD 创建和发布模块,然后可以从其他私有项目中使用这些模块。

认证到 Terraform 模块注册表

要认证到 Terraform 模块注册表,您需要以下任一方式:

使用 API 时:

  • 如果使用部署令牌进行认证,必须应用 write_package_registry 权限才能发布模块。要下载模块,请应用 read_package_registry 权限。
  • 如果使用个人访问令牌进行认证,必须将其配置为至少具有 read_api 权限。

不要使用此处文档之外的其他认证方法。未记录的认证方法将来可能会被移除。

前置条件

要发布 Terraform 模块:

  • 您必须至少拥有 Developer 角色。

要删除模块:

  • 您必须至少拥有 Maintainer 角色。

发布 Terraform 模块

发布 Terraform 模块会创建它(如果不存在)。

发布 Terraform 模块后,您可以在 Terraform 模块注册表 页面中查看它。

使用 API

使用 Terraform 模块注册表 API 发布 Terraform 模块。

PUT /projects/:id/packages/terraform/modules/:module-name/:module-system/:module-version/file
属性 类型 必需 描述
id integer/string 项目的 ID 或 URL 编码路径
module-name string 模块名称。支持的语法:1 到 64 个 ASCII 字符,包括小写字母 (a-z) 和数字 (0-9)。
module-system string 模块系统。支持的语法:1 到 64 个 ASCII 字符,包括小写字母 (a-z) 和数字 (0-9)。更多信息请参见 Module Registry Protocol
module-version string 模块版本。应遵循 语义版本规范

在请求正文中提供文件内容。

请求必须以 /file 结尾。 如果您发送以其他内容结尾的请求,会导致 404 Not Found 错误。

使用个人访问令牌的示例请求:

curl --fail-with-body --header "PRIVATE-TOKEN: <your_access_token>" \
     --upload-file path/to/file.tgz \
     --url "https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/terraform/modules/<your_module>/<your_system>/0.0.1/file"

使用部署令牌的示例请求:

curl --fail-with-body --header "DEPLOY-TOKEN: <deploy_token>" \
     --upload-file path/to/file.tgz \
     --url "https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/terraform/modules/<your_module>/<your_system>/0.0.1/file"

示例响应:

{
  "message":"201 Created"
}

使用 CI/CD 模板(推荐)

您可以使用 Terraform-Module.gitlab-ci.yml 或高级的 Terraform/Module-Base.gitlab-ci.yml CI/CD 模板将 Terraform 模块发布到 GitLab Terraform 模块注册表:

include:
  template: Terraform-Module.gitlab-ci.yml

该管道包含以下作业:

  • fmt: 验证 Terraform 模块的格式
  • kics-iac-sast: 测试 Terraform 模块的安全问题
  • deploy: 将 Terraform 模块部署到 Terraform 模块注册表(仅限标签管道)

使用管道变量

使用以下变量配置管道:

变量 默认值 描述
TERRAFORM_MODULE_DIR ${CI_PROJECT_DIR} Terraform 项目的根目录的相对路径。
TERRAFORM_MODULE_NAME ${CI_PROJECT_NAME} 模块名称。不能包含任何空格或下划线。
TERRAFORM_MODULE_SYSTEM local 您模块的目标系统或提供者。例如 localawsgoogle
TERRAFORM_MODULE_VERSION ${CI_COMMIT_TAG} 模块版本。应遵循 语义版本规范

手动配置 CI/CD

要在 GitLab CI/CD 中使用 Terraform 模块,请在命令中使用 CI_JOB_TOKEN 替代个人访问令牌。

例如,此作业为 local 系统提供者 上传新模块,并使用 Git 提交标签中的模块版本:

stages:
  - deploy

upload:
  stage: deploy
  image: curlimages/curl:latest
  variables:
    TERRAFORM_MODULE_DIR: ${CI_PROJECT_DIR}    # Terraform 项目的根目录的相对路径。
    TERRAFORM_MODULE_NAME: ${CI_PROJECT_NAME}  # 您的 Terraform 模块名称,不能有任何空格或下划线(将转换为连字符)。
    TERRAFORM_MODULE_SYSTEM: local             # 您的 Terraform 模块的目标系统或提供者(例如 local、aws、google)。
    TERRAFORM_MODULE_VERSION: ${CI_COMMIT_TAG} # 版本 - 建议遵循 SemVer 进行 Terraform 模块版本控制。
  script:
    - TERRAFORM_MODULE_NAME=$(echo "${TERRAFORM_MODULE_NAME}" | tr " _" -) # 模块名称不能有空格或下划线,因此将它们转换为连字符
    - tar -vczf /tmp/${TERRAFORM_MODULE_NAME}-${TERRAFORM_MODULE_SYSTEM}-${TERRAFORM_MODULE_VERSION}.tgz -C ${TERRAFORM_MODULE_DIR} --exclude=./.git .
    - 'curl --fail-with-body --location --header "JOB-TOKEN: ${CI_JOB_TOKEN}"
         --upload-file /tmp/${TERRAFORM_MODULE_NAME}-${TERRAFORM_MODULE_SYSTEM}-${TERRAFORM_MODULE_VERSION}.tgz
         ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/terraform/modules/${TERRAFORM_MODULE_NAME}/${TERRAFORM_MODULE_SYSTEM}/${TERRAFORM_MODULE_VERSION}/file'
  rules:
    - if: $CI_COMMIT_TAG

要触发此上传作业,请向您的提交添加 Git 标签。 确保标签遵循 Terraform 所需的 语义版本规范rules:if: $CI_COMMIT_TAG 确保 只有标记到您仓库的提交才会触发模块上传作业。

有关控制 CI/CD 管道中作业的其他方法,请参见 CI/CD YAML 语法参考

模块解析工作流

当您上传新模块时,GitLab 会为该模块生成一个路径。例如:

  • https://gitlab.example.com/parent-group/my-infra-package

此路径符合 Terraform 模块注册表协议,其中:

  • gitlab.example.com 是主机名。
  • parent-group 是 Terraform 模块注册表的唯一顶级 命名空间
  • my-infra-package 是模块的名称。

如果不允许重复,模块名称和版本在 parent-group 下的所有组、子组和项目中必须是唯一的。否则,您将收到以下错误:

  • {"message":"命名空间中已存在同名模块。"}

如果允许重复,模块解析基于最近发布的模块。

例如,如果:

  • 项目是 gitlab.example.com/parent-group/subgroup/my-project
  • Terraform 模块是 my-infra-package。 如果允许重复,my-infra-package 是有效的模块。 如果不允许重复,模块名称在 parent-group 下的所有组中的所有项目中必须是唯一的。

当您命名模块时,请记住这些命名约定:

  • 您的项目和组名称不能包含点(.)。 例如,source = "gitlab.example.com/my.group/project.name" 是无效的。
  • 模块版本应遵循 语义版本规范

允许重复的 Terraform 模块

默认情况下,Terraform 模块注册表强制在同一命名空间中模块名称的唯一性。

要允许发布重复的模块名称:

  1. 在左侧边栏,选择 搜索或转到 并找到您的组。
  2. 选择 设置 > 包和注册表
  3. 重复包 表的 Terraform 模块 行中,关闭 允许重复 开关。
  4. 可选。在 例外 文本框中,输入与要允许的模块名称匹配的正则表达式。

您的更改将自动保存。

如果 允许重复 已开启,您可以在 例外 文本框中指定不应有重复的模块名称。

您还可以通过在 GraphQL API 中启用 terraform_module_duplicates_allowed 来允许发布重复名称。

要允许特定名称的重复:

  1. 确保 terraform_module_duplicates_allowed 已禁用。
  2. 使用 terraform_module_duplicate_exception_regex 定义您要允许重复的模块名称的正则表达式模式。

顶级命名空间设置优先于子命名空间设置。 例如,如果您为组启用 terraform_module_duplicates_allowed,并为子组禁用它, 则允许组及其子组中所有项目的重复。

有关模块解析的更多信息,请参见 模块解析工作流

查看 Terraform 模块

要在您的项目或组中查看 Terraform 模块:

  1. 在左侧边栏,选择 搜索或转到 并找到您的项目或组。
  2. 选择 操作 > Terraform 模块

您可以在此页面上搜索、排序和过滤模块。

要查看模块的 README 文件:

  1. Terraform 模块注册表 页面,选择一个 Terraform 模块。
  2. 选择 README

引用 Terraform 模块

从组或项目引用模块。

从命名空间

您可以为 terraform 在环境变量中提供认证令牌(作业令牌、个人访问令牌或部署令牌)。

您应该为环境变量名添加 TF_TOKEN_ 前缀,并将点编码为下划线。 更多信息,请参见 环境变量凭据

例如,名为 TF_TOKEN_gitlab_com 的变量的值,当 CLI 向主机名 gitlab.com 发送服务请求时,将用作部署令牌:

export TF_TOKEN_gitlab_com='glpat-<deploy_token>'

此方法适用于企业实现。对于本地或临时环境, 您可能需要创建一个 ~/.terraformrc%APPDATA%/terraform.rc 文件:

credentials "<gitlab.com>" {
  token = "<TOKEN>"
}

其中 gitlab.com 可以替换为您 GitLab 自托管实例的主机名。

然后您可以从下游 Terraform 项目引用您的 Terraform 模块:

module "<module>" {
  source = "gitlab.com/<namespace>/<module-name>/<module-system>"
}

从项目

要使用项目源引用 Terraform 模块, 使用 Terraform 提供的 通过 HTTP 获取归档 源类型。

您可以在 ~/.netrc 文件中为 terraform 提供认证令牌(作业令牌、个人访问令牌或部署令牌):

machine <gitlab.com>
login <USERNAME>
password <TOKEN>

其中 gitlab.com 可以替换为您 GitLab 自托管实例的主机名, <USERNAME> 是您的令牌用户名。

您可以从下游 Terraform 项目引用您的 Terraform 模块:

module "<module>" {
  source = "https://gitlab.com/api/v4/projects/<project-id>/packages/terraform/modules/<module-name>/<module-system>/<module-version>"
}

如果需要引用模块的最新版本,可以从源 URL 中省略 <module-version>。为防止未来出现问题,如果可能,应引用特定版本。

如果同一命名空间中存在重复的模块名称,从命名空间级别引用模块将安装最近发布的模块。要引用重复模块的特定版本,请使用项目级源类型。

下载 Terraform 模块

要下载 Terraform 模块:

  1. 在左侧边栏,选择 操作 > Terraform 模块
  2. 选择您要下载的模块的名称。
  3. 资源 表中,选择您要下载的模块。

删除 Terraform 模块

在 Terraform 模块注册表中发布 Terraform 模块后,您无法编辑它。相反, 您必须删除并重新创建它。

您可以使用 packages API 或 UI 删除模块。

要在 UI 中删除模块,从您的项目:

  1. 在左侧边栏,选择 操作 > Terraform 模块
  2. 找到您要删除的包的名称。
  3. 选择 删除

该包将被永久删除。

禁用 Terraform 模块注册表

Terraform 模块注册表默认启用。

对于 GitLab 自托管实例,GitLab 管理员可以 禁用 包和注册表, 这会从侧边栏中删除此菜单项。

您还可以为特定项目移除 Terraform 模块注册表:

  1. 在您的项目中,转到 设置 > 常规
  2. 展开 可见性、项目功能、权限 部分,并关闭
  3. 选择 保存更改

示例项目

有关 Terraform 模块注册表的示例,请查看以下项目: