适用场景:共享 Apple Silicon 远程 Mac Runner 上跑 terraform init,跨境访问 Terraform Registry 与自建 Provider Mirror 时,需要把并发、插件缓存、锁文件与有界重试写成可审计策略。

本文交付:评测阈值表、镜像/直连对比与决策矩阵、可复制环境变量与 terraform.rcterraform providers lockinit -lockfile=readonlyCI 门禁,以及 FAQ

延伸阅读(免登录):Technik-Blog 列表Nix Flake 与 Substituter 决策矩阵MacPull 德语首页

常见故障形态:(1)多作业并发 init 争用 Registry 与同一插件缓存目录;(2).terraform.lock.hcl 在笔记本与 CI 平台集合不一致导致无意义 diff;(3)无限重试把坏镜像问题放大成全队列阻塞。下面用阈值 + 矩阵 + 命令清单 + 门禁一次性收口。

评测维度与阈值

下列阈值为跨境公网 + 共享 APFS的起步建议,请用你们真实流水线 init 的 p95、Registry 5xx 比例与锁文件变更频率做回归校准。另:terraform apply-parallelism 只影响资源并发,不解决 provider 下载瓶颈;下载阶段仍以 Registry/镜像与缓存为主战场。

维度 建议起步阈值 判读与动作
terraform init(含 provider 安装)p95 主干 < 120s;夜间大批量可放宽 240s 先补 network_mirror / filesystem_mirror,再调 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 治理 受保护分支禁止无说明哈希漂移;锁更新必须附命令记录 仅在黄金镜像上执行 terraform providers lock

观测提示:TF_LOG=INFO 区分 429/5xx 与本地解压;锁须覆盖 darwin_arm64include/exclude 与出站白名单一致才可过审计。

对比表或决策矩阵

决策焦点是谁提供可信 ZIP 与校验和direct 简单但怕跨境抖动;network_mirror 适合企业 HTTPS 镜像;filesystem_mirror 适合强隔离与间歇断网。混合路由务必写清 include/exclude,避免社区命名空间悄悄回落公网。

模式 最适配场景 主要风险 一句话结论
direct 直连 registry.terraform.io 原型、海外团队、无合规限制 跨境抖动、限流、DNS 分叉 监控 p95;生产勿单吊公网。
network_mirror 统一工件域、需审计出站 索引滞后、证书链不一致 锁在与 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(每作业独立子目录)→ 有界重试 initvalidate + 锁 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/*/*"]
  }
}
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
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 -recursiveterraform 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:TF_PLUGIN_CACHE_DIRplugin_cache_dir 不一致? 以生成式 .terraformrc 为准,并与环境变量指向同一绝对路径

Q:多根模块仓库? 每个根目录各自维护 .terraform.lock.hcl,矩阵 job 分别校验。

Q:是否每次清理插件缓存? 默认否;仅在哈希异常、校验失败或磁盘策略触发时清理,以保留命中。

总结

把超时、镜像路由、缓存路径、锁基线与重试上限写成一条策略,init 才可审计、可排障。若需要稳定 Apple Silicon 容量,可先浏览价格说明购买页,并结合帮助中心做容量评估;更多文章见 博客列表(均无需登录)。

在远程 Mac 上稳定跑 Terraform CI

结合镜像与缓存策略,把跨境抖动关在阈值与门禁之内。以下页面免登录即可阅读。