使用 Amazon S3 的 Terraform 状态管理
Source: Dev.to
请提供您希望翻译的正文内容,我将把它翻译成简体中文并保持原有的格式、Markdown 语法以及技术术语不变。
为什么 Terraform 状态很重要
Terraform 使用状态文件(terraform.tfstate)来跟踪它管理的基础设施。该文件包含你的配置与真实资源之间的映射,使 Terraform 能在后续运行中安全且可预测地进行更改。
默认情况下,Terraform 将状态存储在本地。这对于实验来说可以,但对 协作、自动化和生产使用 来说是 不安全 的。
为什么使用像 S3 这样的远程后端?
| 好处 | 描述 |
|---|---|
| 集中式状态 | 所有团队成员都可以访问 |
| 协作支持 | 防止用户之间出现“状态漂移” |
| 加密与 IAM | 安全的访问控制 |
| 版本控制 | 可轻松从意外删除或损坏中恢复 |
| 状态锁定 | 避免并发写入冲突 |
Terraform 官方文档确认 S3 是受支持的后端类型,可存储状态并支持锁定——它是 AWS 环境中最流行、最可靠的后端之一。
状态锁定 — 防止冲突
Terraform 必须防止两个人(或 CI 作业)同时向同一个状态文件写入更改;否则状态可能会被损坏。
现代锁定(S3 原生)
Terraform 现在通过锁文件机制支持 S3 原生状态锁定。Terraform 会在桶中与你的状态文件并列创建一个 .tflock 文件,从而阻止并发运行。
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket2z"
key = "envs/prod/terraform.tfstate"
region = "us-east-1"
use_lockfile = true
}
}
use_lockfile = true启用 S3 原生锁定。- S3 在 Terraform 运行期间创建
.tflock文件。 - 其他进程必须等到锁被释放后才能继续。
这消除了对单独 DynamoDB 表进行状态锁定的需求——这种方式已被官方标记为不推荐使用,并将在未来的 Terraform 版本中移除。
注意: 仍然支持 DynamoDB 锁定以保持向后兼容,但 Terraform 现在更倾向于在新配置中使用 S3 原生锁定。
前置条件
| 工具 | 命令 |
|---|---|
| AWS CLI(已安装并配置) | aws configure |
| Terraform(已安装) | terraform version |
| 权限 | 能够创建 S3 存储桶并应用 Terraform 更改 |
第一步 — 为 Terraform 状态创建 S3 存储桶
Terraform 不能为你创建后端存储桶,所以你必须先手动创建它。
aws s3api create-bucket \
--bucket my-terraform-state-bucket2z \
--region us-east-1
将 my-terraform-state-bucket2z 替换为全局唯一的名称。
第2步 — 启用存储桶版本控制(最佳实践)
版本控制可帮助您从意外删除或损坏中恢复。
aws s3api put-bucket-versioning \
--bucket my-terraform-state-bucket2z \
--versioning-configuration Status=Enabled
第 3 步 — 为存储桶启用加密
对静态状态进行加密对于安全至关重要。
aws s3api put-bucket-encryption \
--bucket my-terraform-state-bucket2z \
--server-side-encryption-configuration '{
"Rules": [{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}]
}'
故障排除:AccessDenied 错误
如果在运行加密命令时遇到 AccessDenied 错误:
An error occurred (AccessDenied) when calling the PutBucketEncryption operation: Access Denied
常见原因及解决办法
| 问题 | 解决方案 |
|---|---|
| IAM 权限不足 | 在 IAM 策略中添加 s3:PutEncryptionConfiguration。 |
| 存储桶不存在 | 验证存储桶名称:aws s3api head-bucket --bucket my-terraform-state-bucket2z |
| AWS 凭证错误 | 验证您的身份:aws sts get-caller-identity |
步骤 4 — 配置 Terraform 后端
在你的 Terraform 目录中,按如下方式定义后端:
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket2z"
key = "demo/terraform.tfstate"
region = "us-east-1"
use_lockfile = true
}
}
| 选项 | 描述 |
|---|---|
bucket | 你创建的 S3 存储桶 |
key | 在存储桶内用于存放状态文件的路径 |
use_lockfile | 启用原生 S3 状态锁定 |
演示:使用 S3 远程状态
1. 创建 Terraform 项目
mkdir terraform-s3-state-demo
cd terraform-s3-state-demo
2. 添加 Terraform 代码
创建文件 main.tf:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-terraform-state-bucket2z"
key = "demo/terraform.tfstate"
region = "us-east-1"
use_lockfile = true
}
}
(根据需要在此块下方添加其余基础设施资源。)
运行常规的 Terraform 工作流:
terraform init # Initializes the backend and downloads providers
terraform plan # Shows the execution plan
terraform apply # Applies the changes and stores state in S3
状态文件将存储在 s3://my-terraform-state-bucket2z/demo/terraform.tfstate,Terraform 会在每次运行时创建 .tflock 文件,以防止并发修改。
总结
将 Terraform 状态存储在 Amazon S3 远程后端并使用原生锁定功能,可为您提供:
- 集中式、具备版本控制且加密的状态存储
- 跨团队的安全协作
- 无需 DynamoDB 表即可实现自动状态锁定
将这些实践应用于任何在 AWS 上的生产 Terraform 工作流,您就能避免导致状态损坏和部署失败的常见陷阱。祝您配置愉快!
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket2z"
key = "demo/terraform.tfstate"
region = "us-east-1"
encrypt = true
use_lockfile = true
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "example" {
bucket = "tf-s3-backend-demo-example"
}
初始化后端
terraform init
Terraform 将初始化并自动配置后端。
应用更改
terraform apply
您的状态文件现在已存储在 S3 中,并已启用状态锁定。

