跳到主要内容

安装与快速上手

安装​

Terraform 本体是单个二进制文件,安装方式很多,挑顺手的来。

macOS​

brew tap hashicorp/tap
brew install hashicorp/tap/terraform
提示

直接 brew install terraform 装到的是 homebrew-core 里停留在 1.5.x 的旧版(许可变更前的最后一个 MPL 版本)。想用当前版本,走上面的 HashiCorp 官方 tap。

官网下载(macOS / Linux 通用)​

到官网下载页拿对应平台的 zip,解压后把二进制放进 PATH:

# 以 Linux amd64 为例,版本号换成当时最新的
curl -LO https://releases.hashicorp.com/terraform/1.9.8/terraform_1.9.8_linux_amd64.zip
unzip terraform_1.9.8_linux_amd64.zip
sudo mv terraform /usr/local/bin/

macOS 在同一下载页选 darwin 包即可,步骤一样。

Linux 包管理器​

# Ubuntu / Debian(HashiCorp 官方源)
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install -y terraform

# RHEL / CentOS / Fedora
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/fedora/hashicorp.repo
sudo dnf install -y terraform

用 tfenv 管多版本(推荐)​

和 Node 的 nvm 一个思路:不同项目可能锁定不同的 Terraform 版本,tfenv 让你按目录切换。这类版本管理工具的安装思路和坑(镜像加速、目录自动切换)在 nvm 安装与镜像加速 里写过,可以对照着看。

# macOS
brew install tfenv

# 装一个指定版本并设为默认
tfenv install 1.9.8
tfenv use 1.9.8

# 项目目录放一个 .terraform-version 文件,进入目录自动切换
echo "1.9.8" > .terraform-version

验证​

terraform version
Terraform v1.9.8
on darwin_arm64

第二行的 darwin_arm64 表示这是 Apple Silicon 的原生 arm64 构建;Intel Mac 显示 darwin_amd64,Linux 对应 linux_amd64 / linux_arm64。

第一个练习:local_file​

第一个练习不碰任何云账号,用 hashicorp/local 这个官方 provider 在本机生成一个文件,把完整工作流跑一遍。

新建一个空目录,写一个 main.tf:

terraform {
required_version = ">= 1.9"

required_providers {
local = {
source = "hashicorp/local"
version = "~> 2.5"
}
}
}

resource "local_file" "hello" {
filename = "${path.module}/hello.txt"
content = "Hello from Terraform!\n"
}

逐块说明:

  • terraform 块:整个配置的元信息。required_version 限定 Terraform 本体版本;required_providers 声明要用哪个 provider 及版本约束,hashicorp/local 表示 registry 上 hashicorp 命名空间下的 local provider。
  • resource 块:声明一个资源。local_file 是资源类型,hello 是这个实例的名字,合起来的完整地址是 local_file.hello。
  • ${path.module} 是 HCL 插值,代表「当前模块所在目录」,所以 filename 最终就是当前目录下的 hello.txt。
提示

Terraform 命令要在 main.tf 所在目录执行,它会把当前目录所有 .tf 文件拼成一份完整配置。一个目录就是一套环境,别在一个目录里混两套互不相关的资源。

四步流程实操​

第一步:terraform init​

terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/local versions matching "~> 2.5"...
- Installing hashicorp/local v2.5.3...
- Installed hashicorp/local v2.5.3 (signed by HashiCorp)

Terraform has been successfully initialized!

init 做了三件事:

  1. 初始化 backend:决定 state 存哪里,默认本地文件,输出里第一行就是这一步。
  2. 下载 provider:按 required_providers 的约束去 registry 找匹配版本,装进当前目录的 .terraform/ 缓存目录。这个目录不进 git。
  3. 生成锁文件:.terraform.lock.hcl 记录每个 provider 的精确版本和校验哈希,保证团队所有人和 CI 下载到的是同一份插件。

第二步:terraform plan​

terraform plan
Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# local_file.hello will be created
+ resource "local_file" "hello" {
+ content = "Hello from Terraform!\n"
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./hello.txt"
+ id = (known after apply)
}

Plan: 1 to add, 0 to change, 0 to destroy.

逐行解读:

  • + create 说明本计划里只有新建动作。Terraform 的符号约定:+ 新建、- 删除、~ 原地修改、-/+ 先删后建(替换)。
  • will be created 加上每行属性前的 + 前缀,表示这些值即将被写入。
  • (known after apply) 表示这个值(这里是资源 id)要等真正创建后才知道。
  • 结尾的汇总 1 to add, 0 to change, 0 to destroy 是最该扫一眼的一行:数字符合预期再继续,不符合就回头查配置。
注意

plan 不改动任何真实资源,可以放心随便跑。养成「apply 前先 plan 看一遍」的习惯,它是你和生产事故之间的最后一道防线。

第三步:terraform apply​

terraform apply

输出和 plan 相同,结尾多一个交互确认:

Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.

Enter a value: yes

local_file.hello: Creating...
local_file.hello: Creation complete after 0s [id=46d27a1cd59c6b3f1f1298dd8a667232a1f2fe08]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

输入 yes 回车后真正执行。此时目录下多了两样东西:

  • hello.txt:练习的目标产物,cat 一下就是那句 Hello from Terraform!。
  • terraform.tfstate:state 文件,Terraform 的账本,下一节细说。

