一、Treeaform-state的作用
Terraform-state是指Terroform的狀態,是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 包括多種配置訪問權限的方法,因此你可以以精細化的方式控制狀態文件的訪問權限。
三、配置遠端狀態存儲
- 創建遠端狀態所依賴的資源
首先,將 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 State 的最佳實踐
針對 Terraform 狀態文件,我們從狀態優化和安全性方面給出如下建議:
- 團隊協作場景使用遠端狀態
首先,在團隊協作場景中應使用遠程狀態,以便鎖定和版本控制狀態文件。阿里云的客戶應使用 OSS 作為遠端狀態存儲后端,并使用 OTS 來鎖定狀態文件。將敏感信息與 Terraform 配置文件的版本控制分開,并確保只有構建系統和高權限管理員可以訪問遠程狀態存儲 Bucket。為了防止意外地將開發環境的狀態文件提交到源代碼版本控制系統中(如Github,Gitlab等),請為 Terraform 狀態文件配置 gitignore。 - 不要在狀態中存儲敏感數據
許多資源和數據提供者會將敏感數據以明文形式存儲在狀態文件中,這是存在安全隱患的。如果可能,盡量避免在狀態文件中存儲敏感信息。 - 對狀態進行加密
增加一層防御,始終對遠端狀態文件進行加密。阿里云 OSS 存儲支持 KMS、AES256、SM4 三種加密方式的,客戶可以通過自定義的 KMS 密鑰對狀態文件提供額外一層保護。 - 不要手動修改 Terraform 狀態
狀態文件是維護 Terraform 配置和阿里云基礎設施資源之間的映射關系的關鍵,狀態文件的損壞可能導致重大的基礎設施問題。因此不要嘗試手動修改 Terraform 狀態文件內容。