有用的 Terraform 后端命令
将本地状态迁移到远程
terraform init -migrate-state
重新配置后端
terraform init -reconfigure
列出状态资源
terraform state list
检查资源
terraform state show aws_s3_bucket.example
附加最佳实践
远程存储状态
使用 S3 或 Terraform Cloud —— 切勿在团队环境中本地存储状态。
不要手动编辑或删除状态
手动更改会导致状态损坏。
按环境隔离状态
为不同环境使用不同的键:
envs/dev/terraform.tfstate
envs/staging/terraform.tfstate
envs/prod/terraform.tfstate
定期备份
启用 S3 版本控制,这样可以回滚因意外覆盖或删除而受损的状态。
对所有写入进行状态锁定
启用 use_lockfile = true。它确保一次只有一个 Terraform 进程可以修改状态,防止冲突和损坏。
清理:安全删除演示资源
步骤 1:销毁 Terraform 资源
terraform destroy

- 此命令将会:
- 从 S3 读取状态文件
- 识别所有受管理的资源
- 安全地将它们从 AWS 中删除
确认后,所有演示基础设施都会被移除,但 Terraform 状态文件仍然保留在 S3 中(这是预期行为)。
步骤 2:在 S3 中验证状态文件(可选)
aws s3 ls s3://my-terraform-state-bucket2z/demo/
Terraform 保留状态文件,以便您拥有:
- 受管理基础设施的记录
- 历史版本(如果启用了版本控制)
步骤 3:删除 Terraform 状态文件(可选)
aws s3 rm s3://my-terraform-state-bucket2z/demo/terraform.tfstate
警告: 在基础设施仍然存在时切勿删除状态文件——这会导致资源成为孤儿。
步骤 4:(可选)禁用或删除锁文件
如果您使用了 S3 原生锁定,Terraform 会在操作完成后自动删除 .tflock 文件。通常不需要手动删除。
步骤 5:删除 S3 后端存储桶(可选)
如果该存储桶仅为本演示创建:
清空存储桶
aws s3 rm s3://my-terraform-state-bucket2z --recursive
删除存储桶
aws s3api delete-bucket \
--bucket my-terraform-state-bucket2z \
--region us-east-1
清理最佳实践
- 始终先运行
terraform destroy。 - 在销毁资源之前,切勿删除状态文件。
- 对于长期项目,保留状态桶。
- 启用版本控制以便恢复。
- 使用 IAM 策略限制访问。
摘要
Terraform state 是基础设施自动化的基石。将其存储在具有原生状态锁定的远程 S3 后端:
- 实现安全协作
- 防止并发修改
- 允许受控恢复
- 支持 CI/CD 工作流
具有原生锁定的 S3 远程状态现在已成为 Terraform 推荐的最佳实践——在大多数情况下无需单独的 DynamoDB 锁表。
参考文献
最后思考
Terraform 状态清理与资源配置同样重要。
安全的清理过程可确保:
- 没有孤立的资源
- 没有意外的 AWS 费用
- 为后续工作提供干净的环境
使用远程状态时:Terraform 始终是真实来源 — 让它从头到尾管理整个生命周期。