本文提供 Terraform 設定檔的基本樣式和結構建議。這些建議適用於可重複使用的 Terraform 模組和根設定。
本指南並非 Terraform 的介紹。如要瞭解如何搭配使用 Terraform 和 Google Cloud,請參閱「開始使用 Terraform」。
遵循標準模組結構
- Terraform 模組必須遵循標準模組結構。
- 每個模組都會以
main.tf
檔案開頭,這是資源預設的所在位置。 - 在每個模組中,加入 Markdown 格式的
README.md
檔案。在README.md
檔案中,加入模組的基本說明文件。 - 將範例放在
examples/
資料夾中,並為每個範例建立獨立的子目錄。針對每個範例,附上詳細的README.md
檔案。 - 建立資源的邏輯群組,並使用專屬檔案和描述性名稱,例如
network.tf
、instances.tf
或loadbalancer.tf
。- 請勿為每個資源提供專屬檔案。依共用用途將資源分組。例如,在
dns.tf
中結合google_dns_managed_zone
和google_dns_record_set
。
- 請勿為每個資源提供專屬檔案。依共用用途將資源分組。例如,在
- 在模組的根目錄中,只包含 Terraform (
*.tf
) 和存放區中繼資料檔案 (例如README.md
和CHANGELOG.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.id
和some_google_resource.main.id
的差異。
- 您必須額外花費心力,才能記得
如要區分同類型的資源 (例如
primary
和secondary
),請提供有意義的資源名稱。將資源名稱改為單數形式。
在資源名稱中,請勿重複資源類型。例如:
建議做法:
resource "google_compute_global_address" "main" { ... }
不建議使用:
resource "google_compute_global_address" "main_global_address" { … }
謹慎使用變數
- 在
variables.tf
中宣告所有變數。 - 為變數提供與用途或用途相關的描述性名稱:
- 代表數值的輸入內容、區域變數和輸出內容 (例如磁碟大小或 RAM 大小) 必須使用單位 (例如
ram_size_gb
) 命名。 Google Cloud API 沒有標準單位,因此使用單位命名變數,可讓設定維護者清楚瞭解預期的輸入單位。 - 如要使用儲存空間單位,請使用二進位單位前置字元 (1024 的冪次):
kibi
、mebi
、gibi
。如要使用其他測量單位,請使用小數單位前置字元 (1000 的冪次方):kilo
、mega
、giga
。這項用量與 Google Cloud中的用量相符。 - 為了簡化條件式邏輯,請為布林變數提供正面名稱,例如
enable_external_access
。
- 代表數值的輸入內容、區域變數和輸出內容 (例如磁碟大小或 RAM 大小) 必須使用單位 (例如
- 變數必須具備說明。說明會自動納入已發布的模組自動產生文件中。說明可為新開發人員提供描述性名稱無法提供的額外背景資訊。
- 為變數指定定義類型。
- 視情況提供預設值:
- 如果變數具有不受環境影響的值 (例如磁碟大小),請提供預設值。
- 如果變數具有環境專屬值 (例如
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
可重複使用的模組:將可重複使用的模組發布至模組 Registry。
開放原始碼模組:將開放原始碼模組發布至 Terraform Registry。
私人模組:將私人模組發布至私人登錄項。