terraform init 常被跨境拉取 provider 拖慢,并伴随 TLS 抖动与锁文件无意义 diff。本文给出阈值表、镜像决策矩阵、可复制环境变量与 terraform.rc、init 有界重试、CI 门禁与 FAQ。内链:首页、博客列表、Helm OCI 决策矩阵(均免登录)。
痛点:(1)多 job 并发 init 争用 Registry 与插件缓存;(2).terraform.lock.hcl 若未在与生产一致的平台集合上生成,易出噪音 PR;(3)重试需上限+退避,避免坏镜像拖死队列。
评测维度与阈值
下列阈值为跨境 + 共享 APFS起步值,请用你们真实 job 的 p95 init、Registry 5xx、锁文件 diff 频率校准。
| 维度 | 建议起步阈值 | 判读与动作 |
|---|---|---|
terraform init(含 provider 安装)p95 耗时 |
主干流水线 < 120s;夜间大批量可放宽至 240s | 先补镜像再调 TF_REGISTRY_CLIENT_TIMEOUT。 |
TF_REGISTRY_CLIENT_TIMEOUT(秒) |
同城/同区 10–20;跨洲公网 30–60 | 配合≤4 次有界重试;坏镜像勿只靠加长超时。 |
同一宿主机并发 init 作业数 |
共享盘为 APFS 时建议 2–4 路;独占 NVMe 节点可试 4–6 | 缓存锁争用则每作业子目录或排队。 |
| 插件缓存与 workspace 磁盘水位 | 可用空间 > 15% 且绝对值建议 > 20GiB 再跑大批量 init | 低于水位快速失败,防半写入缓存。 |
.terraform.lock.hcl 变更治理 |
受保护分支上 禁止无说明的哈希漂移;PR 必须附 terraform providers lock 命令记录 |
锁刷新只在黄金镜像执行并留命令记录。 |
可引用:TF_LOG=INFO 区分 429/5xx 与本地解压;锁文件须含 darwin_arm64;include/exclude 对齐出站白名单。
对比表或决策矩阵
决策焦点:谁提供可信 ZIP 与校验和。direct 简单但怕跨境;network_mirror 靠企业 HTTPS;filesystem_mirror 靠离线同步目录;混合时必须写清 include/exclude。
| 模式 | 最适配场景 | 主要风险 | 一句话结论 |
|---|---|---|---|
direct 直连 registry.terraform.io |
早期原型、海外团队、无合规限制 | 跨境抖动、Rate limit、DNS 分叉 | 监控 p95,生产勿单吊公网。 |
| network_mirror 企业 HTTPS 镜像 | 已有统一工件域、需审计出站 | 镜像索引滞后、证书链不一致 | 锁文件在与 CI 同镜像生成。 |
| filesystem_mirror 本地目录 | 强隔离区、间歇性断网、批量同版本 init | 目录更新竞态、权限与挂载只读 | 发布同步 ZIP;只读挂载 + 作业临时目录。 |
| plugin_cache_dir + 作业级子路径 | 重复拉同一 minor provider、节省带宽 | 多租户缓存污染、锁文件与缓存一致性 | 先读官方 plugin_cache_may_break_dependency_lock_file 再开团队缓存。 |
可执行命令与环境变量清单
仓库根示例 ${CI_PROJECT_DIR}。五步走:钉死 Terraform 版本 → 生成 .terraformrc+TF_CLI_CONFIG_FILE → 设 TF_PLUGIN_CACHE_DIR → 有界重试 init → validate+锁 diff。
export TF_IN_AUTOMATION=1
export TF_INPUT=0
export TF_CLI_CONFIG_FILE="${CI_PROJECT_DIR}/.terraformrc"
export TF_PLUGIN_CACHE_DIR="${CI_PROJECT_DIR}/.tf-plugin-cache-${CI_JOB_ID:-local}"
export TF_REGISTRY_CLIENT_TIMEOUT="${TF_REGISTRY_CLIENT_TIMEOUT:-45}"
# 短时排障可开:export TF_LOG=INFO
mkdir -p "${TF_PLUGIN_CACHE_DIR}"
.terraformrc 示例;其中路径为字面量,CI 可用 envsubst 生成以与 TF_PLUGIN_CACHE_DIR 对齐。
# 生成后内容示例(路径按作业替换)
plugin_cache_dir = "/tmp/tf-plugin-cache-job-12345"
provider_installation {
filesystem_mirror {
path = "/usr/local/share/terraform/providers-mirror"
include = ["registry.terraform.io/hashicorp/*"]
}
network_mirror {
url = "https://terraform-mirror.internal.example.com/"
include = ["registry.terraform.io/*/*"]
}
direct {
exclude = ["registry.terraform.io/*/*"]
}
}
# 与 CI 相同平台上刷新或校验锁文件(示例:Apple Silicon) terraform providers lock \ -platform=darwin_arm64 \ -platform=linux_amd64 \ -fs-mirror=/usr/local/share/terraform/providers-mirror terraform init -input=false -no-color -upgrade=false terraform validate
# init 有界重试(2s / 4s / 8s,最多 4 次)
run_init() {
local n=1 d=2
while [ "$n" -le 4 ]; do
echo "terraform init attempt ${n}/4"
terraform init -input=false -no-color -upgrade=false && return 0
[ "$n" -eq 4 ] && return 1
sleep "$d"; d=$((d*2)); n=$((n+1))
done
}
run_init
CI 门禁要点(建议全选)
terraform fmt -check -recursive与terraform validate在受保护分支必跑。terraform init -lockfile=readonly防止流水线悄悄改锁;锁更新只能在指定 bot job 执行。git diff --exit-code -- .terraform.lock.hcl或等价检查,确保 PR 意图与锁文件变更一致。- 磁盘水位脚本在 init 前执行,低于阈值直接
exit 42让队列调度到其他节点。
FAQ
Q:镜像已配仍慢? 核对 include/exclude 是否命中;TF_LOG 看是否仍打公网(常漏社区命名空间)。
Q:缓存路径冲突? 令 plugin_cache_dir 与 TF_PLUGIN_CACHE_DIR 指向同一目录,以生成式 .terraformrc 为准。
Q:多根目录? 每根模块各一份 .terraform.lock.hcl,矩阵分别校验。
Q:每次清缓存? 默认否;仅在校验失败、哈希异常或磁盘水位触发清理。