根模組的最佳做法

本文件提供使用根模組時應考量的規範和建議。

根目錄設定或根模組是指您執行 Terraform CLI 的工作目錄。請確認根層級設定符合下列標準 (以及適用的先前 Terraform 規範)。根模組的明確建議會取代一般規範。

本指南並非 Terraform 的介紹。如要瞭解如何搭配使用 Terraform 和 Google Cloud,請參閱「開始使用 Terraform」。

盡可能減少每個根模組中的資源數量

請務必避免單一根目錄設定過大,因為這樣會在同一個目錄和狀態中儲存過多資源。每次執行 Terraform 時,系統都會重新整理特定根設定中的所有資源。如果單一狀態包含過多資源,可能會導致執行速度變慢。一般規則:請勿在單一狀態中加入超過 100 個資源 (最好只有幾十個)。

為每個應用程式使用不同的目錄

如要個別管理應用程式和專案,請將每個應用程式和專案的資源放入各自的 Terraform 目錄。服務可能代表特定應用程式或共用網路等常見服務。將特定服務的所有 Terraform 程式碼巢狀排列在一個目錄 (包括子目錄) 中。

將應用程式分割為特定環境的子目錄

在 Google Cloud中部署服務時,請將服務的 Terraform 設定分成兩個頂層目錄:包含服務實際設定的 modules 目錄,以及包含各個環境的根目錄的 environments 目錄。

-- SERVICE-DIRECTORY/
   -- OWNERS
   -- modules/
      -- <service-name>/
         -- main.tf
         -- variables.tf
         -- outputs.tf
         -- provider.tf
         -- README
      -- ...other…
   -- environments/
      -- dev/
         -- backend.tf
         -- main.tf

      -- qa/
         -- backend.tf
         -- main.tf

      -- prod/
         -- backend.tf
         -- main.tf

使用環境目錄

如要在各環境中共用程式碼,請參考模組。通常,這可能是服務模組,其中包含服務的基本共用 Terraform 設定。在服務模組中,請將常見的輸入內容設為硬式編碼,並只要求環境專屬的輸入內容做為變數。

每個環境目錄都必須包含下列檔案:

  • backend.tf 檔案,宣告 Terraform 後端狀態位置 (通常是 Cloud Storage)
  • 用來將服務模組例項化的 main.tf 檔案

每個環境目錄 (devqaprod) 都對應至預設的 Terraform 工作區,並將服務的某個版本部署至該環境。這些工作區會將特定環境的資源隔離到各自的上下文中。只使用預設工作區

在環境中建立多個 CLI 工作區並不建議,原因如下:

  • 因此,您可能會很難檢查各個工作區中的設定。
  • 不建議為多個工作區使用單一共用後端,因為如果共用後端用於環境分隔,就會成為單點故障。
  • 雖然可以重複使用程式碼,但如果必須根據目前的工作區變數 (例如 terraform.workspace == "foo" ? this : that) 切換程式碼,程式碼就會變得難以讀取。

如要瞭解詳情,請參考下列資源:

透過遠端狀態公開輸出內容

請務必從根模組公開模組例項的實用輸出內容。

舉例來說,以下程式碼片段會將專案 ID 輸出內容從專案工廠模組例項傳遞至根模組的輸出內容。

# Project root module
terraform {
  backend "gcs" {
    bucket  = "BUCKET"
  }
}

module "project" {
  source  = "terraform-google-modules/project-factory/google"
  ...
}

output "project_id" {
  value       = module.project.project_id
  description = "The ID of the created project"
}

其他 Terraform 環境和應用程式只能參照根模組層級的輸出項目。

您可以使用遠端狀態參照根模組輸出內容。如要允許其他依附應用程式使用設定,請務必將與服務端點相關的資訊匯出至遠端狀態。

# Networks root module
data "terraform_remote_state" "network_project" {
  backend = "gcs"

  config = {
    bucket = "BUCKET"
  }
}

module "vpc" {
  source  = "terraform-google-modules/network/google"
  version = "~> 9.0"

  project_id   = data.terraform_remote_state.network_project.outputs.project_id
  network_name = "vpc-1"
  ...
}

有時,例如從環境目錄叫用共用服務模組時,重新匯出整個子項模組會比較適當,如下所示:

output "service" {
  value       = module.service
  description = "The service module outputs"
}

固定至供應商子版本

在根模組中宣告每個提供者,並將其綁定至次要版本。這樣一來,您就能自動升級至新的修補程式版本,同時維持穩定的目標。為求一致性,請將版本檔案命名為 versions.tf

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 4.0.0"
    }
  }
}

將變數儲存在 tfvars 檔案中

如要提供根模組的變數,請使用 .tfvars 變數檔案。為求一致性,請將變數檔案命名為 terraform.tfvars

請勿使用 var-filesvar='key=val' 指令列選項指定變數。指令列選項是暫時性的,很容易忘記。使用預設變數檔案可提高可預測性。

檢查 .terraform.lock.hcl 檔案

對於根模組,應將 .terraform.lock.hcl 依附元件鎖定檔案簽入來源控制項。這可讓您追蹤及查看特定設定的供應者選項變更。

後續步驟