全部產品
Search
文件中心

Terraform:五分鐘入門阿里雲Terraform OSS Backend

更新時間:Jun 30, 2024

本文將介紹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的互動過程,如下圖所示。backendimg

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是基於阿里雲的Table Store服務(Tablestore)和Object Storage Service服務(OSS)實現的Standard Backend,其中Tablestore用來儲存運行過程中產生的“Locking”,保證State的正確性和完整性;OSS用來儲存最終的State檔案。接下來將詳細介紹OSS Backend。

  • 工作原理

    OSS Backend的工作流程可以分為加鎖、儲存State、釋放鎖三步,下圖是一個簡單的工作流程圖:backendimg

    主要包含以下幾個部分:

    • 運行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

    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 = "<your-ots-instance-name>"
    
      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                    = "cn-hangzhou"
      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中。