

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 了解 Terraform 状态和后端
<a name="states-and-backends"></a>

基础设施即代码 (IaC) 中最重要的概念之一是*状态*的概念。IaC 服务保持状态，这允许您在 IaC 文件中声明资源，而无需在每次部署时都重新创建该资源。IaC 文件记录了部署结束时所有资源的状态，这样它就可以将该状态与下一次部署中声明的目标状态进行比较。因此，如果当前状态包含`my-s3-bucket`名为的 Amazon Simple Storage Service (Amazon S3) 存储桶，并且传入的更改也包含相同的存储桶，则新流程将对现有存储桶应用发现的所有更改，而不是尝试创建全新的存储桶。

下表提供了常规 IaC 状态过程的示例。


****  

| 当前状态 | 目标状态 | 操作 | 
| --- | --- | --- | 
| 没有命名的 S3 存储桶 my-s3-bucket | 名为 S3 存储桶 my-s3-bucket | 创建名为的 S3 存储桶 my-s3-bucket | 
| my-s3-bucket未配置存储桶版本控制 | my-s3-bucket未配置存储桶版本控制 | 无需操作 | 
| my-s3-bucket未配置存储桶版本控制 | my-s3-bucket配置了存储桶版本控制 | 配置my-s3-bucket为使用存储桶版本控制 | 
| my-s3-bucket配置了存储桶版本控制 | 没有命名的 S3 存储桶 my-s3-bucket | 正在尝试删除 my-s3-bucket | 

要了解 AWS CloudFormation 和Terraform跟踪状态的不同方式，重要的是要记住这两个工具之间的第一个基本区别：托管在内部 AWS 云，而Terraform本质上 CloudFormation 是远程的。这一事实 CloudFormation 允许在内部维持状态。你可以进入 CloudFormation 控制台查看给定堆栈的事件历史记录，但 CloudFormation 服务本身会为你强制执行状态规则。

在给定资源下 CloudFormation 运行的三种模式是`Create``Update`、和`Delete`。当前模式是根据上次部署中发生的情况确定的，否则无法对其产生影响。你也许可以手动更新 CloudFormation 资源以影响所确定的模式，但你不能向其传递一条写 CloudFormation 着 “对于这个资源，在`Create`模式下操作” 的命令。

由于 Terraform 未托管在中 AWS 云，因此维护状态的过程必须更具可配置性。因此，[Terraform 状态](https://developer.hashicorp.com/terraform/language/state)保存在自动生成的状态文件中。Terraform 开发者必须比处理状态更直接地处理状态。 CloudFormation要记住的重要一点是，跟踪状态对两个工具同样重要。

默认情况下，Terraform 状态文件存储在本地运行 Terraform 堆栈的主目录的顶层。如果你在本地开发环境中运行该`terraform apply`命令，你可以看到 Terraform 生成了它用来实时维护**状态的 terraform.tfstat** e 文件。不管好坏，这让你对Terraform状态的控制比你在Terraform中的状态要多得多。 CloudFormation虽然你永远不应该直接更新状态文件，但你可以运行几个 Terraform CLI 命令来更新两次部署之间的状态。例如，[terraform 导入](https://developer.hashicorp.com/terraform/cli/import)允许您将在 Terraform 之外创建的资源添加到部署堆栈中。相反，你可以通过运行 [terraform](https://developer.hashicorp.com/terraform/cli/commands/state/rm) state rm 将资源从状态中移除。

*Terraform 需要将其状态存储在某个地方，这一事实导致了另一个不适用于后端的概念。 CloudFormation*[Terraform 后端](https://developer.hashicorp.com/terraform/language/settings/backends/configuration)是 Terraform 堆栈在部署后存储其状态文件的地方。这也是它期望在新部署开始时找到状态文件的地方。如上所述，在本地运行堆栈时，可以在顶级本地目录中保存 Terraform 状态的副本。这被称为*本地后端*。

在为持续集成和持续部署 (CI/CD) 环境进行开发时，本地状态文件通常包含在 **.gitignore** 文件中，以使其不受版本控制。然后管道中就没有本地状态文件了。为了正常工作，该管道阶段需要在某处找到正确的状态文件*。*这就是为什么 Terraform 配置文件通常包含后端块的原因。后端块向 Terraform 堆栈表明，它需要在自己的顶级目录之外寻找其他地方才能找到状态文件。

Terraform 后端几乎可以位于任何地方：[亚马逊 S3 存储桶](https://developer.hashicorp.com/terraform/language/settings/backends/s3)、[API 终端节点，](https://developer.hashicorp.com/terraform/language/settings/backends/http)甚至是[远程 Ter](https://developer.hashicorp.com/terraform/language/settings/backends/remote) raform 工作空间。以下是存储在 Amazon S3 存储桶中的 Terraform 后端的示例。

```
terraform {
  backend "s3" {
    bucket = "my-s3-bucket"
    key    = "state-file-folder"
    region = "us-east-1"
  }
}
```

为了避免在 Terraform 配置文件中存储敏感信息，后端还支持部分配置。在前面的示例中，配置中不存在访问存储桶所需的凭证。凭证可以从环境变量中获取，也可以通过其他方式获取，例如 AWS Secrets Manager。有关更多信息，请参阅[使用 AWS Secrets Manager 和 HashiCorp Terraform 保护敏感数据](https://docs.aws.amazon.com/prescriptive-guidance/latest/secure-sensitive-data-secrets-manager-terraform/introduction.html)。

常见的后端场景是在本地环境中用于测试目的的本地后端。**terraform.tfstat** e 文件包含在 **.gitignore** 文件中，因此不会将其推送到远程存储库。然后，CI/CD 管道中的每个环境都将维护自己的后端。在这种情况下，可能有多个开发人员可以访问此远程状态，因此您需要保护状态文件的完整性。如果多个部署同时运行并更新状态，则状态文件可能会损坏。因此，在非本地后端的情况下，状态文件通常在部署期间[被锁定](https://developer.hashicorp.com/terraform/language/state/locking)。