一般樣式和結構的最佳做法

本文提供 Terraform 設定檔的基本樣式和結構建議。這些建議適用於可重複使用的 Terraform 模組和根設定。

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

遵循標準模組結構

  • Terraform 模組必須遵循標準模組結構
  • 每個模組都會以 main.tf 檔案開頭,這是資源預設的所在位置。
  • 在每個模組中,加入 Markdown 格式的 README.md 檔案。在 README.md 檔案中,加入模組的基本說明文件。
  • 將範例放在 examples/ 資料夾中,並為每個範例建立獨立的子目錄。針對每個範例,附上詳細的 README.md 檔案。
  • 建立資源的邏輯群組,並使用專屬檔案和描述性名稱,例如 network.tfinstances.tfloadbalancer.tf
    • 請勿為每個資源提供專屬檔案。依共用用途將資源分組。例如,在 dns.tf 中結合 google_dns_managed_zonegoogle_dns_record_set
  • 在模組的根目錄中,只包含 Terraform (*.tf) 和存放區中繼資料檔案 (例如 README.mdCHANGELOG.md)。
  • 將任何其他文件放在 docs/ 子目錄中。

採用命名慣例

  • 請使用底線將多個字詞分隔開來命名所有設定物件。這麼做可確保資源類型、資料來源類型和其他預先定義值的命名慣例一致。這項慣例不適用於名稱引數

    建議做法:

    resource "google_compute_instance" "web_server" {
      name = "web-server"
    }
    

    不建議使用:

    resource "google_compute_instance" "web-server" {
      name = "web-server"
    }
    
  • 如要簡化對該類型中唯一資源的參照 (例如,整個模組的單一負載平衡器),請將資源命名為 main

    • 您必須額外花費心力,才能記得 some_google_resource.my_special_resource.idsome_google_resource.main.id 的差異。
  • 如要區分同類型的資源 (例如 primarysecondary),請提供有意義的資源名稱。

  • 將資源名稱改為單數形式。

  • 在資源名稱中,請勿重複資源類型。例如:

    建議做法:

    resource "google_compute_global_address" "main" { ... }
    

    不建議使用:

    resource "google_compute_global_address" "main_global_address" { … }
    

謹慎使用變數

  • variables.tf 中宣告所有變數。
  • 為變數提供與用途或用途相關的描述性名稱:
    • 代表數值的輸入內容、區域變數和輸出內容 (例如磁碟大小或 RAM 大小) 必須使用單位 (例如 ram_size_gb) 命名。 Google Cloud API 沒有標準單位,因此使用單位命名變數,可讓設定維護者清楚瞭解預期的輸入單位。
    • 如要使用儲存空間單位,請使用二進位單位前置字元 (1024 的冪次):kibimebigibi。如要使用其他測量單位,請使用小數單位前置字元 (1000 的冪次方):kilomegagiga。這項用量與 Google Cloud中的用量相符。
    • 為了簡化條件式邏輯,請為布林變數提供正面名稱,例如 enable_external_access
  • 變數必須具備說明。說明會自動納入已發布的模組自動產生文件中。說明可為新開發人員提供描述性名稱無法提供的額外背景資訊。
  • 為變數指定定義類型。
  • 視情況提供預設值:
    • 如果變數具有不受環境影響的值 (例如磁碟大小),請提供預設值。
    • 如果變數具有環境專屬值 (例如 project_id),請勿提供預設值。如此一來,呼叫模組就必須提供有意義的值。
  • 只有在變數為空白時,且底層 API 不會拒絕的情況下,才應使用空白預設值。
  • 請謹慎使用變數。請只為每個執行個體或環境必須不同的值設定參數。決定是否要公開變數時,請務必確保有具體的用途來變更該變數。如果變數的使用機率偏低,請不要公開該變數。
    • 新增含有預設值的變數可向下相容。
    • 移除變數不具回溯相容性。
    • 如果文字常值在多個位置重複使用,您可以使用本機值,而無須將其當做變數公開。

