本文介紹如何使用Terraform解決存量雲資源管理難題。
背景資訊
- 情境一:長期使用控制台、阿里雲CLI、Resource Orchestration Service服務或者直接調用API建立和管理資源,初次使用Terraform的情境。
- 情境二:長期使用Terraform管理資源,如果通過控制台對單個雲資源做屬性變更,希望保持原有的資源狀態(State)一致的情境。
- 情境三:所有資源都定義在一個模板中,想要對原有模板進行重構拆分,以降低隨著資源不斷增多而帶來的模板和state的管理複雜度的情境。
- 情境四:想要將新版Provider中新增的參數同步到原文檔中的情境。
Terraform基於資源模板定義不僅可以實現對新資源的建立,變更,刪除等操作,還可以通過簡單的命令將那些游離在Terraform管理體系之外的雲資源進行匯入和納管,進而實現對所有雲資源的統一管理。
Terraform 匯入存量資源
- 擷取資源ID:
基於資源ID查詢資源並擷取其屬性。
- 模板聲明所要匯入的資源:
模板驅動,即使是要匯入的資源,也需要在模板中進行聲明。
- 補齊資源模板定義:
匯入成功後,需要根據資源屬性補齊已經在模板中聲明的資源定義。
- 擷取資源ID。
對資源ID的擷取可以通過Web控制台,CLI,API等多種方式,最簡單的方式是通過Terraform的DataSource,輸入簡單的查詢條件,例如擷取一個Server Load Balancer執行個體:
data "alicloud_slbs" "default" { name_regex = "for-demo*" } output "slb_ids" { value = data.alicloud_slbs.default.ids }
運行 terraform apply 命令即可展示所有合格SLB的ID:$ terraform apply data.alicloud_slbs.default: Refreshing state... Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Outputs: slb_ids = [ "lb-gw8vinrqxxxxxxxxxxx", "lb-gw8axostxxxxxxxxxxx", ]
- 模板聲明所要匯入的資源。
和建立資源一樣,在匯入資源前,也需要在模板中進行資源聲明,以便指定所要匯入的資源在State中的存放路徑。如下所示,聲明一個Server Load Balancer執行個體:
resource "alicloud_slb" "this" {}
簡單的聲明之後,無需定義具體的參數即可開始資源的匯入操作。在Terraform中,匯入一個資源的操作通過import命令來完成,完整的命令格式為terraform import <資源類型>.<資源標識> <資源ID>
,詳細操作如下:$ terraform import alicloud_slb.this lb-gw8vinrqxxxxxxxxxxx alicloud_slb.this: Importing from ID "lb-gw8vinrqxxxxxxxxxxx"... alicloud_slb.this: Import prepared! Prepared alicloud_slb for import alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqxxxxxxxxxxx] 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.
- 補齊資源模板定義。
由於模板中沒有完成對所匯入資源的詳細定義,因此,資源匯入成功後,模板內容與State儲存的內容存在差異,此時如果直接運行plan命令,將會看到一個update:
$ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. data.alicloud_slbs.default: Refreshing state... alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqxxxxxxxxxxx] ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # alicloud_slb.this will be updated in-place ~ resource "alicloud_slb" "this" { address = "47.254.181.122" ... ~ delete_protection = "on" -> "off" id = "id=lb-gw8vinrqxxxxxxxxxxx" ... ~ name = "for_demo-test" -> "tf-lb-20191108144235105700000001" ... } Plan: 0 to add, 1 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.
為了保持資源模板與資源狀態的一致,需要在模板中手動補齊缺失的參數定義,直到運行plan不會再有變更資訊為止:resource "alicloud_slb" "this" { delete_protection = "on" name = "for_demo-test" }
所要補齊的內容主要以那些引起更新的欄位為主,補齊完成後運行terraform plan進行測試:$ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. data.alicloud_slbs.default: Refreshing state... alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqtqx1ro1r94c96] ------------------------------------------------------------------------ No changes. Infrastructure is up-to-date. This means that Terraform did not detect any differences between your configuration and real physical resources that exist. As a result, no actions need to be performed.
可以看到,此時已經沒有任何需要變更的資訊。至此完成了對一個資源的完整匯入。
Terraform移除存量資源
在實際操作環境中,經常會遇到資源的誤匯入,匯入路徑不符,想要調整資源路徑,想要持續保留某資源等多種複雜情況。面對這些情況,整體的實現思路也是非常簡單:先將匯入後的資源從State中移除,然後重新匯入。
terraform state rm <資源類型>.<資源標識>
,詳細操作如下:
$ terraform state rm alicloud_slb.this
Removed alicloud_slb.this
Successfully removed 1 resource instance(s).
state rm命令只是將指定的資源從State檔案中移除,並不會將其真正刪除,這也正是為後續的匯入操作做好了鋪墊。
總結
- 情境一的解決方案:
通過terraform import命令來完成對存量資源的匯入,進而使用Terraform統一管理。
- 情境二的解決方案:
在確定清楚參數屬性的具體值之後,如果以模板參數值為準,那麼只需要運行apply命令再變更回來即可;如果以控制台的值為準,那麼只需要補充或修改模板參數值即可。
- 情境三的解決方案:
可以先通過terraform state rm命令將所有需要重組的資源移出State,等模板重構結束後,再使用terraform import將其匯入即可。
- 情境四的解決方案:
和上一解決方案一樣,通過“先移出再匯入”調整即可。
Terraform的命令非常靈活和簡單,基於模板和State一致性的原理,藉助terraform import可以輕鬆地實現對存量資源的統一管理,不用再擔心那些游離在Terraform管理體系之外資源無法管理的痛點,也無需懼怕某個資源從State中移除後無法繼續管理的問題,所有的雲資源都可以被Terraform統一管理起來。