
作者 | 何貴民 阿裡雲開放平台進階開發工程師 主要負責開源生态工具(Terraform,Ansible,Spinnaker)與阿裡雲的內建,專注于借助主流開源工具幫助企業上阿裡雲和雲上運維提效
1 Terraform State簡介
Terraform State 是用來存放基礎設施資源及其屬性和狀态的機制。上篇文章《一分鐘部署阿裡雲ECS叢集》對State做了詳細的闡述,本文将在此基礎上做一點補充。
Terraform State 從存儲形态上分為兩種:
-
local:本地存儲
即資源狀态存放在本地的一個state檔案中,預設為執行目錄下的名為
檔案。此方式也是Terraform預設的存儲形式。terraform.tfstate
-
remote:遠端存儲
即資源狀态存放在遠端的一個服務中,如阿裡雲的OSS,Terraform Cloud,HashiCorp Consul等。遠端存儲帶來的好處是實作了與資源定義模闆管理的解耦,可以讓State脫離本地磁盤而存儲,在提升State安全性的同時,團隊協作可以不再受制于Terraform的執行環境,執行目錄和多人執行時間的限制,提升了管理的靈活性。
Terraform State的存儲是由一個稱之為
Backend
的元件決定的,local state使用的是local backend。除了local backend,其他所有的backend在使用之前都需要在模闆中顯示定義并通過
terraform init
來實作加載和配置。
2 Terraform Backend簡介
Backend
是存儲State的機制,它決定了State資料的加載邏輯和Terraform指令執行之後State的資料的更新過程。如下是Terraform生命周期中與Backend的互動過程。
Terraform 通過
init
指令完成Backend的加載和配置。執行
plan
和
apply
的指令,在加載資源模闆的同時,通過Backend加載State中的存量資料(如果有);指令結束後,将Provider/Provisioner響應中的資料通過Backend更新到State中,最終達到State資料與模闆定義的一緻。
從功能實作級别的角度,Backend可以分為兩種:
-
Standard
即State管理的标準化實作,覆寫标準的功能點“State存儲”和“State加鎖”。這種Backend目前隻适用于在本地系統上運作所有操作的場景,盡管也實作了對State的遠端存儲,但Backend的執行邏輯仍發生在本地并通過直接調用API請求來完成。
目前這種Backend總共有13種,阿裡雲的OSS Backend也屬于此類。
-
Enhanced
可以看作是
的加強版,即Backend的執行邏輯不僅可以發生在本地,還可以通過API或者CLI的方式發生在遠端。目前這種Backend的種類有兩種,一是Standard
,另一個是隻支援Terraform Cloud的local
。remote
阿裡雲也提供了一個标準的Backend -
oss
,在Terraform 0.12.2中予以支援,并在Terraform 0.12.6 和 0.12.8 版本中對
oss
進行了更新,支援
profile
設定,
ecs_role_name
,
assume_role
等鑒權方式。
3 阿裡雲 OSS Backend詳解
OSS Backend 是基于阿裡雲的表格存儲服務(OTS)和對象存儲服務(OSS)實作的Standard Backend,其中OTS用來存儲運作過程中産生的“Locking”,保證State的正确性和完整性;OSS用來存儲最終的State檔案。接下來将詳細介紹OSS Backend。
3.1 工作原理
OSS Backend的工作流程可以分為加鎖,存儲State,釋放鎖三步,下圖是一個簡單的工作流程圖:
主要包含以下幾個部分:
- 運作Terraform指令後,Backend首先會從OTS中擷取LockID,如果已經存在,表明State被損壞或者有人正在操作,傳回報錯;否則,自動生成一個LockID并存儲在OTS中;
- 如果是
指令,初次會生成一個新的state檔案并存儲在OSS的指定目錄下,并釋放LockID;init
-
plan
apply
等涉及到修改State的指令,會在指令結束後将最新的資料同步更新到State檔案中,并釋放LockID;destroy
-
,`` show 等不涉及修改的操作,會直接讀取State内容并傳回。state
3.2 模闆定義
和Provider一樣,Backend在使用時同樣需要在模闆中定義。Backend 通過關鍵字
backend
來聲明:
terraform {
backend "oss" {
profile = "terraform"
bucket = "terraform-oss-backend-1024"
key = "prod/terraform.tfstate"
tablestore_endpoint = "https://tf-oss-backend.cn-hangzhou.ots.aliyuncs.com"
tablestore_table = "terraform-oss-backend-1024"
acl = "private"
encrypt = true
...
}
}
對
backend
的定義包含如下幾個部分:
-
為運作主體,定義了terraform
的操作主體。Backend 的邏輯實作是存放在 Terraform 倉庫中的,服務于所有Provider和Provisioner,是以它的運作主體是Backend
,而不是具體某個Provider;terraform
-
為Backend類型,用來辨別一個特定的Backend;oss
- 大括号裡面的内容為參數配置,用來定義Backend屬性,比如鑒權資訊,OSS Bucket的名稱,存放路徑,OTS配置資訊等。更多參數和含義可參考官方文檔: https://www.terraform.io/docs/backends/types/oss.html
如上代碼聲明了一個
oss
backend,其中state存儲在名為“terraform-oss-backend-1024”的bucket中,對應的檔案為“prod/terraform.tfstate”,并聲明state檔案為隻讀和加密;鎖資訊存儲在一個名為“terraform-oss-backend-1024”的表格中,這個表格位于杭州的OTS執行個體“tf-oss-backend”中。
3.3 一鍵生成OSS Backend模闆
為了更快捷的編寫OSS Backend模闆,阿裡雲提供了一個Terraform Module:remote-backend,可用來自動生成OSS Backend模闆:
module "oss-backend" {
source = "terraform-alicloud-modules/remote-backend/alicloud"
create_backend_bucket = true
create_ots_lock_instance = true
create_ots_lock_table = true
region = "cn-hangzhou"
state_name = "new/terraform.tfstate"
encrypt_state = true
}
運作完成後,會在目前目錄下生成一個名為
terraform.tf
的配置檔案,檔案内容即為已經配置好的OSS Backend:
terraform {
backend "oss" {
bucket = "terraform-remote-backend-94a22ee-0714-e8ef-8573-21df8b021f86"
prefix = "env:"
key = "new/terraform.tfstate"
acl = "private"
region = "cn-hangzhou"
encrypt = "true"
tablestore_endpoint = "https://tf-oss-backend.cn-hangzhou.ots.aliyuncs.com"
tablestore_table = "terraform_remote_backend_lock_table_38001042_0714_e8ef_8573_21df8b021f86"
}
}
生成後的
terraform.tf
可以直接跟目标模闆放在同一個目錄下,以用于對後續State的遠端存儲。
如果想把生成
terraform.tf
的state也存放在上述的OSS Backend中,隻需再次運作
terraform init
指令,本地目錄下的local state将會自動同步到OSS Backend中,如下所示:
總結
OSS Backend遵循Standard Backend的實作邏輯,覆寫“State存儲”和“State加鎖”兩大功能點,保證了State的安全性和體驗的一緻性。借助OSS服務的安全,高可靠和OTS服務的實時通路等特點,為使用者提供了标準的,安全可靠的遠端存儲State的能力。
OSS Backend對Terraform使用者,尤其是阿裡雲Provider的使用者無疑是一大利好,在降低資源管理成本的同時,為團隊協作提供了更多的便利。