CI 等自动化场景没人敲 yes,用 terraform apply -auto-approve 跳过确认——前提是这个 plan 已经被人 review 过。

第四步:terraform destroy​

练完回收:

terraform destroy
Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
Enter a value: yes

local_file.hello: Destroying... [id=46d27a1cd59c6b3f1f1298dd8a667232a1f2fe08]
local_file.hello: Destruction complete after 0s

Destroy complete! Resources: 1 destroyed.

hello.txt 被删除,state 随之清空。destroy 同样有确认交互,同样支持 -auto-approve。

认识 state​

看一眼 terraform.tfstate 里记了什么(删减后):

{
"version": 4,
"terraform_version": "1.9.8",
"resources": [
{
"mode": "managed",
"type": "local_file",
"name": "hello",
"provider": "provider[\"registry.terraform.io/hashicorp/local\"]",
"instances": [
{
"attributes": {
"content": "Hello from Terraform!\n",
"filename": "./hello.txt",
"id": "46d27a1cd59c6b3f1f1298dd8a667232a1f2fe08"
}
}
]
}
]
}

本质是一张映射表:「配置里的 local_file.hello」对应「现实里 id 为 xxx 的那个文件」,外加属性快照。下次 plan 时 Terraform 拿着它和现实对比,才知道该增改删什么。

由此引出两条铁律:

  • 不能删:删了 state,Terraform 就「失忆」了——文件还在磁盘上,但它不知道那是自己管的,plan 会当成全新资源再建一遍。放到云资源场景,这就是「配置里没有、现实里一堆」的孤儿资源事故。
  • 不能绕过 Terraform 手改资源:直接改了现实资源(比如手工删掉 hello.txt),state 和现实就对不上了。下次 plan 会检测到漂移并试图拉回配置描述的状态——这是特性,但理解不了就会觉得「行为诡异」。
注意

state 里可能存敏感信息(数据库密码、私钥的明文)。本地练习无所谓,上生产必须换远端 backend 并加密存储,同时不要把 terraform.tfstate 提交进 git。

常用配置块​

main.tf 里会反复出现的几类块,先认个脸熟:

terraform {
required_version = ">= 1.9"

required_providers {
local = {
source = "hashicorp/local"
version = "~> 2.5"
}
}

# backend "s3" { ... } # 团队协作时 state 存远端,后续篇章细讲
}

provider "local" {
# 多数 provider 在这里填凭证、区域等参数;local provider 无可配项
}

要点:

  • required_version:约束 Terraform 本体版本,团队协作时写上,避免有人拿太老的版本执行出不一样的行为。
  • ~> 2.5 的写法:叫悲观版本约束(pessimistic constraint),含义是「2.5 及以上、但不到 3.0」,即 >= 2.5, < 3.0;再精确一点 ~> 2.5.0 则是 >= 2.5.0, < 2.6.0。日常用 ~> x.y 即可:吃得到补丁更新,又不会被大版本变更偷袭。
  • provider 块:配凭证和默认参数的地方。local provider 不用配;换成 docker、aws 这类,就要在这里写地址或密钥。
  • backend 块:state 存哪里。默认本地,多人协作必须换远端(S3、OSS、Terraform Cloud 等),本篇先用默认,后续篇章细讲。

常见问题​

拉 provider 慢或超时​

init 卡在 Installing hashicorp/local... 或报网络超时,是访问 registry.terraform.io 不稳定的常见现象。解法按优先级:

  1. 给终端配好代理后重跑 init,最直接。
  2. 配 CLI 镜像:在 ~/.terraformrc 里写 provider_installation 块,指向国内镜像站或本地目录,让 Terraform 换地方下载。
  3. 公司有内网制品库的话,走私有 registry。

.terraform.lock.hcl 要不要提交 git​

要。锁文件记录 provider 的精确版本和哈希,提交后团队和 CI 才能装到同一份插件,避免「我本地能跑、CI 上炸了」。反过来,.terraform/ 目录(插件缓存)和 state 文件要加进 .gitignore:

.terraform/
terraform.tfstate
terraform.tfstate.backup

Apple Silicon 注意 arm64​

M 系 Mac 上确认装的是 darwin_arm64 构建(terraform version 第二行可看)。个别老 provider 没发布 arm64 版本时,init 会报「no available releases」,解法要么升级 provider 版本,要么临时用 Rosetta 跑 amd64 构建。如今主流 provider 都已补齐 arm64,遇到的多半是年代久远的小众插件。

小结​

  • 安装任选 brew / 官网 zip / 包管理器;多版本管理用 tfenv,思路和 nvm 一致。
  • 第一个练习用 hashicorp/local 的 local_file,零云账号跑通全流程。
  • 四步命令记牢:init 装插件、plan 看差异、apply 真执行、destroy 做回收;plan 输出重点看 Plan: x to add, y to change, z to destroy 那行汇总。
  • state 是 Terraform 的账本:不删、不手改、不进 git。
  • ~> 是悲观版本约束;.terraform.lock.hcl 要提交,.terraform/ 和 state 要忽略。

环境跑通、流程走顺之后,下一篇开始讲变量、输出与 data source,给这套骨架填上血肉。