

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 了解 Terraform 狀態和後端
<a name="states-and-backends"></a>

基礎設施即程式碼 (IaC) 中最重要的概念之一是*狀態*的概念。IaC 服務會維持 狀態，可讓您在 IaC 檔案中宣告資源，而不必在每次部署時重新建立。IaC 檔案會在部署結束時記錄所有資源的狀態，以便將該狀態與目標狀態進行比較，如下次部署中所宣告。因此，如果目前狀態包含名為 的 Amazon Simple Storage Service (Amazon S3) 儲存貯體，`my-s3-bucket`而傳入的變更也包含相同的儲存貯體，則新程序會將找到的任何變更套用至現有儲存貯體，而不是嘗試建立新的儲存貯體。

下表提供一般 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 追蹤狀態的不同方式，請務必記住兩個工具之間的第一個基本差異：CloudFormation 託管在 內部 AWS 雲端，而 Terraform 基本上是遠端的。此事實可讓 CloudFormation 在內部維持狀態。您可以前往 CloudFormation 主控台並檢視指定堆疊的事件歷史記錄，但 CloudFormation 服務本身會為您強制執行狀態規則。

CloudFormation 在指定資源下操作的三種模式為 `Create`、 `Update`和 `Delete`。目前模式會根據上次部署中發生的情況來決定，否則無法受到影響。您或許可以手動更新 CloudFormation 資源，以影響決定哪個模式，但您無法將命令傳遞給 CloudFormation，其中指出「對於此資源，請在 `Create` 模式下操作」。

由於 Terraform 不在 中託管 AWS 雲端，因此維護狀態的程序必須更可設定。因此，[Terraform 狀態](https://developer.hashicorp.com/terraform/language/state)會維持在自動產生的狀態檔案中。與 CloudFormation 相比，Terraform 開發人員必須更直接地處理狀態。要記住的重要事項是，追蹤狀態對這兩個工具同樣重要。

根據預設，Terraform 狀態檔案會儲存在本機執行 Terraform 堆疊的主目錄最上層。如果您從本機開發環境執行 `terraform apply`命令，您可以看到 Terraform 產生用於即時維護狀態的 **terraform.tfstate** 檔案。為了更好或更差，這可讓您比在 CloudFormation 中更能控制 Terraform 中的狀態。雖然您不應該直接更新狀態檔案，但您可以執行數個 Terraform CLI 命令，以便在部署之間更新狀態。例如，[terraform import](https://developer.hashicorp.com/terraform/cli/import) 可讓您將 Terraform 外部建立的資源新增至部署堆疊。相反地，您可以透過執行 [terraform 狀態 rm 從狀態](https://developer.hashicorp.com/terraform/cli/commands/state/rm)移除資源。

Terraform 需要將其狀態存放在某個位置，這會導致另一個不適用於 CloudFormation 的概念：*後端*。[Terraform 後端](https://developer.hashicorp.com/terraform/language/settings/backends/configuration)是 Terraform 堆疊在部署後存放其狀態檔案的位置。這也是它預期在新部署開始時尋找狀態檔案的位置。當您在本機執行堆疊時，如上所述，您可以將 Terraform 狀態的副本保留在最上層本機目錄中。這稱為*本機後端*。

開發持續整合和持續部署 (CI/CD) 環境時，本機狀態檔案通常包含在 **.gitignore** 檔案中，以防止版本控制。然後，管道中不存在任何本機狀態檔案。為了正常運作，管道階段需要在某個位置找到正確的狀態檔案*。 *這就是 Terraform 組態檔案通常包含後端區塊的原因。後端區塊會向 Terraform 堆疊指出，除了自己的頂層目錄之外，還需要尋找某個位置才能尋找狀態檔案。

Terraform 後端幾乎可以位於任何地方：[Amazon S3 儲存貯](https://developer.hashicorp.com/terraform/language/settings/backends/s3)體、[API 端點，](https://developer.hashicorp.com/terraform/language/settings/backends/http)甚至是[遠端 Terraform 工作區](https://developer.hashicorp.com/terraform/language/settings/backends/remote)。以下是存放在 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.tfstate **檔案包含在 **.gitignore** 檔案中，因此不會推送到遠端儲存庫。然後，CI/CD 管道中的每個環境都會維護自己的後端。在此案例中，多個開發人員可能可以存取此遠端狀態，因此您想要保護狀態檔案的完整性。如果多個部署同時執行並更新狀態，狀態檔案可能會損毀。因此，在具有非本機後端的情況下，狀態檔案通常會在部署期間[鎖定](https://developer.hashicorp.com/terraform/language/state/locking)。