跳到主要内容

安装与工作区规范

本章目标:在本地装好 Terraform(或它的开源分支 OpenTofu),把版本锁死,并搭好后续章节共用的仓库骨架与 backend 选型心智模型。

完成后你应具备:

  1. terraform version 显示锁定版本(如 1.9.x)
  2. 仓库里有一份 .terraform-version 与 required_version 双重锁定
  3. 跑通 terraform init / fmt / validate
  4. 清楚本地 state 与远程 backend 的取舍

1. Terraform 还是 OpenTofu​

2023 年起 HashiCorp 将 Terraform 的许可证改为 BSL(不再宽松开源),社区随即 fork 出 OpenTofu(Linux 基金会托管,真正的 MPL 开源)。两者在 HCL 语法与命令上几乎完全兼容,本系列示例以 Terraform 命令为准,把 terraform 换成 tofu 通常也能直接跑。

命令差异

仅少数命令/特性分叉(如 OpenTofu 更早支持 import 块、for_each 的 import、状态加密等)。涉及差异处本系列会标注。日常 init / plan / apply / fmt / validate 完全一致。

团队统一二进制

同一个仓库、同一个环境,所有人(含 CI)必须用同一版本。否则 required_version 一旦约束到某小版本,版本不符的人连 plan 都跑不起来——这正是下一节要解决的。


2. 安装​

2.1 macOS(推荐 Homebrew)​

# Terraform
brew tap hashicorp/tap
brew install hashicorp/tap/terraform

# 或 OpenTofu
brew install opentofu

terraform version
# OpenTofu v1.8.x / Terraform v1.9.x

2.2 Linux(官方 zip 包,最通用)​

TERRAFORM_VERSION=1.9.5
curl -fsSL "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" -o /tmp/tf.zip
sudo unzip -o /tmp/tf.zip -d /usr/local/bin/
terraform version
别用系统包管理瞎装

部分发行版自带极老的 terraform(甚至 0.12),语法天差地别。生产仓库一律用官方二进制 + 版本锁定,别依赖系统版本。

2.3 用 tfenv 管多版本(强烈推荐)​

和 rbenv / nvm 一个思路,按项目切换:

# macOS
brew install tfenv
tfenv install 1.9.5
tfenv use 1.9.5

# 在仓库根放一份锁定文件,进入目录自动切换
echo "1.9.5" > .terraform-version
tfenv use # 读取 .terraform-version

3. 版本锁定:两层保险​

只靠口头约定版本迟早翻车。用两层锁定:

3.1 仓库级:.terraform-version​

给 tfenv / tofuenv 用,控制二进制本身的版本(见上)。

3.2 代码级:required_version​

写在 terraform {} 块里,控制配置能接受的解释器版本:

terraform {
required_version = ">= 1.5.0, < 1.10.0" # 允许 1.5~1.9,封住 1.10 的潜在破坏

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.40" # 允许 >= 5.40 且 < 6.0;若只允许 5.40.x,写 ~> 5.40.0
}
}
}
约束写法含义
>= 1.9.0不低于 1.9.0
~> 1.9.01.9.x,允许补丁/小版本,不跳主版本
~> 5.40>= 5.40, < 6.0;两位版本号会允许同一主版本内的后续 minor
~> 5.40.05.40.x;三位版本号才只允许补丁升级
>= 1.5.0, < 1.10.0区间,最稳
1.9.5精确锁定(不推荐,CI 升级麻烦)
Provider 也要锁

required_providers 里的 version 同样关键。Provider 升级可能改资源 schema,导致 state 不兼容。provider 版本必须和 terraform 版本一起进版本控制,并用 -upgrade=false(默认)避免误升。


4. 仓库骨架​

推荐一个「模块与环境分离」的结构,后续章节会持续用到:

terraform/
├── modules/ # 可复用模块(与具体环境解耦)
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── versions.tf
│ └── eks/
├── envs/ # 每个环境一套 root module
│ ├── staging/
│ │ ├── main.tf # 调用 ../../modules/*
│ │ ├── backend.tf # 该环境的远程 state 配置
│ │ ├── variables.tf
│ │ └── staging.tfvars # 环境特有变量
│ └── prod/
├── _global/ # 跨环境资源(IAM、Route53、组织策略)
└── .terraform-version

要点:

  • 模块放 modules/,只描述「如何造一个东西」,不含账号/地域等环境信息。
  • 环境放 envs/<env>/,用 module 调用模块,并把账号、地域、规格通过 tfvars 注入。
  • 这套结构天然支持「同一套模块,多套环境各跑各的 state」。第 4、6 章会展开。

5. 第一个 init / fmt / validate​

进入任一 envs/* 目录,先 init(下载 provider、连接 backend):

cd terraform/envs/staging
terraform init
# Initializing the backend...
# Terraform has been successfully initialized!

常用三板斧:

terraform fmt -recursive # 格式化全部 .tf(提交前必跑)
terraform validate # 校验语法与变量约束(不需要真实凭证)
terraform plan # 真正连云、算差异(需要凭证)
命令是否连云是否需要凭证用途
terraform fmt否否统一代码风格
terraform validate否否静态校验
terraform plan是是预览变更
terraform apply是是执行变更
CI 里先 validate 再 plan

validate 不连云、不花钱,适合在每次提交时秒级拦住低级语法错误;plan 才真正连云。CI 顺序: fmt --check → validate → init -input=false → plan。


6. backend 选型概览(详细见第 5 章)​

terraform init 时若没配 backend,state 默认落在本地 .terraform.tfstate——只适合你一个人、一台电脑的玩具。团队协作必须上远程 backend,它解决三件事:

诉求本地 state远程 backend
多人共享同一份真实状态❌✅
并发写锁(防止两人同时 apply 互相覆盖)❌✅(如 S3+DynamoDB、GCS、Azure Blob)
状态加密、版本、备份❌✅

常见 backend 选项:

  • AWS S3 + DynamoDB:最主流,S3 存 state、DynamoDB 加锁,均支持服务端加密
  • GCS(Google Cloud Storage):原生状态锁
  • Azure Blob Storage:原生状态锁
  • Terraform Cloud / Enterprise:托管 backend + 远程执行 + 策略
  • Consul / etcd:自建场景

选型先有个概念即可,第 5 章会把 S3 这套完整配通。


7. 练习与验收​

练习 A

  1. 用 tfenv 安装并锁定 1.9.x,确认 terraform version 输出符合预期
  2. 新建仓库骨架(上面第 4 节),在 envs/staging/ 放一个最小 versions.tf
  3. 跑 terraform fmt -check 与 terraform validate 均通过

练习 B

  1. 故意把 required_version 写低(如 = 1.0.0),观察 terraform validate 如何拦截
  2. 改回正确约束

验收清单

  • terraform version 显示锁定版本
  • 仓库含 .terraform-version 与 required_version 双重锁定
  • terraform fmt -check 通过(或已格式化)
  • terraform validate 通过
  • 已清楚本地 vs 远程 backend 的取舍

下一章:HCL 基础 —— 真正动手写 resource / variable / output,并用 count / for_each 批量生成资源。