返回文章列表

Terraform 模組互動與最佳實踐

本文探討 Terraform 模組的互動方式,包含變數宣告、輸入、輸出以及模組間的依賴關係,同時提供版本控制、程式碼管理及與 Terraform Registry 互動的最佳實務,以提升 IaC 的效率和可維護性。

DevOps 雲端運算

Terraform 模組化讓基礎設施程式碼更具重複使用性,簡化了複雜佈署的管理。理解模組的輸入、輸出以及變數宣告至關重要,能有效控制資源組態。此外,善用 Terraform Registry 的公共模組,並搭配版本控制,可以確保程式碼的穩定性和可靠性,同時降低維護成本。使用 for_eachcountdepends_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"
}

程式碼解析:

  1. module "lb-vms":定義了一個名為 lb-vms 的模組區塊。
  2. source = "./modules/lb-vms":指定了 lb-vms 模組的來源路徑。
  3. vm_countvm_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
}

內容解密:

  1. source 屬性指定了 VPC 模組的來源,這裡使用的是 Terraform Registry 中的官方 VPC 模組。
  2. namecidr 是傳遞給 VPC 模組的輸入變數,它們的值可以是根模組中的變數、硬編碼的值或是其他資源的屬性。
  3. azsprivate_subnetspublic_subnets 等屬性也是 VPC 模組的輸入變數,用於設定 VPC 的可用區和子網路。
  4. enable_nat_gatewayenable_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"
}

內容解密:

  1. variable 關鍵字後面的標籤是變數的名稱,必須在同一模組中唯一。
  2. description 屬性提供了對變數的描述,有助於使用者瞭解變數的用途。
  3. type 屬性指定了變數的型別,可以是簡單型別(如 string)或複雜型別(如 list(int))。
  4. default 屬性指定了變數的預設值,如果呼叫模組時沒有提供該變數的值,則使用預設值。

輸出

輸出值用於將模組中的資源屬性暴露給外部使用。輸出值可以被宣告在根模組或子模組中。

output "vpc_id" {
  description = "VPC 的 ID"
  value       = concat(aws_vpc.this.*.id, [""])[0]
}

內容解密:

  1. output 關鍵字後面的標籤是輸出的名稱,必須是一個有效的識別符號。
  2. description 屬性提供了對輸出的描述,有助於使用者瞭解輸出的內容。
  3. value 屬性指定了輸出的值,可以是任何有效的表示式。

模組之間的依賴關係

Terraform 0.13 版本引入了對 for_eachcountdepends_on 等 meta-arguments 的支援,用於控制模組的建立和依賴關係。

  • for_eachcount 用於建立多個模組例項。
  • depends_on 用於建立模組之間的顯式依賴關係。

重點整理

  • 在 Terraform 中,變數是用於引數化組態的機制。
  • 輸出值用於將模組中的資源屬性暴露給外部使用。
  • Terraform 0.13 版本引入了對 for_eachcountdepends_on 等 meta-arguments 的支援,用於控制模組的建立和依賴關係。

###graph LR; A[Terraform 模組] –> B[變數宣告]; A –> C[輸入]; A –> D[輸出]; A –> E[模組之間的依賴關係];

此圖示說明瞭Terraform模組的主要組成部分,包括變數宣告、輸入、輸出和模組之間的依賴關係。這些元素共同構成了Terraform模組的核心功能,使得使用者能夠靈活地管理和組態基礎設施。

補充資訊

重點摘錄

  • 在模組中宣告的變數可以用作該模組的輸入。
  • 資源屬性只有在作為輸出暴露時,才能被呼叫模組存取。
  • 輸入和輸出可以是簡單或複雜型別。

與 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
}

內容解密:

  1. variable "naming_prefix"區塊:定義了一個名為 naming_prefix 的輸入變數,用於設定資源命名的字首。
  2. module "virtual_machine_set"區塊:呼叫了 virtual_machine_set 子模組,並傳遞了必要的引數,如 namenum_vms
  3. 傳遞 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
}

內容解密:

  1. module "nsgs-Core"區塊:呼叫了 nsgs-Core 子模組來建立網路安全群組。
  2. CoreProduction-NSG-Name引數:從 vnets-Core 子模組的輸出值中取得 CoreProduction-NSG-Name,並將其傳遞給 nsgs-Core 子模組。
  3. 跨模組資訊分享:透過輸出值和輸入變數的結合,實作了不同子模組之間的資訊分享。

使用公共模組登入檔

Terraform 提供了一個公共模組登入檔(Terraform Registry),包含了許多由主要雲端服務提供商維護的官方模組。這些模組是開源的,程式碼可在 GitHub 上檢視。

使用公共模組的最佳實踐

  1. 指定版本號:在使用公共模組時,建議指定明確的版本號,以避免未經測試的變更影響現有基礎設施。
module "vpc" {
  source = "terraform-aws-modules/vpc/aws"
  version = "2.20.0"
}

內容解密:

  1. source屬性:指定了公共模組的來源路徑。
  2. 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(含)之間的版本

特定運算元的實務應用價值

~> 運算元在保持相同主要版本的前提下,允許引入次要版本的更新,是非常實用的選擇。

版本約束的有效條件

版本約束僅在模組具有可用版本號的情況下生效。本地定義的模組並無版本號的概念,因此版本約束僅適用於從模組登入檔中取得的模組。

重點回顧與實務建議

  1. 明確指定模組版本:在使用模組登入檔時,建議明確指定特定版本的子模組,以避免非預期的更新。
  2. 善用版本約束運算元:根據實際需求選擇適當的版本約束運算元,以實作靈活且穩定的版本控制。

補充資源

瀏覽 Terraform 工作流程的核心技術

描述 Terraform 工作流程(寫入 -> 計畫 -> 建立)

Terraform 的核心工作流程包含三個主要步驟:

  1. 寫入(Write):以程式碼形式撰寫基礎設施組態
  2. 計畫(Plan):預覽即將進行的變更
  3. 套用(Apply):提供可重複使用的基礎設施

寫入階段的技術實踐

撰寫 Terraform 組態檔案通常在整合開發環境(IDE)或進階文字編輯器中進行。這些工具提供語法檢查、原始碼控制整合等功能,甚至提供建立常見 Terraform 結構的捷徑。

Terraform 組態檔案主要採用 HashiCorp Configuration Language(HCL)或 JSON 格式撰寫,其中 HCL 更為常見,因為它更易於人類讀寫。

最佳實踐:原始碼管理

將 Terraform 組態檔案納入原始碼管理(SCM)系統是最佳實踐之一,這有助於追蹤變更、備份程式碼以及進行版本控制,以便在出現問題時回復變更。

重點回顧與實務建議

  1. 採用結構化的工作流程:遵循寫入、計畫、套用的工作流程,能夠確保基礎設施佈署的一致性和可預測性。
  2. 善用開發工具:利用 IDE 或進階文字編輯器的功能,提高 Terraform 組態檔案的撰寫效率和品質。

在下一章中,我們將探討如何導覽 Terraform 工作流程,包括刪除佈署等關鍵步驟。