我想 rename 怎麼辦?state mv 乾坤大挪移
課程內容與代碼會放在 Github 上: https://github.com/chechiachang/terraform-30-days
賽後文章會整理放到個人的部落格上 http://chechia.net/
這邊用範例講解,同時注意三個部分的差異程度
terraform 是協助工程師管理上述三組 state,達到狀態統一
terraform state 變更 (ex. mv 等) 只管理 terraform state 這一部分,.tf resource 與 remote resource 是維持原狀的
state 變更會在三組 state 中產生分歧,這些分歧會產生額外的效果,這是我們在 state manipulation 時須要格外注意的
https://www.terraform.io/docs/cli/commands/state/mv.html
一樣回到 azure/foundation/compute_network
的範例
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
例如:我們因為業務需求變更,希望 rename module.network
的 module name,從 module.network 變成 module.private-network
git diff
# https://github.com/Azure/terraform-azurerm-network
-module "network" {
+module "private-network" {
source = "Azure/network/azurerm"
resource_group_name = var.resource_group_name
(END)
改完之後,回到 azure/foundation/compute_network
,進行 terraform plan,請問會看到什麼變化?這邊大家依據過去所學,預測一下 terraform 的行為
這邊給幾個提示
cd azure/foundation/compute_network
terragtunt plan
╷
│ Error: Module not installed
│
│ on compute_network.tf line 2:
│ 2: module "private-network" {
│
│ This module is not yet installed. Run "terraform init" to install all
│ modules required by this configuration.
╵
ERRO[0015] 1 error occurred:
* exit status 1
跳出 module not installed 的錯誤,於是這邊我們進行 initA
terragrunt init
Initializing modules...
Downloading Azure/network/azurerm 3.5.0 for priavte-network...
- priavte-network in .terraform/modules/private-network
Initializing the backend...
Initializing provider plugins...
於是在進行 plan
terragrunt plan
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
- destroy
Terraform will perform the following actions:
# module.network.azurerm_subnet.subnet[0] will be destroyed
}
# module.network.azurerm_subnet.subnet[1] will be destroyed
}
# module.network.azurerm_subnet.subnet[2] will be destroyed
}
# module.network.azurerm_virtual_network.vnet will be destroyed
}
# module.private-network.azurerm_subnet.subnet[0] will be created
}
# module.private-network.azurerm_subnet.subnet[1] will be created
}
# module.private-network.azurerm_subnet.subnet[2] will be created
}
# module.private-network.azurerm_virtual_network.vnet will be created
}
Plan: 4 to add, 0 to change, 4 to destroy.
Changes to Outputs:
~ vnet_id = "/subscriptions/.../resourceGroups/terraform-30-days/providers/Microsoft.Network/virtualNetworks/acctvnet" -> (known after apply)
~ vnet_subnets = [
...
+ (known after apply),
+ (known after apply),
+ (known after apply),
]
plan 的結果,獲得 4 to add, 4 to destroy,terraform 認為要移除遠端已經存在的 network,並重新建立新的
terraform 為何會有這樣的判斷?
完全符合之前討論過 terraform 運作的邏輯
然而這樣符合我們的需求嗎?
實務上,我們盡量避免 rename resource / module,可以避免上述情形時常發生,然而這邊的 state manipulation 就是在講非常情形:我們真的被迫要做 module rename,然而不希望遠端被 destroy + create
在回憶一下三個部分
我們只要能夠 rename state 中的 module.network 變成 state module.private-network
於是我們進行 state mv,嘗試看看
terragrunt state mv --dry-run SOURCE DESTINATION
terragrunt state mv --dry-run module.network.data.azurerm_resource_group.network module.private-network.data.azurerm_resource_group.network
Would move "module.network.data.azurerm_resource_group.network" to "module.private-network.data.azurerm_resource_group.network"
看起來跟我們預想的狀況相符,於是我們為 module 底下所有 resource 進行 state mv
terragrunt state mv module.network.data.azurerm_resource_group.network module.private-network.data.azurerm_resource_group.network
terragrunt state mv "module.network.azurerm_subnet.subnet[0]" "module.private-network.azurerm_subnet.subnet[0]"
terragrunt state mv "module.network.azurerm_subnet.subnet[1]" "module.private-network.azurerm_subnet.subnet[1]"
terragrunt state mv "module.network.azurerm_subnet.subnet[2]" "module.private-network.azurerm_subnet.subnet[2]"
terragrunt state mv module.network.azurerm_virtual_network.vnet module.private-network.azurerm_virtual_network.vnet
由於這個範例剛好 mv 一整個 module,我們也可以
terragrunt state mv module.network module.network-private
檢視 state list 中的最新狀況
terragrunt state list
module.private-network.data.azurerm_resource_group.network
module.private-network.azurerm_subnet.subnet[0]
module.private-network.azurerm_subnet.subnet[1]
module.private-network.azurerm_subnet.subnet[2]
module.private-network.azurerm_virtual_network.vnet
從成功更改 state 這邊開始,會產生多人協作問題
在本地 .tf merge 進去之前,master branch 上 plan,會出現 4 destroy, 4 create,這是為何?
卡在這裡的風險,就是其他同事剛好也在 plan 的話,看到 plan 一定超困惑,不曉得發生什麼事情
如何用 terraform 惹怒同事:改 state 不講
所以 state manipulation PR 需要走特別的開發流程