更改 state 有其風險,State manipulation 有賺有賠(?),更改前應詳閱官方文件說明書
課程內容與代碼會放在 Github 上: https://github.com/chechiachang/terraform-30-days
賽後文章會整理放到個人的部落格上 http://chechia.net/
本篇講解進階的 terraform state 操作,請複習基本State 操作與基本 Backend 的相關概念
一般來說,我們可以完全仰賴 provider 自動管理 state,不需要手動干涉 state 內容。此時 state 的 workflow 很單純:針對每個 root module
前面 18 天的課程,我們都是依照上面的流程,讓 terraform 自動管理 state
更改 state 有其風險,State manipulation 有賺有賠(?),更改前應詳閱官方文件說明書
Terraform 官方文件對於 state manipulation 的描述 標記 important note
Important: Modifying state data outside a normal plan or apply can cause Terraform to lose track of managed resources, which might waste money, annoy your colleagues, or even compromise the security of your operations. Make sure to keep backups of your state data when modifying state out-of-band.
重要!在正常 plan / apply 以外的流程更改 state,可能造成 terraform 無法追蹤遠端 resource
在進到更改 state 之前,要來細看 terraform 是如何 address state
以 azure/foundation/compute_network
為例說明。首先回憶一下 .tf 內容
modules/compute_network
https://github.com/Azure/terraform-azurerm-network
的 remote module由於我們已經 apply 過,這邊使用 state list 列出現有的 state
cd azure/foundation/compute_network
terragrunt state list
module.network.data.azurerm_resource_group.network
module.network.azurerm_subnet.subnet[0]
module.network.azurerm_subnet.subnet[1]
module.network.azurerm_subnet.subnet[2]
module.network.azurerm_virtual_network.vnet
我們這個 root module (azure/foundation/compute_network
) 產生五個 resource
module.network.azurerm_subnet.subnet(s)
module.network.azurerm_virtual_network.vnet
module / resource 的命名也很直觀
module.<module-name>.azurerm_virtual_network.<resouce-name>
上面把 state manipulation 說得這麼可怕,那 terraform 都自動把 state 維護好,我們有什麼動機需要手動來更改 state?
實務上比較常見到的例子
rename resource / module 應該是常見的需求,特別是針對開發中的 module,會希望讓 resource 的名稱更直觀
從 resource addressing
如果我們把 module.network.azurerm_virtual_network.vnet
的 azurerm_virtual_network.vnet
rename 成為 azurerm_virtual_network.main
module.network.azurerm_virtual_network.vnet
不見了module.network.azurerm_virtual_network.main
module.network.azurerm_virtual_network.vnet
module.network.azurerm_virtual_network.main
應該要產生- module.network.azurerm_virtual_network.vnet {
}
+ module.network.azurerm_virtual_network.main {
}
1 to create, 1 to delete
這也是 terraform,應該說是 RESTful API 常見的問題
在這種情形下,如果我們希望的是 rename,便可以更改 state
module.network.azurerm_virtual_network.vnet
-> module.network.azurerm_virtual_network.main
module.network.azurerm_virtual_network.main
,state 中也有 module.network.azurerm_virtual_network.main
,兩個是對在一起的state mv 方法很多種,例如:
State manipulation 有其風險有賺有賠(?)工程師應詳閱官方文件公開說明書。
今天我們遇上上面描述的情形,被迫要手動調整 state,然而 state 更改方式許多種,使用 editor 直接 edit 大概是最容易出錯的一種
當使用 local state 進行變更時(ex. apply),本地會有一個版本的 terraform.tfstate.backup 檔案,是 terraform 使用 local state 的時候,一個貼心的小功能。如果
如果 terraform.tfstate 跟 terraform.tfstate.backup 都改壞了,那復原的步驟就會變得非常麻煩,而且一個不小心就會弄壞遠端的 resource。這在 prod 發生的話不是開玩笑的
附帶一提,這時就體現出 state versioning 的優勢,如果使用的 backend 有支援 state versioning,遠端的 backend 上會保留非常多以前 apply 的 state,萬一真的不幸搞壞最近幾個版本,還是可以 checkout 更早版本的 state,協助回朔
然而,版本離越遠,回朔的過程越痛苦。這是一個惹惱同事的好方法 ;)
爛方法沒試過不知道他有多爛
_poc
內使用 local backend 的範例