适用场景:共享 Apple Silicon 远程 Mac Runner 上跑 terraform init,跨境访问 Terraform Registry 与自建 Provider Mirror 时,需要把并发、插件缓存、锁文件与有界重试写成可审计策略。
本文交付:评测阈值表、镜像/直连对比与决策矩阵、可复制环境变量与 terraform.rc、terraform providers lock 与 init -lockfile=readonly 等 CI 门禁,以及 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_arm64;include/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(每作业独立子目录)→ 有界重试 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/*/*"]
}
}
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 -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:TF_PLUGIN_CACHE_DIR 与 plugin_cache_dir 不一致? 以生成式 .terraformrc 为准,并与环境变量指向同一绝对路径。
Q:多根模块仓库? 每个根目录各自维护 .terraform.lock.hcl,矩阵 job 分别校验。
Q:是否每次清理插件缓存? 默认否;仅在哈希异常、校验失败或磁盘策略触发时清理,以保留命中。
总结
把超时、镜像路由、缓存路径、锁基线与重试上限写成一条策略,init 才可审计、可排障。若需要稳定 Apple Silicon 容量,可先浏览价格说明与购买页,并结合帮助中心做容量评估;更多文章见 博客列表(均无需登录)。