上篇介紹 state rm,強制 terraform 遺忘已經存在的 state。然而 state rm 後並沒有說明如何修復或 undo,讓 module 留在一個會激怒 team member 的狀態XD
這篇介紹 state rm 的反向操作:terraform import
課程內容與代碼會放在 Github 上: https://github.com/chechiachang/terraform-30-days
賽後文章會整理放到個人的部落格上 http://chechia.net/
import 是在 terraform root command,用來 import 已經存在的 remote resource 到 state。可以看 官方文件 import 中描述
要 import 之前,要先手寫產生 .tf resource
subnet[0]
,要先寫 subnet[0] 的 resource 在 .tf 中subnet[0]
的 resource address,將 remote resource import 近來文件提到 Terraform 目前的 import 實作,只影響 state,不會產生 .tf resource。這是什麼意思?
另一個專案 Google Cloud Platform 推出的 terraformer 有提供直接 import 並產生 .tf 檔案的方法
這邊接續上堂課 state rm 的範例,直接使用 import
上堂課我們卡在這邊
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
module.network.azurerm_subnet.subnet[0]: Creating...
╷
│ Error: A resource with the ID "/subscriptions/6fce7237-7e8e-4053-8e7d-ecf8a7c392ce/resourceGroups/terraform-30-days/providers/Microsoft.Network/virtualNetworks/acctvnet/subnets/dev-1" already exists - to be managed via Terraform this resource needs to be imported into the State. Please see the resource documentation for "azurerm_subnet" for more information.
│
│ with module.network.azurerm_subnet.subnet[0],
│ on .terraform/modules/network/main.tf line 15, in resource "azurerm_subnet" "subnet":
│ 15: resource "azurerm_subnet" "subnet" {
│
╵
ERRO[0129] 1 error occurred:
* exit status 1
剛好這例子中
module.network.azurerm_subnet.subnet[0]
到 terraform registry 中的各個 resource 文件下查詢 import 語法,例如 azurerm_subnet
底下有 import 語法
terraform import azurerm_subnet.exampleSubnet /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/virtualNetworks/myvnet1/subnets/mysubnet1
cd azure/foundation/compute_network
terragrunt import "module.network.azurerm_subnet.subnet[0]" "/subscriptions/6fce7237-7e8e-4053-8e7d-ecf8a7c392ce/resourceGroups/terraform-30-days/providers/Microsoft.Network/virtualNetworks/acctvnet/subnets/dev-1"
module.network.azurerm_subnet.subnet[0]: Importing from ID "/subscriptions/6fce7237-7e8e-4053-8e7d-ecf8a7c392ce/resourceGroups/terraform-30-days/providers/Microsoft.Network/virtualNetworks/acctvnet/subnets/dev-1"...
module.network.azurerm_subnet.subnet[0]: Import prepared!
Prepared azurerm_subnet for import
module.network.azurerm_subnet.subnet[0]: Refreshing state... [id=/subscriptions/6fce7237-7e8e-4053-8e7d-ecf8a7c392ce/resourceGroups/terraform-30-days/providers/Microsoft.Network/virtualNetworks/acctvnet/subnets/dev-1]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
顯示 import 成功
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
terragrunt plan
Changes to Outputs:
~ vnet_subnets = [
- null,
+ "/subscriptions/6fce7237-7e8e-4053-8e7d-ecf8a7c392ce/resourceGroups/terraform-30-days/providers/Microsoft.Network/virtualNetworks/acctvnet/subnets/dev-1",
"/subscriptions/6fce7237-7e8e-4053-8e7d-ecf8a7c392ce/resourceGroups/terraform-30-days/providers/Microsoft.Network/virtualNetworks/acctvnet/subnets/dev-2",
# (1 unchanged element hidden)
]
You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.
plan 顯示剩下唯一有差異的地方是 output 的值,我們進行 apply 來更新這個 output
terragrunt apply
上面我們直接使用 state rm 後的例子來做 import 示範,但實務上會更接近
與前面一樣,更改 state 會有多人協作的問題,這邊操作流程類似。如果團隊在專案途中開始導入 terraform 的話,不妨參考一下這個流程
所以,何時需要 import
一個是團隊成員中有 state rm 狂人,或是有人搞砸弄壞 state 被迫上來修
一個是上面第二個例子,就是逐漸導入 terraform 的過程,如果有既有的 resource,這樣會常常用到 import,請小心操作
另外一個,也算是常見的例子,就是被中斷的 terraform workflow