GitLab as Code (二) 离线运行优化

2023-03-08 20:25:49 浏览数 (1)

前言

本文是对上一篇文章(使用 GitLab Terraform 管理 GitLab 的 Group 和 Project)的补充。在实际使用中,我们经常会遇到以下问题:

  • GitLab 部署在内网,未开放公网访问,无法访问 Terraform Registry[1]
  • Initializing Terraform Provider 时,频繁出现类似 Get "https://registry.terraform.io/.well-known/terraform.json": net/http: TLS handshake timeout 这样由网络卡顿引起的错误
  • 拉取不到 Terraform.gitlab-ci.yml template 中的 registry.gitlab.com/gitlab-org/terraform-images/releases 镜像

解决方案

上述这些问题均由网络因素造成,其有多种解决方案:

  • 在可以访问公网的机器(甚至是您的笔记本电脑)注册私有 GitLab Runner[2],通过该 Runner 运行 Pipeline

GitLab Runner 支持多系统(Linux、macOS、Windows、FreeBSD 等)、多架构(x86、ARM)以及 Docker/Kubernetes 容器平台

  • 使用 Terraform Providers Mirror[3] 将需要的 Terraform Provider 镜像下载到本地

本文主要介绍第二种方案,关于第一种方案,详情请参阅官方文档[4]

离线运行优化

基于上一篇文章的内容,只需几步即可实现离线运行优化,并使 Pipeline 运行速度提高一倍。

优化前后

Terraform Providers Mirror

在无法访问 Terraform Registry[5] 或访问境外站点速度过慢时,可以使用 Terraform Providers Mirror 解决问题。只需一行命令即可将 .tf 文件中使用的 Providers 下载到本地:

代码语言:javascript复制
terraform providers mirror -platform=linux_amd64 .

terraform providers mirror 仅适用于 Terraform v0.13 或更高版本

  • -platform=OS_ARCH: 指定需要运行的 providers 的系统架构,默认是本机架构。因为 jihulab.com[6] 的 share-runner 是 linux 系统 amd64 架构,所以这里使用了 linux_amd64
  • .: 指定下载后的 <target-dir>,即 providers 镜像将保存在该目录中。

运行命令后,项目的根目录会多出一个名为 registry.terraform.io 的文件夹,里面是已下载的镜像文件。

.terraformrc 文件

下载好 Providers 镜像后,下一步是编辑 Terraform CLI 配置文件 .terraformrc,指定运行 Terraform 时使用镜像的 Providers。

以下是配置示例:

代码语言:javascript复制
provider_installation {
    filesystem_mirror {
        path    = "${TF_ROOT}"
        include = ["registry.terraform.io/gitlabhq/*"]
    }
}
  • path: 镜像的路径
  • include: 指定为哪些 Providers 提供镜像,也可以使用 exclude 来排除

如果有 Terraform Providers 镜像站地址,可以直接使用 network_mirror 指定 URL。有关详细内容,请参阅官方文档[7]

GitLab CI

在编辑完 .terraformrc 文件后,接下来即可编辑 .gitlab-ci.yml 文件。

.gitlab-ci.yml 文件中,需要进行如下修改:

before_script 中生成 .terraformrc 供 terraform CLI 使用:

代码语言:javascript复制
before_script:
- |
    cat>.terraformrc<<EOF
    provider_installation {
        filesystem_mirror {
            path    = "${TF_ROOT}"
            include = ["registry.terraform.io/gitlabhq/*"]
        }
    }
    EOF

增加 Variables

代码语言:javascript复制
variables:
  TF_STATE_NAME: default
  TF_CACHE_KEY: default
  # If your terraform files are in a subdirectory, set TF_ROOT accordingly. For example:
  # TF_ROOT: terraform/production
  TF_CLI_CONFIG_FILE: ${TF_ROOT}/.terraformrc
  GITLAB_BASE_URL: ${CI_API_V4_URL}
  • TF_CLI_CONFIG_FILE: 设置为指定的 terraform CLI 配置文件路径,即生成的 .terraformrc 文件路径。${TF_ROOT} 表示 Terraform 配置的根路径,该环境变量由 GitLab Terraform helpers[8] 提供
  • GITLAB_BASE_URL: 设置为 GitLab Provider 的 base_url,默认为 https://gitlab.com/api/v4/,此处使用了预定义 CI/CD 变量[9] CI_API_V4_URL

这样每次运行 Pipeline 时,都会通过指定的 .terraformrc 文件从本地 Terraform Providers Mirror 拉取 Terraform Providers。

GitLab Container Registry

有些 GitLab 实例没有公网访问权限,无法拉取到 GitLab 提供的 Terraform 基础镜像 registry.gitlab.com/gitlab-org/terraform-images/releases,解决方案很简单:

  • 在公网拉取该镜像并上传到私有镜像仓库(如 Harbor)
  • 将镜像上传到 GitLab 提供的 Container Registry 使用

结语

在实际使用中,即使没有网络连接的困扰,我仍然强烈推荐使用这套离线运行方案。不管是 validateplan 还是 apply 等操作,它们的执行速度都快得多,因此特别适合那些正在学习并尝试使用 GitLab Terraform 整套方案的用户。

Demo 地址:https://jihulab.com/cloud-native/gitops/gitlab-as-code/

参考资料

[1]

Terraform Registry: https://registry.terraform.io

[2]

私有 GitLab Runner: https://docs.gitlab.cn/runner/register/#注册-runner

[3]

Terraform Providers Mirror: https://developer.hashicorp.com/terraform/cli/commands/providers/mirror

[4]

官方文档: https://docs.gitlab.cn/runner/

[5]

Terraform Registry: https://registry.terraform.io

[6]

jihulab.com: https://jihulab.com

[7]

官方文档: https://developer.hashicorp.com/terraform/cli/config/config-file#explicit-installation-method-configuration

[8]

GitLab Terraform helpers: https://docs.gitlab.com/ee/user/infrastructure/iac/gitlab_terraform_helpers.html#generic-variables

[9]

预定义 CI/CD 变量: https://docs.gitlab.cn/ee/ci/variables/predefined_variables.html

- END -

0 人点赞