3. 本地状态与远程状态对比
Terraform 的状态文件(terraform.tfstate)记录了当前基础设施的真实映射关系:每个资源实例的地址、属性值、依赖关系以及元数据。默认情况下,执行 terraform init 后,状态文件会以明文 JSON 的形式保存在当前工作目录下,这就是“本地状态”。本地状态在单人、单机、短周期实验中足够方便,但一旦进入团队协作场景,它就会成为最脆弱的一环。
一、默认本地状态的协作缺陷
本地状态的核心问题在于:状态文件只存在于执行 Terraform 的那台机器上,而基础设施却是团队共享的。由此衍生出几类典型故障。
- 状态分裂(State Drift / Split Brain):成员 A 在本地 apply 后创建了 3 台 ECS 实例,状态文件留在 A 的电脑上;成员 B 拿到同一份 .tf 代码后执行 plan,Terraform 认为这些资源都不存在,于是再次创建,导致重复资源或冲突。
- 并发写入覆盖:两人几乎同时 apply,各自基于旧状态计算差异,后写入者会覆盖前者的状态,造成状态与真实资源不一致,后续 plan 出现大量“幽灵差异”。
- 敏感信息泄露:本地状态是明文 JSON,数据库密码、AK/SK、证书私钥等都会以明文写入。若被误提交到 Git,等同于凭据泄露。
- 状态丢失不可恢复:笔记本损坏、误删目录、切换分支时被覆盖,都会让状态文件消失。没有状态,Terraform 无法再管理已有资源,只能手工 import 或重建。
- 无法审计与追溯:谁在什么时候改了状态、改了什么,本地文件没有任何版本记录,出问题后难以定位。
二、远程状态的优势
远程状态(Remote State)把状态文件存放到一个共享的、支持锁与版本的后端中,常见后端包括 AWS S3 + DynamoDB、Terraform Cloud、Azure Storage、GCS、Consul 等。它带来的能力可以归纳为四点。
- 单一事实来源:所有成员读写同一份状态,plan 的基线一致,从根本上消除状态分裂。
- 状态锁:apply 期间对状态加锁,其他人要么等待要么失败退出,避免并发覆盖。S3 后端通过 DynamoDB 表实现锁,Terraform Cloud 内置锁机制。
- 版本与恢复:S3 开启版本控制后,每次状态写入都会生成新版本,可回滚到任意历史点;Terraform Cloud 保留完整的状态版本历史。
- 安全与权限:状态存放在受 IAM/存储策略保护的位置,可加密(SSE-KMS)、可限制访问范围,避免明文散落在个人电脑上。
此外,远程状态还支持 terraform_remote_state 数据源,让不同项目之间以只读方式引用输出值,实现“网络层输出 VPC ID,应用层读取 VPC ID”的解耦协作。
三、迁移决策:什么时候必须切到远程状态
判断是否需要远程状态,可以看三个信号:是否多人协作、是否在 CI/CD 中执行 apply、是否管理生产环境。只要命中任意一条,就应使用远程状态。反之,个人学习、一次性实验、临时沙箱可以继续用本地状态,但建议至少把状态文件加入 .gitignore。
迁移本身并不复杂,核心是配置 backend 并执行 init 迁移。以下是一个 S3 后端的示例配置:
terraform {
backend "s3" {
bucket = "my-terraform-state-prod"
key = "network/terraform.tfstate"
region = "cn-north-1"
dynamodb_table = "terraform-lock"
encrypt = true
}
}
配置完成后执行 terraform init -migrate-state,Terraform 会提示是否把本地状态复制到远程后端,确认后本地状态被上传,后续操作全部走远程。若只想重新配置而不迁移,可用 terraform init -reconfigure。迁移前务必先备份本地 terraform.tfstate,并确认后端桶已开启版本控制、DynamoDB 锁表已创建且主键为 LockID。
四、常见误区
- “用了远程状态就不会冲突了”:远程状态只解决状态文件层面的并发,代码层面的同一资源被两个配置管理仍会冲突。锁是保护状态,不是保护资源。
- “把 state 提交到 Git 就等于远程状态”:Git 没有锁、没有实时读写,且历史中的明文密钥无法彻底清除,这是最危险的误区。
- “后端配置可以随便改”:修改 backend 块后必须重新 init,否则 Terraform 仍按旧后端读写,可能出现“状态找不到”的假象。
- “远程状态一定安全”:若 S3 桶策略过宽、未开加密、未限制访问,状态中的敏感值同样会泄露。安全取决于后端配置,而非“远程”二字。
- “迁移后本地文件可以删了”:迁移成功后本地状态会被清空或标记为已迁移,但迁移前应保留备份,确认远程状态可正常 plan 后再清理。
env/dev/terraform.tfstate、env/prod/terraform.tfstate,避免环境之间互相污染;同时为状态桶开启访问日志与版本控制,把“状态可恢复”作为底线要求。总结来看,本地状态适合单人快速验证,远程状态是团队协作与生产管理的必要条件。迁移决策的关键不是“要不要用远程”,而是“什么时候必须用、用什么后端、如何保证锁与版本”。把状态当作团队共享的基础设施资产来治理,后续的模块化、CI/CD 与权限体系才有稳固的落脚点。