使用 Amazon S3 的 Terraform 状态管理

发布: (2026年1月7日 GMT+8 15:02)
11 min read
原文: Dev.to

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 中,并已启用状态锁定。

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

Terraform 销毁输出

  • 此命令将会:
    • 从 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 始终是真实来源 — 让它从头到尾管理整个生命周期。

Back to Blog

相关文章

阅读更多 »