iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
DevOps

30 天 Terraform 學習筆記:從零開始的 IaC 實戰系列 第 19

Day 19 - Resource Lifecycle 管理:create_before_destroy、prevent_destroy、Ignore changes

  • 分享至 

  • xImage
  •  

昨天我們聊到 Workspace 多環境管理,學會如何讓同一份 Terraform 程式碼安全地部署在 Dev、Test、Prod,並且讓不同環境互不干擾。這對於日常開發是很重要的,但在專案中,還有另一個也是讓人頭痛的問題:當我們修改資源或更新配置時,服務可能會短暫中斷,或者重要資源被意外刪掉。

Terraform 的 Resource Lifecycle 就派上用場了!我們可以透過 lifecycle 區塊,明確控制資源的建立、更新與銷毀順序,讓基礎設施運作更安全,也能強制執行策略,降低人為錯誤的風險~

Terraform Lifecycle Rules

Terraform 的生命週期規則(Life Cycle Rules)是一種 元參數(meta argument),用於在資源管理過程中定義特定的行為和條件。它能幫助我們自動化流程、最小化停機時間、防止意外破壞,並確保配置策略被嚴格執行。

在實務上,最常用的規則包括 create_before_destroyprevent_destroyignore_changesreplace_triggered_by,還有最近新增的前置條件與後置條件。接下來我們就分別來看每個規則的實際作用!

create_before_destroy

想像一下,我們在雲端上有一台 Web 伺服器,然後突然想把機器規格升級。預設情況下,Terraform 會先刪掉舊的 VM,再建立新的 VM。但如果網站正在運行,使用者就會遇到短暫的中斷,這樣等於是大幅減少使用者體驗!

像這種情況,我們就可以使用 create_before_destroy 來解決這個問題。它確保新的資源先被建立,並確認運行正常後,再會刪除舊的資源。

它的配置像以下這樣:

resource "google_compute_instance" "web" {
  name         = "web-instance"
  machine_type = "e2-medium"
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-12"
    }
  }

  network_interface {
    network = "default"
    access_config {}
  }

  lifecycle {
    create_before_destroy = true
  }
}

我們只要透過這個設定,當在修改 machine_type 後,Terraform 會先建立新的 VM,確認新機器正常啟動後,才會刪掉舊 VM。這樣就能達到服務不中斷,用戶甚至感受不到切換過程!

prevent_destroy

在雲端上有些資源比 VM 更為重要,比如資料庫或關鍵儲存。但如果不小心刪掉,後果是不是就非常嚴重!(光想到就覺得毛骨悚然)這時候我們就需要 prevent_destroy

resource "google_sql_database_instance" "primary" {
  name             = "prod-db"
  database_version = "POSTGRES_14"
  region           = var.region

  settings {
    tier = "db-custom-2-7680"
  }

  lifecycle {
    prevent_destroy = true
  }
}

配置啟用後,當遇到有人執行 terraform destroy 或者錯誤操作修改某些欄位,Terraform 都會拒絕刪除並報以下錯誤:

Error: Instance cannot be destroyed
Resource google_sql_database_instance.primary has lifecycle.prevent_destroy set

這就像在重要資源上加了一把鎖,必須先移除設定才能刪除。這個小細節在生產環境中非常重要,能防止「一鍵毀滅」的悲劇!

ignore_changes

有些屬性如果不希望被 Terraform 管理,例如:自動生成的 IP 或由其他系統自動維護的標籤。這時候我們可以用 ignore_changes 告訴 Terraform 忽略這些欄位,避免每次執行 apply 都觸發更新:

resource "google_storage_bucket" "critical_data" {
  name     = "company-critical-backup"
  location = "US"

  lifecycle {
    prevent_destroy = true
    ignore_changes  = [labels]
  }
}

這個配置在實務中是非常常見的。例如在自動化備份系統或標籤策略中,就能避免不必要的變更導致意外操作~

replace_triggered_by

當資源之間有依賴關係時,某個資源變更可能會影響其他資源。replace_triggered_by 可以自動觸發替換相關資源,確保依賴一致性:

resource "azure_rm_storage_account" "example" {
  name                     = "examplestorage"
  resource_group_name      = azure_rm_resource_group.example.name
  location                 = var.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

  lifecycle {
    replace_triggered_by = [azure_rm_resource_group.example.id]
  }
}

當 Resource Group ID 改變時,Storage Account 也會被自動替換,能避免依賴錯亂。

前置條件與後置條件(Custom Conditions)

Terraform 的前置條件(precondition)和後置條件(postcondition)是資源生命週期中的檢查機制,幫助我們在部署前後驗證資源狀態,確保符合策略與需求。

前置條件 precondition

前置條件會在資源建立之前執行,用來檢查輸入參數或環境是否符合預期。例如,我們可以檢查資源位置是否在允許的列表中:

resource "azurerm_resource_group" "example" {
  name     = "example-rg"
  location = var.location

  lifecycle {
    precondition {
      condition     = contains(var.allowed_locations, var.location)
      error_message = "Location '${var.location}' is not allowed. Valid locations: ${join(", ", var.allowed_locations)}"
    }
  }
}

使用前置條件,我們可以在計畫階段就阻止錯誤配置的建立,避免違反組織政策或依賴資源狀態不符合要求。

後置條件 postcondition

後置條件則在資源建立或更新後檢查,驗證資源的實際狀態。例如,確保 VM 已分配公共 IP,或不使用已淘汰的規格:

resource "azurerm_virtual_machine" "example" {
  name                = "example-vm"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

  lifecycle {
    postcondition {
      condition     = self.public_ip_address != null
      error_message = "VM must have a public IP address assigned"
    }
    postcondition {
      condition     = self.vm_size != "Standard_A0"
      error_message = "VM size Standard_A0 is deprecated and not allowed"
    }
  }
}

透過後置條件,我們可以在 apply 階段及時捕捉問題,確保資源符合安全規範或實際運作需求!

💡 小提醒

使用 lifecycle 時要注意以下幾點:

  • create_before_destroy 會讓新舊資源短暫並存,可能增加成本。
  • prevent_destroy 並非永久鎖定,只要移除設定即可刪除資源。
  • 某些資源不支援 create_before_destroy(例如需要唯一名稱的資源)。
  • 執行 Terraform 命令時務必在正確目錄,避免狀態檔錯亂或資源錯誤更新。

總結一下

今天我們看到 Terraform Resource Lifecycle 保護基礎設施、避免意外的重要機制。透過設定 create_before_destroy,我們可以在更新資源時避免服務中斷;利用 prevent_destroy,可以防止關鍵資源被意外刪除;ignore_changes 能幫助我們忽略那些不必要的變更,保持資源穩定;replace_triggered_by 則確保了依賴資源之間的一致性;而前置條件與後置條件(precondition / postcondition)則可以在資源建立前後進行檢查,確保資源狀態符合預期。這些規則雖然看起來只是小細節,但在生產環境中往往能一命,也能讓 Terraform 專案更安全、更可控!


上一篇
Day 18 - Terraform Workspaces 多環境管理
下一篇
Day 20 - Terraform 迴圈與條件邏輯:for_each、count、條件表達式
系列文
30 天 Terraform 學習筆記:從零開始的 IaC 實戰20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言