五分鐘入門阿里云Terraform OSS Backend
本文將介紹Terraform的Backend機制及如何使用Terraform OSS Backend。
Terraform State簡介
Terraform State是用來存放基礎設施資源及其屬性和狀態的機制。Terraform State從存儲形態上分為兩種:
local:本地存儲
資源狀態存放在本地的一個state文件中,默認為執行目錄下的名為terraform.tfstate文件。此方式也是Terraform默認的存儲形式。
remote:遠端存儲
資源狀態存放在遠端的一個服務中,例如阿里云的OSS Terraform Cloud,HashiCorp Consul等。遠端存儲帶來的好處是實現了與資源定義模板管理的解耦,可以讓State脫離本地磁盤而存儲,在提升State安全性的同時,團隊協作可以不再受制于Terraform的執行環境、執行目錄和多人執行時間的限制,提升了管理的靈活性。
Terraform State的存儲是由一個稱之為Backend的組件決定的,local state使用的是local backend。除了local backend,其他所有的backend在使用之前都需要在模板中顯式定義并通過terraform init來實現加載和配置。
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
可以看作是Standard的加強版,即Backend的執行邏輯不僅可以發生在本地,還可以通過API或者CLI的方式發生在遠端。目前這種Backend的種類有兩種,一是local,另一個是只支持Terraform Cloud的remote 。
阿里云也提供了一個標準的Backend-oss ,在Terraform 0.12.2中予以支持,并在Terraform 0.12.6 和0.12.8版本中對OSS進行了升級,支持profile設置, ecs_role_name , assume_role等鑒權方式。
阿里云OSS Backend詳解
OSS Backend是基于阿里云的表格存儲服務(Tablestore)和對象存儲服務(OSS)實現的Standard Backend,其中Tablestore用來存儲運行過程中產生的“Locking”,保證State的正確性和完整性;OSS用來存儲最終的State文件。接下來將詳細介紹OSS Backend。
工作原理
OSS Backend的工作流程可以分為加鎖、存儲State、釋放鎖三步,下圖是一個簡單的工作流程圖:
主要包含以下幾個部分:
運行Terraform命令后,Backend首先會從Tablestore中獲取LockID,如果已經存在,表明State被損壞或者有人正在操作,返回報錯,否則,自動生成一個LockID并存儲在Tablestore中。
如果是init命令,初次會生成一個新的state文件并存儲在OSS的特定目錄下,并釋放LockID。
如果是plan、apply、destroy等涉及到修改State的命令,會在命令結束后將最新的數據同步更新到State文件中,并釋放LockID。
如果是 state、show 等不涉及修改的操作,會直接讀取State內容并返回。
模板定義
和Provider和Provisioner一樣,Backend在使用時同樣需要在模板中定義。Backend 通過關鍵字backend來聲明
如下代碼聲明了一個oss backend,其state存儲在名為terraform-oss-backend-1024的bucket中,對應的文件為prod/terraform.tfstate,并聲明state文件為只讀和加密;鎖信息存儲在一個名為terraform-oss-backend-1024的表格中,這個表格位于杭州的Tablestore實例tf-oss-backend中。
terraform { backend "oss" { profile = "terraform" bucket = "terraform-oss-backend-1024" key = "prod/terraform.tfstate" tablestore_endpoint = "https://tf-oss-backend.cn-hangzhou.Tablestore.aliyuncs.com" tablestore_table = "terraform-oss-backend-1024" acl = "private" encrypt = true ... } }
對backend的定義包含如下幾個部分:
terraform為運行主體,定義了Backend的操作主體。Backend的邏輯實現是存放在Terraform倉庫中的,服務于所有Provider和Provisioner,因此它的運行主體是terraform ,而不是具體某個Provider。
oss 為Backend類型,用來標識一個特定的Backend。
大括號里面的內容為參數配置,用來定義Backend屬性,例如鑒權信息,OSS Bucket的名稱,存放路徑,Tablestore配置信息等。更多參數和含義可參考官方文檔:https://www.terraform.io/docs/backends/types/oss.html
一鍵生成OSS Backend模板
為了更快捷的編寫OSS Backend模板,阿里云提供了一個Terraform Module:remote-backend
terraform { required_providers { alicloud = { # 在使用 module 時,我們強烈推薦使用 hashicorp 源。aliyun 源的 provider 無法被 module 繼承,可能會導致部分配置不生效 source = "hashicorp/alicloud" } } } variable "region" { default = "cn-hangzhou" } provider "alicloud" { region = var.region } resource "random_integer" "default" { min = 10000 max = 99999 } module "remote_state" { source = "terraform-alicloud-modules/remote-backend/alicloud" create_backend_bucket = true create_ots_lock_instance = true # 注意,為了避免OTS實例名稱的沖突,此處需要指定自己的OTS Instance名稱 # 如果指定的OTS Instance已經存在,那么需要設置 create_ots_lock_instance = false backend_ots_lock_instance = "ots-i-${random_integer.default.result}" create_ots_lock_table = true # 注意,如果想要自定義OTS Table或者使用已經存在的Table,可以通過參數backend_ots_lock_table來指定 # 如果指定的OTS Table已經存在,那么需要設置 create_ots_lock_table = false # backend_ots_lock_table = "<your-ots-table-name>" region = var.region state_name = "prod/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://<your-ots-instance-name>.cn-hangzhou.Tablestore.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中。