Terraform 状态基础 #
什么是状态? #
Terraform 状态是 Terraform 跟踪管理资源的方式。状态文件记录了 Terraform 管理的所有资源及其属性,是 Terraform 实现声明式配置的关键。
text
┌─────────────────────────────────────────────────────────────┐
│ 状态的作用 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 资源映射 │ │ 状态跟踪 │ │ 依赖关系 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ - 配置与真实资源的映射 │
│ - 记录资源当前状态 │
│ - 存储资源依赖关系 │
│ - 提高性能(缓存) │
│ │
└─────────────────────────────────────────────────────────────┘
状态文件 #
默认状态文件 #
Terraform 默认在当前目录创建 terraform.tfstate 文件:
text
project/
├── main.tf
├── terraform.tfstate 状态文件
├── terraform.tfstate.backup 备份文件
└── .terraform/
状态文件结构 #
json
{
"version": 4,
"terraform_version": "1.6.6",
"serial": 1,
"lineage": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"outputs": {
"instance_ip": {
"value": "54.123.45.67",
"type": "string"
}
},
"resources": [
{
"mode": "managed",
"type": "aws_instance",
"name": "example",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"id": "i-1234567890abcdef0",
"ami": "ami-0c55b159cbfafe1f0",
"instance_type": "t2.micro",
"public_ip": "54.123.45.67",
"tags": {
"Name": "example-instance"
}
}
}
]
}
],
"check_results": null
}
状态文件字段说明 #
text
┌─────────────────────────────────────────────────────────────┐
│ 状态文件字段 │
├─────────────────────────────────────────────────────────────┤
│ │
│ version 状态文件格式版本 │
│ terraform_version 创建状态的 Terraform 版本 │
│ serial 状态序列号(每次更新递增) │
│ lineage 状态唯一标识符 │
│ outputs 输出值 │
│ resources 资源列表 │
│ check_results 检查结果 │
│ │
└─────────────────────────────────────────────────────────────┘
状态的作用 #
1. 资源映射 #
text
┌─────────────────────────────────────────────────────────────┐
│ 资源映射 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 配置文件 状态文件 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ aws_instance │ -> │ i-1234567890 │ │
│ │ "example" │ │ │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ Terraform 通过状态文件知道: │
│ - 哪些资源已被创建 │
│ - 资源的真实 ID │
│ - 资源的当前属性 │
│ │
└─────────────────────────────────────────────────────────────┘
2. 状态跟踪 #
hcl
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
text
┌─────────────────────────────────────────────────────────────┐
│ 状态跟踪 │
├─────────────────────────────────────────────────────────────┤
│ │
│ terraform plan 时: │
│ 1. 读取状态文件 │
│ 2. 刷新状态(获取真实资源状态) │
│ 3. 对比配置与状态 │
│ 4. 生成执行计划 │
│ │
│ terraform apply 时: │
│ 1. 执行变更 │
│ 2. 更新状态文件 │
│ │
└─────────────────────────────────────────────────────────────┘
3. 依赖关系 #
状态文件存储资源间的依赖关系,确保正确的创建和销毁顺序。
text
┌─────────────────────────────────────────────────────────────┐
│ 依赖关系 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 创建顺序: │
│ VPC → Subnet → Security Group → Instance │
│ │
│ 销毁顺序(反向): │
│ Instance → Security Group → Subnet → VPC │
│ │
│ 状态文件记录这些依赖关系 │
│ │
└─────────────────────────────────────────────────────────────┘
4. 元数据存储 #
状态文件存储资源的元数据:
json
{
"dependencies": [
"aws_subnet.public",
"aws_security_group.web"
],
"deposed_key": ""
}
状态管理挑战 #
1. 团队协作 #
text
┌─────────────────────────────────────────────────────────────┐
│ 团队协作问题 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 本地状态文件: │
│ ❌ 无法共享 │
│ ❌ 无法协作 │
│ ❌ 容易冲突 │
│ ❌ 容易丢失 │
│ │
│ 解决方案:远程状态 │
│ ✅ 集中存储 │
│ ✅ 状态锁定 │
│ ✅ 版本控制 │
│ ✅ 团队共享 │
│ │
└─────────────────────────────────────────────────────────────┘
2. 敏感信息 #
json
{
"attributes": {
"password": "my-secret-password",
"api_key": "secret-api-key"
}
}
状态文件可能包含敏感信息:
text
┌─────────────────────────────────────────────────────────────┐
│ 敏感信息处理 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ⚠️ 状态文件中的敏感信息是明文 │
│ │
│ 解决方案: │
│ 1. 加密状态文件 │
│ 2. 限制访问权限 │
│ 3. 使用远程后端(支持加密) │
│ 4. 不要将状态文件提交到版本控制 │
│ │
└─────────────────────────────────────────────────────────────┘
3. 状态锁定 #
text
┌─────────────────────────────────────────────────────────────┐
│ 状态锁定 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 并发问题: │
│ 用户 A: terraform apply │
│ 用户 B: terraform apply ← 同时执行 │
│ │
│ 可能导致: │
│ ❌ 状态损坏 │
│ ❌ 资源冲突 │
│ ❌ 不一致状态 │
│ │
│ 解决方案:状态锁定 │
│ ✅ 同一时间只有一个操作 │
│ ✅ 远程后端支持锁定 │
│ │
└─────────────────────────────────────────────────────────────┘
状态安全 #
1. 不要提交状态文件 #
gitignore
.terraform/
*.tfstate
*.tfstate.*
*.tfvars
2. 加密状态文件 #
使用远程后端加密:
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
kms_key_id = "alias/terraform-state-key"
}
}
3. 限制访问权限 #
bash
chmod 600 terraform.tfstate
4. 定期备份 #
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
skip_metadata_api_check = false
}
}
状态刷新 #
自动刷新 #
Terraform 在 plan 和 apply 时会自动刷新状态:
bash
terraform plan
terraform apply
手动刷新 #
bash
terraform refresh
刷新过程 #
text
┌─────────────────────────────────────────────────────────────┐
│ 刷新过程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 读取状态文件 │
│ 2. 对每个资源调用 Provider API │
│ 3. 获取资源的当前状态 │
│ 4. 更新状态文件 │
│ │
│ 注意: │
│ - 刷新会修改状态文件 │
│ - 可能检测到配置漂移 │
│ - 资源被手动修改时会更新 │
│ │
└─────────────────────────────────────────────────────────────┘
状态文件版本 #
版本兼容性 #
text
┌─────────────────────────────────────────────────────────────┐
│ 版本兼容性 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Terraform 版本与状态版本: │
│ - Terraform 0.12+ → 状态版本 4 │
│ - Terraform 0.7-0.11 → 状态版本 3 │
│ │
│ 升级 Terraform 时: │
│ - 通常向后兼容 │
│ - 可能需要状态升级 │
│ - 建议先备份状态 │
│ │
└─────────────────────────────────────────────────────────────┘
状态升级 #
bash
terraform state replace-provider
状态最佳实践 #
1. 使用远程状态 #
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
2. 分离状态文件 #
text
project/
├── environments/
│ ├── dev/
│ │ └── terraform.tfstate
│ ├── staging/
│ │ └── terraform.tfstate
│ └── prod/
│ └── terraform.tfstate
└── modules/
3. 状态隔离 #
hcl
resource "aws_s3_bucket" "state" {
bucket = "my-terraform-state"
versioning {
enabled = true
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
}
}
}
}
4. 定期备份 #
hcl
resource "aws_s3_bucket_versioning" "state" {
bucket = aws_s3_bucket.state.id
versioning_configuration {
status = "Enabled"
}
}
下一步 #
了解了状态基础后,接下来学习 远程状态,了解如何配置和使用远程状态存储!
最后更新:2026-03-29