# Terraform 状态管理与团队协作最佳实践


Terraform 的 State 文件是基础设施即代码的核心，它记录了真实资源与配置之间的映射关系。在团队协作中，State 管理不当会导致资源漂移、状态锁冲突甚至基础设施被意外销毁。

本文总结 State 管理的最佳实践，涵盖远程后端配置、状态锁、工作区隔离和日常运维技巧。

<!--more-->

### 1. 永远不要使用本地 State

默认情况下 Terraform 将状态存储在本地 `terraform.tfstate` 文件中，这在团队协作中是灾难性的：

- 多人同时 apply 会互相覆盖
- State 文件丢失意味着 Terraform 失去对所有资源的追踪

**配置远程后端（以 S3 为例）：**

```hcl
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/network/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
```

关键点：
- `encrypt = true` 确保 State 静态加密
- `dynamodb_table` 提供状态锁，防止并发写入

---

### 2. 状态锁 (State Locking)

状态锁确保同一时间只有一个操作可以修改 State，避免并发冲突。

| 后端 | 锁机制 |
|------|--------|
| S3 | DynamoDB |
| GCS | 内置锁 |
| Azure Blob | Blob Lease |
| Consul | KV Lock |

**锁卡住时的处理：**

```bash
# 查看当前锁信息（报错时会显示 Lock ID）
# 确认没有其他人在操作后，强制解锁
terraform force-unlock <lock-id>
```

> ⚠️ `force-unlock` 是危险操作，使用前务必确认没有其他 apply 正在进行。

---

### 3. State 隔离策略

#### 方式一：按目录隔离（推荐）

将不同环境和模块拆分到独立目录，每个目录有自己的 State：

```
infrastructure/
├── modules/
│   ├── vpc/
│   └── ecs/
├── prod/
│   ├── network/
│   │   └── main.tf    # state: prod/network/terraform.tfstate
│   └── compute/
│       └── main.tf    # state: prod/compute/terraform.tfstate
└── staging/
    ├── network/
    └── compute/
```

优点：
- 爆炸半径小，一个目录出问题不影响其他资源
- 权限可以按目录粒度控制
- `plan` / `apply` 速度快

#### 方式二：Workspace 隔离

```bash
terraform workspace new staging
terraform workspace new prod
terraform workspace select prod
```

适用于环境之间配置差异很小的场景。State 会按 workspace 名称自动隔离。

> 不推荐用 workspace 隔离 prod 和 staging，因为它们共享同一份代码和后端配置，容易误操作。

---

### 4. 跨 State 数据引用

不同目录的 State 之间需要共享数据时，使用 `terraform_remote_state`：

```hcl
data "terraform_remote_state" "network" {
  backend = "s3"
  config = {
    bucket = "my-terraform-state"
    key    = "prod/network/terraform.tfstate"
    region = "us-east-1"
  }
}

# 引用 network 层输出的 VPC ID
resource "aws_instance" "app" {
  subnet_id = data.terraform_remote_state.network.outputs.subnet_id
}
```

> 更好的替代方案是使用 `data` 数据源直接查询云资源（如 `aws_vpc`），减少 State 之间的耦合。

---

### 5. State 日常运维命令

```bash
# 查看当前 State 中的所有资源
terraform state list

# 查看某个资源的详细属性
terraform state show aws_instance.app

# 从 State 中移除资源（不删除真实资源）
terraform state rm aws_instance.legacy

# 将资源移动到新地址（重构代码后使用）
terraform state mv aws_instance.old aws_instance.new

# 从真实环境导入已有资源到 State
terraform import aws_instance.app i-1234567890abcdef0

# 拉取远程 State 到本地查看
terraform state pull > state.json
```

---

### 6. 安全注意事项

- **State 包含敏感信息：** 数据库密码、密钥等明文存储在 State 中，务必加密存储并限制访问权限。
- **S3 Bucket 策略：** 开启版本控制（Versioning），便于 State 回滚；配置 Bucket Policy 限制访问。
- **CI/CD 中的 State：** Pipeline 中使用的 IAM Role 应遵循最小权限原则，只授予必要的 State 读写权限。
- **`.gitignore` 必须包含：**
  ```
  *.tfstate
  *.tfstate.backup
  .terraform/
  ```

---

