Terraform 模組化讓基礎設施程式碼更具重複使用性,簡化了複雜佈署的管理。理解模組的輸入、輸出以及變數宣告至關重要,能有效控制資源組態。此外,善用 Terraform Registry 的公共模組,並搭配版本控制,可以確保程式碼的穩定性和可靠性,同時降低維護成本。使用 for_each、count 和 depends_on 等 meta-arguments,更能精細化控制模組的建立與依賴關係,提升整體 IaC 流程的效率。
Terraform 模組互動
Terraform 模組是一種可重複使用的組態單元,能夠定義輸入、資源和輸出。本章節將探討 Terraform 模組的使用方法及其重要性。
模組的基本概念
在 Terraform 中,模組是指一個包含多個 .tf 或 .tf.json 檔案的目錄。當你在一個目錄中建立這些檔案時,就形成了一個模組。主要的組態稱為根模組(root module),它可以呼叫其他模組來建立資源。
模組的層級結構
模組具有層級結構,根模組可以呼叫子模組,而子模組又可以呼叫另一個子模組。例如,根模組呼叫 lb-vms 子模組來建立一個負載平衡的 Azure 虛擬機器叢集,而 lb-vms 子模組可能會呼叫 vnet 子模組來建立必要的虛擬網路和子網。
模組來源選項
要使用一個模組,Terraform 需要知道該模組檔案的存放位置。source 引數定義了模組檔案的來源。這些檔案可以儲存在多個位置,包括:
- 本地路徑
- Terraform Registry
- GitHub
- Bitbucket
- 一般的 Git 和 Mercurial 儲存函式庫
- HTTP URL
- S3 儲存桶
- GCS 儲存桶
Terraform Registry 的重要性
Terraform Registry 提供了一個公共平台,用於存放和分享已驗證的模組。這些模組由第三方供應商維護和驗證,因此具有很高的可靠性。例如,你可以在 Registry 中找到 AWS VPC 或 Azure AKS 叢集的驗證模組。
與模組輸入和輸出的互動
輸入變數
輸入變數作為 Terraform 模組的引數,允許自定義模組的某些方面而不必修改其原始碼。這使得模組能夠被分享和重複使用。
重點整理
- 模組是可重複使用的組態,可以被根模組或其他子模組呼叫。
- 模組的來源可以是本地檔案系統或遠端儲存函式庫,包括 Terraform Registry。
進一步閱讀
若需更多關於 Terraform 模組來源的資訊,請參考 Terraform 檔案。
使用 Terraform CLI 管理模組
在使用 Terraform 時,瞭解如何有效地管理模組是非常重要的。以下是一些與管理模組相關的關鍵操作:
初始化與取得模組
當你執行 terraform init 時,Terraform 會自動將遠端模組的檔案複製到根模組的 .terraform 目錄中。你也可以使用 terraform get 命令來單獨檢索模組,而不進行初始化。
管理多層級模組
對於具有多層級結構的模組,瞭解如何管理和除錯這些資源至關重要。使用 terraform state list 命令,你可以檢視所有資源的地址,包括那些由子模組建立的資源。
範例程式碼:呼叫子模組
module "lb-vms" {
source = "./modules/lb-vms"
# 輸入變數範例
vm_count = 3
vm_size = "Standard_DS2_v2"
}
程式碼解析:
module "lb-vms":定義了一個名為lb-vms的模組區塊。source = "./modules/lb-vms":指定了lb-vms模組的來源路徑。vm_count和vm_size:這些是傳遞給lb-vms模組的輸入變數,用於自定義虛擬機器的數量和大小。
本章節總結了 Terraform 模組的基本概念、來源選項以及如何與其輸入和輸出進行互動。透過有效地使用和管理 Terraform 模組,你可以簡化你的基礎設施即程式碼(IaC)實踐,提高可重複性和可維護性。
與Terraform模組互動
Terraform 模組是 Terraform 組態的基本組成單位,它允許使用者將基礎設施的組態分解為可重複使用的元件。在本章節中,我們將探討如何與 Terraform 模組互動,包括變數的宣告、輸入、輸出以及模組之間的依賴關係。
變數宣告與輸入
在 Terraform 中,變數是用於引數化組態的機制。當你在根模組中宣告變數時,可以使用 CLI 選項和環境變數來設定它們的值。當你在子模組中宣告變數時,呼叫模組應該在模組區塊中傳遞值。
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "${var.prefix}-vpc"
cidr = var.cidr_address
azs = var.vpc_azs
private_subnets = var.vpc_private_subnets
public_subnets = var.vpc_private_subnets
enable_nat_gateway = true
enable_vpn_gateway = true
}
內容解密:
source屬性指定了 VPC 模組的來源,這裡使用的是 Terraform Registry 中的官方 VPC 模組。name和cidr是傳遞給 VPC 模組的輸入變數,它們的值可以是根模組中的變數、硬編碼的值或是其他資源的屬性。azs、private_subnets和public_subnets等屬性也是 VPC 模組的輸入變數,用於設定 VPC 的可用區和子網路。enable_nat_gateway和enable_vpn_gateway用於啟用或停用 NAT閘道和 VPN閘道。
每個子模組的輸入變數都需要在該模組中宣告,使用 variable 區塊。例如,在官方 VPC 模組的 variables.tf 檔案中,你可以看到如下宣告:
variable "name" {
description = "用於所有資源的名稱"
type = string
default = ""
}
variable "cidr" {
description = "VPC 的 CIDR 區塊"
type = string
default = "0.0.0.0/0"
}
內容解密:
variable關鍵字後面的標籤是變數的名稱,必須在同一模組中唯一。description屬性提供了對變數的描述,有助於使用者瞭解變數的用途。type屬性指定了變數的型別,可以是簡單型別(如string)或複雜型別(如list(int))。default屬性指定了變數的預設值,如果呼叫模組時沒有提供該變數的值,則使用預設值。
輸出
輸出值用於將模組中的資源屬性暴露給外部使用。輸出值可以被宣告在根模組或子模組中。
output "vpc_id" {
description = "VPC 的 ID"
value = concat(aws_vpc.this.*.id, [""])[0]
}
內容解密:
output關鍵字後面的標籤是輸出的名稱,必須是一個有效的識別符號。description屬性提供了對輸出的描述,有助於使用者瞭解輸出的內容。value屬性指定了輸出的值,可以是任何有效的表示式。
模組之間的依賴關係
Terraform 0.13 版本引入了對 for_each、count 和 depends_on 等 meta-arguments 的支援,用於控制模組的建立和依賴關係。
for_each和count用於建立多個模組例項。depends_on用於建立模組之間的顯式依賴關係。
重點整理
- 在 Terraform 中,變數是用於引數化組態的機制。
- 輸出值用於將模組中的資源屬性暴露給外部使用。
- Terraform 0.13 版本引入了對
for_each、count和depends_on等 meta-arguments 的支援,用於控制模組的建立和依賴關係。
###graph LR; A[Terraform 模組] –> B[變數宣告]; A –> C[輸入]; A –> D[輸出]; A –> E[模組之間的依賴關係];
此圖示說明瞭Terraform模組的主要組成部分,包括變數宣告、輸入、輸出和模組之間的依賴關係。這些元素共同構成了Terraform模組的核心功能,使得使用者能夠靈活地管理和組態基礎設施。
補充資訊
- https://www.terraform.io/docs/configuration/variables.html
- https://www.terraform.io/docs/configuration/outputs.html
重點摘錄
- 在模組中宣告的變數可以用作該模組的輸入。
- 資源屬性只有在作為輸出暴露時,才能被呼叫模組存取。
- 輸入和輸出可以是簡單或複雜型別。
與 Terraform 模組互動的最佳實踐
Terraform 的模組功能允許使用者將重複使用的基礎設施程式碼模組化,進而提高程式碼的可維護性和重複使用率。在 Terraform 中,每個包含設定檔的目錄都會被視為一個模組,而使用模組則意味著明確地參照這些設定。
模組的基本概念
- 模組的定義:在 Terraform 中,每個目錄自動被視為一個模組。使用
module區塊可以參照其他模組,從而建立資源。 - 輸出值:子模組中的資源需要透過輸出值(output values)來暴露給父模組。
變數和本地值的存取規則
- 本地值(Local Values):定義在模組內的本地值僅在該模組內可見,無法被父模組或其他子模組直接存取,除非透過輸出值暴露。
- 變數(Variables):子模組無法直接存取父模組中定義的變數,必須透過輸入變數(input variables)顯式傳遞。
例項解析
假設有一個根模組呼叫了一個子模組來建立虛擬機器,如下所示:
variable "naming_prefix" {
type = string
description = "用於命名資源的字首"
default = "tfm"
}
module "virtual_machine_set" {
source = "../modules/virtual_machine_set"
name = "vms"
num_vms = 3
}
在這個例子中,子模組 virtual_machine_set 無法直接存取根模組中的 naming_prefix 變數。如果需要在子模組中使用該變數,需要顯式地將其作為輸入變數傳遞:
module "virtual_machine_set" {
source = "../modules/virtual_machine_set"
name = "vms"
num_vms = 3
naming_prefix = var.naming_prefix
}
內容解密:
variable "naming_prefix"區塊:定義了一個名為naming_prefix的輸入變數,用於設定資源命名的字首。module "virtual_machine_set"區塊:呼叫了virtual_machine_set子模組,並傳遞了必要的引數,如name和num_vms。- 傳遞
naming_prefix:需要在呼叫子模組時,將naming_prefix作為輸入變數傳遞給子模組,以使其在子模組中可用。
跨模組分享資訊
- 輸出值的使用:子模組可以透過輸出值將內部資訊暴露給父模組。父模組可以存取這些輸出值,並將其傳遞給其他子模組。
- 例項:假設有一個子模組建立網路安全群組(NSGs),並且需要從另一個子模組(
VNets-Core)取得輸出值。
module "nsgs-Core" {
source = "../../nsgs/core"
ResourceID = var.ResourceID
CostCenter = var.CostCenter
CoreNetworking-ResourceGroup-Name = azurerm_resource_group.CoreNetworking.name
CoreProduction-NSG-Name = module.vnets-Core.CoreProduction-NSG-Name
}
內容解密:
module "nsgs-Core"區塊:呼叫了nsgs-Core子模組來建立網路安全群組。CoreProduction-NSG-Name引數:從vnets-Core子模組的輸出值中取得CoreProduction-NSG-Name,並將其傳遞給nsgs-Core子模組。- 跨模組資訊分享:透過輸出值和輸入變數的結合,實作了不同子模組之間的資訊分享。
使用公共模組登入檔
Terraform 提供了一個公共模組登入檔(Terraform Registry),包含了許多由主要雲端服務提供商維護的官方模組。這些模組是開源的,程式碼可在 GitHub 上檢視。
使用公共模組的最佳實踐
- 指定版本號:在使用公共模組時,建議指定明確的版本號,以避免未經測試的變更影響現有基礎設施。
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.20.0"
}
內容解密:
source屬性:指定了公共模組的來源路徑。version屬性:指定了要使用的模組版本,這樣可以確保基礎設施的一致性和可預測性。
與 Terraform 模組互動的關鍵技術解析
精確定義模組版本的重要性
在使用 Terraform 模組時,明確設定可接受的版本號至關重要,這能夠有效防止因未預期的變更而導致的問題。尤其是在非模組維護者的情況下,這種做法更顯關鍵。
版本設定的具體實踐
在 module 區塊中使用 version 引數即可定義模組的版本號,範例如下:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.20.0"
}
版本約束運算元的多樣選擇
version 引數的值可以是明確的版本號或版本約束運算式。除了簡單的 = 運算元外,還可以使用其他多種運算元來進行版本控制:
>= 2.20.0:使用 2.20.0 或更新版本<= 2.20.0:使用 2.20.0 或更舊版本~> 2.20.0:使用 2.20.x 系列的版本(例如,2.21.x 不符合條件)>= 2.0.0, <= 2.20.0:使用介於 2.0.0 和 2.20.0(含)之間的版本
特定運算元的實務應用價值
~> 運算元在保持相同主要版本的前提下,允許引入次要版本的更新,是非常實用的選擇。
版本約束的有效條件
版本約束僅在模組具有可用版本號的情況下生效。本地定義的模組並無版本號的概念,因此版本約束僅適用於從模組登入檔中取得的模組。
重點回顧與實務建議
- 明確指定模組版本:在使用模組登入檔時,建議明確指定特定版本的子模組,以避免非預期的更新。
- 善用版本約束運算元:根據實際需求選擇適當的版本約束運算元,以實作靈活且穩定的版本控制。
補充資源
瀏覽 Terraform 工作流程的核心技術
描述 Terraform 工作流程(寫入 -> 計畫 -> 建立)
Terraform 的核心工作流程包含三個主要步驟:
- 寫入(Write):以程式碼形式撰寫基礎設施組態
- 計畫(Plan):預覽即將進行的變更
- 套用(Apply):提供可重複使用的基礎設施
寫入階段的技術實踐
撰寫 Terraform 組態檔案通常在整合開發環境(IDE)或進階文字編輯器中進行。這些工具提供語法檢查、原始碼控制整合等功能,甚至提供建立常見 Terraform 結構的捷徑。
Terraform 組態檔案主要採用 HashiCorp Configuration Language(HCL)或 JSON 格式撰寫,其中 HCL 更為常見,因為它更易於人類讀寫。
最佳實踐:原始碼管理
將 Terraform 組態檔案納入原始碼管理(SCM)系統是最佳實踐之一,這有助於追蹤變更、備份程式碼以及進行版本控制,以便在出現問題時回復變更。
重點回顧與實務建議
- 採用結構化的工作流程:遵循寫入、計畫、套用的工作流程,能夠確保基礎設施佈署的一致性和可預測性。
- 善用開發工具:利用 IDE 或進階文字編輯器的功能,提高 Terraform 組態檔案的撰寫效率和品質。
在下一章中,我們將探討如何導覽 Terraform 工作流程,包括刪除佈署等關鍵步驟。