Terraform 命令速查表 - Terraform 基础设施即代码常用命令大全
用 Terraform 的节奏是固定的:plan 看差异、apply 落库、destroy 谨慎使用。理解这套流程的关键在于状态文件——它记录着资源与现实世界的对应关系,是整套工具的事实来源。状态丢了会导致下次 plan 想重建所有资源,状态与现实不一致则会引发误删,所以团队协作必须配远程后端并开启锁机制。本表按核心工作流、状态管理、变量与输出、模块、远程后端、高级功能、调试与排障分组。实际写代码时还有几条铁律:敏感值走变量或敏感标记而不是硬编码,state 文件含凭据不可入库,terraform fmt 让 diff 更干净。排障时 state list 与 state show 是第一步,refresh-only 则是修正状态偏差的最小手段。
典型使用场景
面向负责云上基础设施即代码的工程师。日常节奏是 `init → plan → apply` 三步,但真正吃掉时间的是另外几件事,本表重点覆盖它们:状态管理——`state list`/`show`/`mv`/`rm`/`import` 是排查「资源漂移」和「配置与实际不符」的主力工具,`taint`/`untaint` 控制强制重建;远程后端——S3 存状态、DynamoDB 做状态锁,是团队协作与并发 apply 的前提;`count` 与 `for_each` 两种批量创建方式的取舍;以及 `terraform console`、`TF_LOG` 调试表达式和输出日志。`workspace` 则用来隔离 staging 与 prod 的状态。
核心工作流 Core Workflow 7
terraform initterraform planterraform applyterraform destroyterraform fmtterraform validateterraform apply -auto-approve状态管理 State Management 9
terraform state listterraform state show <resource>terraform state mv <src> <dst>terraform state rm <resource>terraform state pullterraform state pushterraform import <address> <id>terraform taint <resource>terraform untaint <resource>变量与输出 Variables & Outputs 8
variable "region" {\n type = string\n default = "us-east-1"\n}var.regionTF_VAR_region=us-west-2terraform plan -var="region=us-west-2"output "ip" {\n value = aws_instance.web.public_ip\n}terraform outputterraform output -jsonlocals {\n name = "${var.prefix}-web"\n}模块使用 Modules 6
module "vpc" {\n source = "terraform-aws-modules/vpc/aws"\n version = "5.0.0"\n}module "vpc" {\n source = "./modules/vpc"\n}module "vpc" {\n source = "git::https://example.com/vpc.git"\n}module.vpc.vpc_idterraform init -upgradeterraform get远程后端 Remote Backends 6
terraform {\n backend "s3" {\n bucket = "my-tf-state"\n key = "prod/terraform.tfstate"\n region = "us-east-1"\n }\n}terraform {\n backend "s3" {\n dynamodb_table = "tf-lock"\n }\n}data "terraform_remote_state" "db" {\n backend = "s3"\n config = {\n bucket = "shared-state"\n key = "db/terraform.tfstate"\n }\n}data.terraform_remote_state.db.outputs.db_endpointterraform init -reconfigureterraform init -migrate-state高级功能 Advanced Features 9
terraform workspace new stagingterraform workspace listterraform workspace select stagingresource "aws_instance" "web" {\n for_each = var.subnets\n}resource "aws_instance" "web" {\n count = var.instance_count\n}depends_on = [aws_s3_bucket.data]lifecycle {\n create_before_destroy = true\n}lifecycle {\n prevent_destroy = true\n}lifecycle {\n ignore_changes = [tags]\n}调试与排障 Debugging 8
terraform consoleterraform graph | dot -Tpng > graph.pngterraform showterraform show -jsonTF_LOG=DEBUG terraform applyTF_LOG=TRACE terraform planTF_LOG_PATH=./tf.log terraform applyexport TF_LOG=WARN参数矩阵
| 参数 | 作用 | 示例 |
|---|---|---|
init | 初始化工作目录,下载 Provider 与模块 | terraform init |
init -upgrade | 升级模块到当前允许的最新版本 | terraform init -upgrade |
init -reconfigure | 重新配置后端(迁移状态) | terraform init -reconfigure |
init -migrate-state | 把状态文件迁移到新后端 | terraform init -migrate-state |
plan -var="k=v" | 命令行传入变量值 | terraform plan -var="region=us-west-2" |
apply -auto-approve | 跳过人工确认,CI 场景使用 | terraform apply -auto-approve |
validate / fmt | 校验配置一致性 / 统一代码格式 | terraform fmt |
state list / show | 列出状态中的资源 / 查看单个资源详情 | terraform state list |
state mv <src> <dst> | 移动资源在状态中的地址 | terraform state mv aws_instance.a aws_instance.b |
state rm <res> | 只从状态移除,不销毁真实资源 | terraform state rm aws_s3_bucket.old |
import <addr> <id> | 把已有资源纳管进 Terraform | terraform import aws_instance.web i-0123456789 |
taint / untaint <res> | 标记损坏下次重建 / 取消标记 | terraform taint aws_instance.web |
output / output -json | 查看输出值 / 以 JSON 形式查看 | terraform output -json |
workspace new/select/list | 创建 / 切换 / 列出工作空间 | terraform workspace select staging |
count / for_each | 按计数或按集合批量创建资源 | count = var.instance_count |
console | 交互式控制台,测试表达式 | terraform console |
TF_LOG / TF_LOG_PATH | 设置日志级别(TRACE/DEBUG/INFO/WARN/ERROR)与输出路径 | TF_LOG_PATH=./tf.log terraform apply |
易错点与避坑指南
现象apply 报 state 已被占用 / 锁超时,多人同时操作时互相阻塞
原因远程后端没有配置状态锁,或只用了 S3 而没加锁表。
处置在 backend "s3" 里补 `dynamodb_table = "tf-lock"`,然后 `terraform init -migrate-state`。
现象plan 里出现大量并非本次改动造成的差异
原因远端资源被人手工改过,本地 state 与实际出现漂移。
处置先用 `terraform state list` 和 `terraform state show <资源>` 确认,再 `terraform apply` 让状态与配置重新对齐;重大差异先 `terraform plan -out` 存档审阅。
现象换了资源名后 Terraform 想「销毁旧的 + 创建新的」,而旧资源不能删
原因资源的地址变了,Terraform 无法判断二者是同一个东西。
处置用 `terraform state mv <旧地址> <新地址>` 把资源在新地址下认领,不要靠复制配置硬改。
现象资源已经手工删掉,apply 却在报创建冲突
原因state 里仍记录着这个已不存在的资源。
处置用 `terraform state rm <资源>` 从状态中摘除(该命令不删真实资源),再重新 apply。
现象输出里暴露数据库密码、密钥等敏感信息
原因state 文件本身就包含资源的全部属性,包括敏感字段;把它提交到 Git 就会扩散。
处置把敏感值放进 variable 且不设 default,通过环境变量或 CI secret 注入;state 目录加入 .gitignore,并开启远程后端加密。
现象CI 里 apply 卡在等待确认,流水线超时
原因没有加自动批准标志,命令停在交互确认。
处置在非交互环境一律使用 `terraform apply -auto-approve`,并确保流水线已经完成 `init` 与 `plan` 审阅环节。
现象把 count 改成 for_each(或反过来)后 Terraform 要销毁并重建整批资源
原因两者的资源地址形式不同,切换即等于换了身份。
处置在切换前用 `terraform state mv` 尽量迁移已有资源地址,或接受重建代价时先评估停机窗口。
排障路径
1确认本地状态里到底有哪些资源
terraform state list输出的资源地址是排查「缺失资源 / 多余资源」的第一手依据。
2查看单个资源的实际状态属性
terraform state show aws_instance.web用于对比配置与真实资源差异,定位漂移来源。
3把状态输出成 JSON 供 grep/jq 分析
terraform show -json适合在脚本里统计资源数量、比对 ID,或与 plan 结果做差异对比。
4交互式验证表达式是否算对
terraform console输入 var.region、local.name 之类表达式,直接看求值结果,比改完 plan 再试快得多。
5打开详细日志并落盘
TF_LOG=DEBUG TF_LOG_PATH=./tf.log terraform plan日志里能看到 Provider 实际发出的 API 请求与响应,是排查「资源外部系统改不了」的关键。
6用代码格式检查暴露潜在语法问题
terraform fmt -check -diffCI 中作为门禁使用,输出差异即为不符合规范的文件片段。
命令示例
先 plan 看清差异再 apply
terraform plan -out=tfplan
terraform show tfplanplan -out 存成文件后可以 terraform show tfplan 复核,再 terraform apply tfplan 执行同一份计划,保证执行的就是你审过的那版。
输出
# aws_instance.web will be updated in-place
~ resource "aws_instance" "web" {
~ instance_type = "t2.micro" -> "t3.medium"
}
Plan: 0 to add, 1 to change, 0 to destroy.漂移检测:现实与状态不一致时
terraform plan -detailed-exitcode
echo $?退出码 0=无变更、1=有错误、2=有变更且非破坏性。这个约定让它能直接用在 CI 里做基础设施漂移检测。
输出
2
状态与现实脱节时让 Terraform 忘记资源
terraform state rm aws_instance.web
terraform planstate rm 只改状态不动真实资源,plan 随即显示要重建——这正是「删掉重建」而非误删。直接用 destroy 会真删掉机器。
输出
# aws_instance.web will be created
+ resource "aws_instance" "web" {
+ id = "i-0abc123"
}
Plan: 1 to add, 0 to change, 0 to destroy.常见坑与注意事项
- apply 前必须先看 plan;对含 destroy 的计划不加 -auto-approve,确认无误再执行。
- 状态文件含敏感信息且不应提交 Git,生产环境必须配置远程后端并启用状态锁。
- terraform destroy 会删除所有受管资源,包括数据库;只想删单个资源应改用 -target 或从配置移除。
- for_each 的键变更会导致整个资源销毁重建;键要设计成稳定不变的标识。
- 切 workspace 前务必 terraform workspace show 确认当前环境,prod 与 staging 用错会出事。
- state rm 让人工创建的资源被 plan 判定为缺失从而重建;用于扶正漂移而非掩盖问题。
提示
- terraform plan 永远不会修改资源,放心使用
- 将敏感信息放在变量中,不要硬编码在 .tf 文件里
- 使用 terraform fmt 统一代码格式,团队协作必备
- state 文件包含敏感信息,切勿提交到 Git
- 使用 remote backend(如 S3+ DynamoDB)实现团队协作和状态锁
- terraform state show <资源地址> 可查看单个资源的完整属性,比反复 plan 更快定位差异来源。
- terraform refresh-only 只同步状态不改实际资源,状态漂移时比 apply 安全但仍需人工核对清单。
- tfvars 与同名变量后缀对应:terraform.tfvars 自动加载,环境专用值放 terraform.<env>.tfvars 显式指定。
常见问题
terraform plan 和 apply 为什么要分开跑?
plan 只计算并展示差异,不动任何资源;apply 才真正创建、修改或销毁。把 plan 单独跑一遍是把人工确认插进流程的机会,尤其对会触发重建或删除资源的改动。日常可以先 plan 存下输出,apply 时加 plan 指定的文件重放同一份计划,保证执行的正是你审过的那一版。
terraform state rm 和 terraform destroy 有什么区别?
destroy 会真的删除云上资源并从状态移除它;state rm 只是把资源从状态文件中摘掉,云上的实际资源仍在运行。适用场景完全不同:误用变量导致状态与现实不符时用 state rm 让 Terraform 忘记这个资源,从而避免它把资源「删掉重建」;要真正回收资源时才用 destroy。
workspace 应该在什么时候切换?
每个环境一个 workspace(如 staging、prod),用 terraform workspace new staging 创建、select 切换、list 查看。但 workspace 共享同一个后端状态文件,不同 workspace 的资源命名必须自己保证不冲突。更重要的是:workspace 是易错的,务必在每次操作前用 terraform workspace show 确认当前处于哪一个环境。
count 和 for_each 批量创建资源时该选哪个?
count 适用于创建完全相同的资源,只是数量不同;for_each 适用于每个实例配置不同的情况,比如不同子网或不同规格。因为 for_each 的键一旦变更,Terraform 会销毁并重建对应的整个资源,所以键要设计成稳定不变的标识;count 的序号在列表变动时同样会导致索引漂移引发重建。
状态文件应该提交到 Git 吗?
不应该,状态文件记录的是与真实资源的对应关系,包含敏感信息且极易产生冲突合并。正确做法是配置远程后端(backend "s3" 之类)把它放在对象存储或 Terraform Cloud 里,本地只保留配置代码。团队协作时还需要配置状态锁(如 S3 的 DynamoDB 锁或 Terraform Cloud),否则两个人同时 apply 会互相覆盖。
由 巧匠 维护
公开更新于 2026年7月21日,内容持续校对官方文档。