Terraform State
什么是 Terraform State
Terraform State 是指 Terraform 狀態,是 Terraform 生命周期過程中必不可少的元素。本質上講,Terraform 狀態是你的基礎設施配置的元數據存儲庫,Terraform 把它管理的資源狀態保存在一個狀態文件中。
默認情況下,狀態保存在一個名為 "terraform.tfstate" 的文件中,但也可以遠程存儲,在團隊協作管理基礎設施的場景下,推薦采用遠程存儲。
Terraform 使用狀態來創建執行計劃并更改您的基礎設施。在任何操作之前,Terraform 會執行刷新操作以用基礎設施的實際狀態來更新狀態。Terraform 狀態的主要目的是存儲遠端系統(如云上)中的基礎設施對象和配置文件中聲明的資源實例之間的綁定關系,當 Terraform 通過配置文件創建或者更改了遠端對象時,它會將該遠端對象的標識記錄在與之對應的資源實例中,并保存在狀態文件中,之后,Terraform 可能會根據未來的配置更改更新或刪除該對象。
每個在資源塊中創建的基礎設施資源都是通過其resource_name
在 Terraform 狀態中進行標識的,其對資源的管理流程大致如下:
當第一次通過 terraform apply 應用 Terraform 配置時,會創建基礎設施資源,同時自動生成一個狀態文件,該文件引用資源塊中聲明的名稱
如果一個資源已經在 Terraform 狀態文件中有標識,那么 Terraform 會將配置文件與狀態文件和當前的資源遠端的實際狀態進行比較,并根據比較結果,會生成一個執行計劃
當執行該計劃時,它會更新資源的狀態以匹配配置文件中的定義,如果由于遠端 API 限制無法實現就地更新參數,那么該執行計劃將會先銷毀資源,然后再重新創建新的資源;如果是一個資源銷毀的計劃,將發起資源的銷毀操作
計劃執行成功后,Terraform 狀態文件會更新以反映當前的基礎設施狀態
如果某資源已從當前 Terraform 配置中移除但在狀態文件中仍然存在,Terraform 則會比較配置文件并銷毀不再存在的資源
存儲 Terraform State
Terraform 默認將本地狀態文件保存在當前工作目錄中,擴展名為 .tfstate,因此它們不需要額外的維護。本地狀態文件適用于只有一個開發人員工作的項目,當多個開發人員同時運行 Terraform 并且每臺機器都有對當前基礎設施的理解和配置時,默認的本地狀態文件的配置方式就會變得棘手。
在團隊協作開發場景中使用本地狀態時主要存在以下幾個問題:
本地狀態沒有共享訪問權限
當使用 Terraform 更新你的基礎設施,團隊中的每個成員都需要訪問相同的狀態文件,這意味著這些文件必須存儲在一個共享的位置,比如 ECS 實例特定的位置,而這無形增加了管理成本。
不能鎖定本地狀態文件
如果兩個團隊成員同時運行 Terraform,他們可能會遇到競爭條件,因為多個 Terraform 進程可能同時在更新狀態文件。在這種情況下,可能帶來導致沖突、數據丟失和狀態文件損壞等風險。
本地狀態文件不保密
當信息以明文形式存儲在狀態文件中時,敏感數據將存在被暴露的風險,例如數據庫憑證,SSH 登錄密碼等。
因此,當一個團隊中有多個開發人員通過編寫代碼來管理基礎設施時,我們推薦你應該將狀態文件存儲在一個遠端的中心位置。這樣,當基礎設施發生變化時,Terraform 狀態文件會更新并同步,團隊中的所有人員將始終使用最新的基礎設施狀態。
面對本地狀態存在的問題,當使用遠端狀態存儲時,這些問題將會得到解決:
遠端狀態文件會自動更新
當遠程存儲時,狀態文件會自動更新,即一旦配置了遠程后端,每次運行 plan 或 apply 命令時,Terraform 將自動從遠端加載狀態文件。除此之外,它還會在每次 apply 后自動將狀態文件同步存儲在遠端中,因此不存在手動錯誤的情況。
遠端狀態文件支持狀態鎖定
當執行 Terraform 命令時,可以對遠端狀態文件進行加鎖,這樣如果多個開發人員同時運行 terraform apply,它不會因同時更新而損壞。
遠端狀態文件存儲比本地存儲更安全
OSS Bucket 支持本地傳輸加密和遠端加密功能。此外,OSS Bucket 包括多種配置訪問權限的方法,因此你可以以精細化的方式控制狀態文件的訪問權限。
配置遠端狀態存儲
阿里云基于 OSS Bucket 提供了遠端狀態存儲的能力,同時利用表格存儲 OTS 支持了遠端狀態文件的加鎖能力,因此在配置遠端狀態存儲之前,首先需要準備好用于狀態文件存儲的 OSS Bucket 和 OTS 實例。我們展示如何在云存儲桶中遠程存儲 Terraform 狀態:
創建遠端狀態所依賴的資源
首先,將 alicloud_oss_bucket,alicloud_ots_instance,alicloud_ots_table 資源添加到 Terraform 配置文件中,例如 main.tf,并按照自身的需求對資源進行配置,如設置 Bucket 名稱,OTS 實例名稱,實例規格,表格名稱等。完成配置后,運行 terraform apply 來創建 Bucket 以及其他資源。
配置遠端狀態
接下來,將代碼配置添加到一個名為 backend.tf 的新 Terraform 配置文件中,接著運行 terraform init 來配置你的 Terraform 遠端狀態。此時,Terraform 檢測到本地已經有一個狀態文件,并提示你將其復制到新的 OSS Bucket 中。輸入 yes,terraform init 運行成功后,你的 Terraform 狀態將存儲在 OSS Bucket 中。
為了更便捷的配置遠端存儲,可以使用阿里云提供的用于配置遠端狀態的 Terraform Module。
以下是來自 OSS Bucket 的狀態文件片段:
{
"version": 4,
"terraform_version": "1.7.1",
"serial": 9,
"lineage": "5827f172-fc29-c293-cce7-7932f3537499",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "alicloud_oss_bucket",
"name": "this",
"provider": "provider[\"registry.terraform.io/hashicorp/alicloud\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"access_monitor": [
{
"status": "Disabled"
}
],
"acl": "private",
"bucket": "tf-oss-backend-for-demo",
狀態包括了創建的資源的元數據,例如資源類型、資源名稱和提供商名稱等。
Terraform State 的最佳實踐
針對 Terraform 狀態文件,我們從狀態優化和安全性方面給出如下建議:
團隊協作場景使用遠端狀態
首先,在團隊協作場景中應使用遠程狀態,以便鎖定和版本控制狀態文件。阿里云的客戶應使用 OSS 作為遠端狀態存儲后端,并使用 OTS 來鎖定狀態文件。將敏感信息與 Terraform 配置文件的版本控制分開,并確保只有構建系統和高權限管理員可以訪問遠程狀態存儲 Bucket。為了防止意外地將開發環境的狀態文件提交到源代碼版本控制系統中(如Github,Gitlab等),請為 Terraform 狀態文件配置 gitignore。
不要在狀態中存儲敏感數據
許多資源和數據提供者會將敏感數據以明文形式存儲在狀態文件中,這是存在安全隱患的。如果可能,盡量避免在狀態文件中存儲敏感信息。
對狀態進行加密
增加一層防御,始終對遠端狀態文件進行加密。阿里云 OSS 存儲支持 KMS、AES256、SM4 三種加密方式的,客戶可以通過自定義的 KMS 密鑰對狀態文件提供額外一層保護。
不要手動修改 Terraform 狀態
狀態文件是維護 Terraform 配置和阿里云基礎設施資源之間的映射關系的關鍵,狀態文件的損壞可能導致重大的基礎設施問題。因此不要嘗試手動修改 Terraform 狀態文件內容。