公開輸出

  • 將所有輸出內容整理到 outputs.tf 檔案中。
  • 為所有輸出內容提供有意義的說明。
  • README.md 檔案中記錄輸出說明。使用 terraform-docs 等工具,在提交時自動產生說明。
  • 輸出根模組可能需要參照或分享的所有實用值。特別是針對開放原始碼或使用頻繁的模組,請公開所有可能會被使用到的輸出內容。
  • 請勿直接透過輸入變數傳遞輸出內容,因為這樣做會導致輸出內容無法正確加入依附元件圖表。為確保系統建立隱含的依附元件,請確認輸出內容會參照資源中的屬性。請不要直接參照執行個體的輸入變數,而是如以下所示傳遞屬性:

    建議做法:

    output "name" {
      description = "Name of instance"
      value       = google_compute_instance.main.name
    }
    

    不建議使用:

    output "name" {
      description = "Name of instance"
      value       = var.name
    }
    

使用資料來源

  • 資料來源放在參照這些資料來源的資源旁邊。舉例來說,如果您要擷取用於啟動執行個體的映像檔,請將該映像檔與執行個體一併放置,而不要在各自的檔案中收集資料資源。
  • 如果資料來源數量變多,請考慮將資料來源移至專屬的 data.tf 檔案。
  • 如要擷取與目前環境相關的資料,請使用變數或資源插補

限制自訂指令碼的使用

  • 請只在必要時使用指令碼。Terraform 不會計算或管理透過指令碼建立的資源狀態。
    • 盡量避免使用自訂指令碼。只有在 Terraform 資源不支援所需行為時,才使用這些指令。
    • 使用任何自訂指令碼時,都必須明確記錄其存在的原因,並盡可能提供淘汰計畫。
  • Terraform 可以透過佈建工具 (包括 local-exec 佈建工具) 呼叫自訂指令碼。
  • 將 Terraform 呼叫的自訂指令碼放在 scripts/ 目錄中。

在獨立目錄中加入輔助指令碼

  • helpers/ 目錄中整理未由 Terraform 呼叫的輔助指令碼。
  • README.md 檔案中記錄輔助指令碼,並附上說明和叫用範例。
  • 如果輔助指令碼接受引數,請提供引數檢查和 --help 輸出內容。

將靜態檔案放在獨立目錄中

  • Terraform 參照但不會執行的靜態檔案 (例如載入至 Compute Engine 執行個體的啟動指令碼) 必須整理至 files/ 目錄。
  • 將長篇幅的 HereDocs 放在外部檔案中,與 HCL 分開。使用 file() 函式參照這些項目。
  • 如果是使用 Terraform templatefile 函式讀取的檔案,請使用檔案副檔名 .tftpl
    • 範本必須放在 templates/ 目錄中。

保護有狀態資源

對於有狀態的資源 (例如資料庫),請務必啟用防刪除功能。例如:

resource "google_sql_database_instance" "main" {
  name = "primary-instance"
  settings {
    tier = "D0"
  }

  lifecycle {
    prevent_destroy = true
  }
}

使用內建格式設定

所有 Terraform 檔案都必須符合 terraform fmt 的標準。

限制運算式的複雜度

  • 限制任何個別內插運算式的複雜度。如果單一運算式需要許多函式,建議您使用本機值,將其分割成多個運算式。
  • 請勿在單一行中使用超過一個三元運算。請改用多個本機值來建立邏輯。

使用 count 處理條件式值

如要依條件將資源例項化,請使用 count 元資料引數。例如:

variable "readers" {
  description = "..."
  type        = list
  default     = []
}

resource "resource_type" "reference_name" {
  // Do not create this resource if the list of readers is empty.
  count = length(var.readers) == 0 ? 0 : 1
  ...
}

請謹慎使用使用者指定的變數,設定資源的 count 變數。如果為這類變數 (例如 project_id) 提供資源屬性,但該資源尚不存在,Terraform 就無法產生計畫。而是回報 value of count cannot be computed 錯誤。在這種情況下,請使用個別的 enable_x 變數來計算條件邏輯。

使用 for_each 處理重複的資源

如果您想根據輸入資源建立多個資源副本,請使用 for_each 元參數。

將模組發布至 Registry

後續步驟