過去幾天,我們已經學過 Terraform 的基本元件:resource
、variable
、output
、data source
。
但這些就像是散落一地的零件,雖然能組裝出機器,但每次都要自己拼,會很麻煩。
今天,我們要練習把這些零件「組裝」起來,做出我們的 第一個 Module。
就像是寫程式時不會一直複製貼上,而是把功能包成 function,Terraform 的 module 也有同樣的精神!
🐈🐈🐈
先舉個例子。假設公司要在開發、測試、正式三個環境,各建立 3 台 VM。
如果不用 module,我們就得把一大段 VM 的設定,複製貼上 9 次。不但程式碼很長,未來要改配置還得一個一個找,非常容易出錯。這就是為什麼 module 會登場。它讓我們把 VM 的邏輯抽出來,放到一個獨立的目錄,之後只要呼叫這個 module,再帶入不同的參數,就能快速建立多台 VM。
首先,我們先釐清一個觀念:
Root Module(根模組)
terraform init
和 terraform apply
的工作目錄就是 Root Module.tf
設定檔案(可能叫 main.tf
、variables.tf
,也可能叫別的名字)Sub Module(子模組)
./modules/vm
)、Git 倉庫、或 Terraform Registry做個簡單的比喻:
總監不需要知道水管怎麼接,只要告訴水電工「我要在這裡裝廁所」;水電工也不用管整體設計,專心把廁所裝好就行了。
大概了解為什麼需要 Module 以及 Root Module 與 Sub Module 的差別後,我們就要實際嘗試建立一個 VM 的 module。
我們先新增一個 modules/vm
目錄,裡面放三個檔案:
modules/vm/
├── main.tf
├── variables.tf
└── outputs.tf
這就是一個最小的 module 架構。
在 modules/vm/main.tf
裡面,我們把 VM 的資源定義好:
resource "google_compute_instance" "this" {
name = var.name
machine_type = var.machine_type
zone = var.zone
boot_disk {
initialize_params {
image = var.image
size = var.disk_size
}
}
network_interface {
network = var.network
access_config {}
}
tags = var.tags
}
大家可以看到這裡沒有寫死 VM 名稱、機型、zone,而是透過 var.xxx
從變數帶進來。
在 modules/vm/variables.tf
裡,把需要的變數列出來:
variable "name" {
description = "VM 名稱"
type = string
}
variable "machine_type" {
description = "機器規格"
type = string
default = "e2-micro"
}
variable "zone" {
description = "部署區域"
type = string
default = "asia-east1-b"
}
variable "image" {
description = "作業系統映像檔"
type = string
default = "debian-cloud/debian-11"
}
variable "disk_size" {
description = "開機磁碟大小 (GB)"
type = number
default = 10
}
variable "network" {
description = "VPC 網路名稱"
type = string
default = "default"
}
variable "tags" {
description = "網路標籤"
type = list(string)
default = []
}
這樣我們就能在呼叫 module 的時候,靈活決定 VM 的細節。
在 modules/vm/outputs.tf
裡,定義一些常用的輸出資訊,例如 VM 名稱、內外部 IP:
output "instance_name" {
value = google_compute_instance.this.name
}
output "internal_ip" {
value = google_compute_instance.this.network_interface[0].network_ip
}
output "external_ip" {
value = google_compute_instance.this.network_interface[0].access_config[0].nat_ip
}
最後回到專案根目錄的 main.tf
,我們就能用簡單的方式呼叫這個 module:
module "dev_vm1" {
source = "./modules/vm"
name = "dev-vm-1"
tags = ["development", "web"]
}
module "prod_vm1" {
source = "./modules/vm"
name = "prod-vm-1"
machine_type = "e2-standard-2"
zone = "asia-east1-c"
disk_size = 50
tags = ["production", "web"]
}
output "dev_vm1_info" {
value = {
name = module.dev_vm1.instance_name
external_ip = module.dev_vm1.external_ip
}
}
output "prod_vm1_info" {
value = {
name = module.prod_vm1.instance_name
external_ip = module.prod_vm1.external_ip
}
}
這樣只要呼叫一次,就能建立一台 VM;改變參數,就能快速建立不同規格的 VM。
terraform init
terraform plan
terraform apply
執行完成後,可以用 terraform output
查看剛剛輸出的 VM 名稱與 IP~
登愣!用了 module 之後就不用一直複製貼上重複的設定,還能把資源打包成可重複利用的積木,維護起來更清楚又有效率!
今天我們踏出了*模組化基礎建設的第一步~
outputs
),方便地取得 VM 的名稱與 IP,也不用自己到 Console 一個個找更重要的是!
Module 讓我們的 Terraform 程式碼,從「一次性寫死」升級成「可重複使用的積木」。
未來不管是要建更多 VM,還是要調整參數,只要改 Module 就能影響所有呼叫它的地方,既減少錯誤,又讓架構設計更清晰。
這就是基礎建設自動化真正的好處:一次設計,多次使用,輕鬆擴展。
🐈🐈🐈
明天要了解模組設計的原則與參數管理技巧,讓我們寫的 module 不只是能用,而是好用、耐用且可重複使用!