本文介紹如何使用 Terraform 及其配套工具解決存量雲資源管理的難題。
背景介紹
Terraform作為IaC領域的重要工具,已經成為自動化管理雲上資源的重要手段。對於新增的資源,直接編寫Terraform代碼並執行命令即可完成資源的自動化建立;對於存量的資源或者非Terraform建立的資源,需要藉助一種資源匯入的機制,產生資原始碼和狀態檔案,進而通過Terraform來持續管理。
Terraform基於資原始碼定義實現了資源建立、變更、刪除等操作,藉助資源匯入能力,可以將那些游離在Terraform管理體系之外的雲資源進行統一納管。
使用情境
資源匯入機制在資源管理和部署的很多情境都能得到很好的應用。
管理存量資源:將非Terraform(如控制台、API、CLI或者其他管理工具)管理的資源快速切換為Terraform的管理方式
解決資源漂移:使用Terraform管理的資源,當出現資源漂移問題(通過非Terraform的方式修改了資源,導致資源狀態發生了變化)時,可以通過重新匯入來修複
代碼重構:所有資源都定義在一個模板中,想要對原有模板進行重構拆分,以降低隨著資源不斷增多而帶來的模板和state的管理複雜度
快速部署:將現有資源部署架構在不同地區或者不同帳號下進行快速複製和部署
快速恢複:定期備份現有資源架構,當現有資源架構出現穩定性問題時,可以基於備份代碼實現快速恢複
操作步驟
本文提供了三種不同的資源匯入的方式:
Import 命令:通過Terraform原生的命令
terraform import實現單個資源的快速匯入。Import 代碼:編寫Terraform import 代碼並執行
terraform plan和terraform apply實現單個或者多個資源的快速匯入。Terraformer工具:通過執行開源工具Terraformer命令批量過濾和查詢資源,並實現自動匯入
以上三種方式在不同的使用情境中各有不同,您可根據自身情境需要進行選擇。
匯入方式 | 優勢 | 不足 | 適用情境 |
Import 命令 |
|
| 管理存量資源 解決資源漂移 代碼重構 |
Import 代碼 |
|
| 管理存量資源 解決資源漂移 代碼重構 快速部署 |
Terraformer |
|
| 管理存量資源 解決資源漂移 代碼重構 快速部署 快速恢複 |
Terraform Import命令
terraform import命令通過指定資源地址和資源 ID 實現匯入,同時還支援了若干配置參數。
環境準備
準備 Terraform 運行環境。您可以選擇以下任一方式來使用
Cloud Shell:阿里雲Cloud Shell中預裝了Terraform的組件,並已配置好身份憑證,您可直接在Cloud Shell中運行Terraform的命令。適用於低成本、快速、便捷地訪問和使用Terraform的情境。
在本地安裝和配置Terraform:適用於網路連接較差或需要自訂開發環境的情境。
需要為當前帳號授予相關資源的唯讀許可權
用法
命令格式為terraform import [配置參數] <資源地址> <資源ID>
資源地址:格式為
<資源類型>.<資源名稱>包含資源類型和名稱,為基礎設施在狀態檔案中的標識。例如以下模板片段中的 VPC 的資源地址為
alicloud_vpc.default
resource "alicloud_vpc" "default" { vpc_name = "tf-example" cidr_block = "10.0.0.0/8" }資源ID:資源 ID 為請求服務端資訊的入參,可以定位到一個唯一的資源。資源 ID 的格式可以參考每個資源的 Provider 文檔,擷取詳細資料。
例如資源
alicloud_security_group,其資源 ID 為安全性群組 ID;而安全性群組規則alicloud_security_group_rule的資源 ID 則遵循特定格式。

配置參數:terraform 還提供了很多配置參數用於 import 命令,詳細可參考官網使用說明
樣本
下面展示如何匯入一個Object Storage Service執行個體:
建立一個工作目錄,並在目錄下建立名為 main.tf 的設定檔,在其中定義將要匯入的資源地址
resource "alicloud_oss_bucket" "default"{ }確定資源 ID,通過 alicloud_oss_bucket 得到其 ID 為 bucket 名稱
初始化運行環境
terraform init執行 import 匯入命令
# 此處替換為自己的 bucket 名稱 terraform import alicloud_oss_bucket.default oss-bucket-import返回以下資訊即為匯入成功:
alicloud_oss_bucket.default: Importing from ID "oss-bucket-import"... alicloud_oss_bucket.default: Import prepared! Prepared alicloud_oss_bucket for import alicloud_oss_bucket.default: Refreshing state... [id=oss-bucket-import] 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.terraform import 匯入後,屬性不會自動填滿到模板中,還需要手工補齊,執行
terraform show可以查看當前資源的所有屬性:# alicloud_oss_bucket.default: resource "alicloud_oss_bucket" "default" { acl = "private" bucket = "oss-bucket-import" creation_date = "2024-11-22" extranet_endpoint = "oss-cn-beijing.aliyuncs.com" id = "oss-bucket-import" intranet_endpoint = "oss-cn-beijing-internal.aliyuncs.com" location = "oss-cn-beijing" owner = "1511928*****" redundancy_type = "ZRS" resource_group_id = "rg-acf***" storage_class = "Standard" tags = {} access_monitor { status = "Disabled" } }將以上資訊補充到您的模板中,再根據 alicloud_oss_bucket中的資訊,去掉唯讀屬性,就可以通過 Terraform 來進行資源的管理了。
Terraform Import代碼
Terraform 從 V1.5.0 版本起支援了使用 import block 的方式進行匯入。您可以在模板中編寫 import block,規定要匯入的資源 ID 和資源地址,通過 terraform plan 和 terraform apply命令可對匯入結果進行預覽和執行。
官方文檔參考:https://developer.hashicorp.com/terraform/language/import
環境準備
準備 Terraform 運行環境。您可以選擇以下任一方式來使用
說明當前命令要求 Terraform 版本在 v1.5.0 以上,在環境配置時請注意切換到可用版本。
Cloud Shell:阿里雲Cloud Shell中預裝了Terraform的組件,並已配置好身份憑證,您可直接在Cloud Shell中運行Terraform的命令。適用於低成本、快速、便捷地訪問和使用Terraform的情境。
在本地安裝和配置Terraform:適用於網路連接較差或需要自訂開發環境的情境。
需要為當前帳號授予相關資源的唯讀許可權
用法
其文法格式為:
import {
to = alicloud_oss_bucket.example
id = "oss-bucket-import"
}
# 可選
# resource "alicloud_oss_bucket" "example" {
# # (other resource arguments...)
# }相較於 import 命令,import block 有如下兩個優勢:
自動產生模板檔案。您可以將資源匯入一個在模板中已定義好的資源地址中,也可以使用參數
-generate-config-out自動產生,省去了模板填充的成本。大量匯入。在 import 塊中可以通過
for_each實現批量資源的匯入,在資源屬性一致的情況下,可以將其匯入到同一個資源地址中進行管理,通過下標加以區分。
需要注意的是,以上兩個特性不能同時使用。Terraform CLI 暫不支援對使用了for_each的資源自動產生模板。
樣本
下面展示如何使用 import block 匯入一個Object Storage Service執行個體:
建立一個工作目錄,並在目錄下建立名為 main.tf 的設定檔,編寫 import block 確定要匯入的資源 ID 和地址
import { to = alicloud_oss_bucket.default id = "oss-bucket-import" }初始化運行環境
terraform init執行
terraform plan命令,預覽將要匯入的資源模板,使用-generate-config-out參數自動產生模板terraform plan -generate-config-out=generated.tf執行後將展示以下資訊:
alicloud_oss_bucket.default: Preparing import... [id=oss-bucket-import] alicloud_oss_bucket.default: Refreshing state... [id=oss-bucket-import] Terraform will perform the following actions: # alicloud_oss_bucket.default will be imported # (config will be generated) resource "alicloud_oss_bucket" "default" { acl = "private" bucket = "oss-bucket-import" creation_date = "2024-11-22" extranet_endpoint = "oss-cn-beijing.aliyuncs.com" id = "oss-bucket-import" intranet_endpoint = "oss-cn-beijing-internal.aliyuncs.com" location = "oss-cn-beijing" owner = "15119****" redundancy_type = "ZRS" resource_group_id = "rg-acfmzaq*****" storage_class = "Standard" tags = {} access_monitor { status = "Disabled" } } Plan: 1 to import, 0 to add, 0 to change, 0 to destroy. ╷ │ Warning: Config generation is experimental │ │ Generating configuration during import is currently experimental, and the generated configuration │ format may change in future versions. ╵ ───────────────────────────────────────────────────────────────────────────────────────────────────── Terraform has generated configuration and written it to generated.tf. Please review the configuration and edit it as necessary before adding it to version control. Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.確認後,執行
terraform apply命令執行匯入terraform apply根據提示輸入 yes 後返回以下結果即為匯入成功:
...... 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 alicloud_oss_bucket.default: Importing... [id=oss-bucket-import] alicloud_oss_bucket.default: Import complete [id=oss-bucket-import] Apply complete! Resources: 1 imported, 0 added, 0 changed, 0 destroyed.
Terraformer 工具
除 Terraform 原生功能外,還可以使用開源工具 Terraformer,快速、批量地將帳號下的資源匯入為 Terraform 模板。開源 Terraformer 中只對各個雲廠商的部分資源做了支援,各廠商還需進行二次開發,對齊各自 Provider 支援的資源。
Terraformer工具有兩種使用方式:
開源 Terraformer:原生Terraformer,支援對多個雲廠商的資源匯入
阿里雲 Terraformer:基於原生Terraformer增強面向阿里雲匯入工具,只支援對阿里雲資源的匯入。
功能點 | 開源 Terraformer | 阿里雲 Terraformer |
查看支援匯入的產品列表 | ❌ | ✅ |
查看支援匯入的資源類型列表 | ❌ | ✅ |
按Region維度過濾 | ✅ | ✅ |
按Region維度反向過濾(即排除指定的Region) | ❌ | ❌ |
按可用性區域維度過濾 | ❌ | ✅ |
按可用性區域維度反向過濾(即排除指定的可用性區域) | ❌ | ❌ |
按產品維度過濾 | ❌ | ✅ |
按產品維度反向過濾(即排除指定的產品) | ❌ | ✅ |
按資源類型過濾 | ✅ | ✅ |
按資源類型反向過濾(即排除指定的資源類型) | ✅ | ✅ |
按資源ID列表過濾 | ✅ | ✅ |
按資源ID列表反向過濾(即排除指定的資源ID) | ❌ | ❌ |
按資源名稱過濾 | ✅ | ✅ |
按資源群組過濾 | ✅ | ✅ |
按標籤過濾 | ✅ | ✅ |
自動建立資源依賴關係 | ❌ | ✅ |
自動產生變數variables | ❌ | ✅ |
自動產生出參outputs | ❌ | ❌ |
開源 Terraformer
環境準備
下載和安裝
開源 Terraformer 發布包中既包含了針對所有 Provider 的包,又針對每個 Provider 提供了一個單獨的包,您可根據自己的需要進行下載。此處展示了 Linux 以及 Mac 使用者下載的方式,更多方式可參考 Installation。
Linux 使用者
export PROVIDER=all curl -LO "https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-linux-amd64" chmod +x terraformer-${PROVIDER}-linux-amd64 sudo mv terraformer-${PROVIDER}-linux-amd64 /usr/local/bin/terraformermacOS 使用者
export PROVIDER=all curl -LO "https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-darwin-amd64" chmod +x terraformer-${PROVIDER}-darwin-amd64 sudo mv terraformer-${PROVIDER}-darwin-amd64 /usr/local/bin/terraformer依賴條件
需要為當前帳號授予相關資源的唯讀許可權
安裝 Terraform
說明若在 Cloud Shell 中執行可省略這一步。
詳細步驟可參考入門文檔:在本地安裝和配置Terraform。
下載相關的 Provider,可通過以下兩種方式配置:
在運行 Terraformer 命令的目錄下初始化 Provider
將 Provider 下載到~/.terraform.d/plugins/路徑下
配置訪問憑證:目前只支援讀取本地 profile 這一種認證方式,預設會使用第一個憑證進行匯入。配置阿里雲訪問憑證可參考 配置憑證。
用法
以 terraformer-all-darwin-amd64 v0.8.24 版本為例。
共支援了四個命令:help、import、plan、version
help:查看當前命令詳情

version:查看目前的版本

import:提供針對各個 Provider 的匯入功能

plan:提供針對各個 Provider 匯入的預覽功能
樣本
以匯入杭州地區下所有的阿里雲 VPC 為例:
建立一個目錄用來存放匯入後的模板和狀態檔案
mkdir example && cd example執行以下命令
terraformer-all-darwin-arm64 import alicloud --resources=vpc --regions=cn-hangzhou --path-pattern={output} --path-output=./--resources:指定要匯入的資源集合--regions:指定資源所在地區--path-pattern:產生的目錄模式--path-output:目錄檔案路徑
產生的模板檔案如下所示,目錄路徑上會預設加上地區資訊。若需要將所有資源模板壓縮到一個檔案中,可指定
--compact參數,將資源都輸出到resources.tf中└── cn-hangzhou ├── outputs.tf ├── provider.tf ├── terraform.tfstate ├── variables.tf ├── vpc.tf └── vswitch.tf 2 directories, 6 files若您本地的 Terraform 版本
>=0.13.0,您需要執行以下命令來對狀態檔案進行修改以適配新版本 Terraformterraform state replace-provider -auto-approve "registry.terraform.io/-/alicloud" "aliyun/alicloud"
阿里雲 Terraformer - aliterraformer(推薦)
基於開源 Terraformer,我們對更多資源進行了支援。並在訪問憑證的配置、匯入維度功能上進行了增強最佳化。
環境準備
下載和安裝
目前 aliterraformer 儲存在阿里雲的OSS上,可按照如下的地址進行下載:
macOS
# amd64 wget https://terraform-share.oss-cn-hangzhou.aliyuncs.com/aliterraformer/aliterraformer_darwin_amd64.zip # arm64 wget https://terraform-share.oss-cn-hangzhou.aliyuncs.com/aliterraformer/aliterraformer_darwin_arm64.zipLinux
# amd64 wget https://terraform-share.oss-cn-hangzhou.aliyuncs.com/aliterraformer/aliterraformer_linux_amd64.zip # arm wget https://terraform-share.oss-cn-hangzhou.aliyuncs.com/aliterraformer/aliterraformer_linux_arm.zip # arm64 wget https://terraform-share.oss-cn-hangzhou.aliyuncs.com/aliterraformer/aliterraformer_linux_arm64.zipWindows
# amd64 wget https://terraform-share.oss-cn-hangzhou.aliyuncs.com/aliterraformer/aliterraformer_windows_amd64.zip # 386 wget https://terraform-share.oss-cn-hangzhou.aliyuncs.com/aliterraformer/aliterraformer_windows_386.zip以 macOS 系統為例,下載之後,解壓檔案:
unzip aliterraformer_darwin_amd64.zip chmod +x aliterraformer sudo mv aliterraformer /usr/local/bin/aliterraformer依賴條件
與開源 Terraformer 相同,也需要準備 terraform 和 terraform-provider-alicloud 這兩個檔案,並配置存取控制的配置。
為 RAM 帳號授予相關資源的唯讀許可權
安裝 Terraform
詳細步驟可參考入門文檔:在本地安裝和配置Terraform。若在 Cloud Shell 中執行可省略這一步
下載 terraform-provider-alicloud
通過以下方式可設定匯入的 Provider 版本,執行 init 後的緩衝目錄在 v0.13.0 前後的結構不同,此處展示 v0.13.0 版本之後的讀取方式
# 1. 通過環境變數 TF_DATA_TFER_DIR 來設定 <$TF_DATA_TFER_DIR>/providers/registry.terraform.io/aliyun/alicloud/1.239.0/darwin_arm64/terraform-provider-alicloud_v1.239.0 # 2. 設定在當前工作目錄下的隱藏目錄 .terraform/providers/registry.terraform.io/aliyun/alicloud/1.239.0/darwin_arm64/terraform-provider-alicloud_v1.239.0 # 3. 設定在使用者根目錄下的隱藏目錄 <HOME>/.terraform.d/plugins/registry.terraform.io/aliyun/alicloud/1.239.0/darwin_arm64/terraform-provider-alicloud_v1.239.0配置訪問憑證
aliterraformer 在 profile 的基礎上支援了通過環境變數和命令參數的方式設定訪問憑證:
# 1. 通過環境變數 ALICLOUD_ACCESS_KEY 和 ALICLOUD_SECRET_KEY $ export ALICLOUD_ACCESS_KEY=xxxx $ export ALICLOUD_SECRET_KEY=xxxxx # 2. 通過 aliterraformer 命令參數 --access-key 和 --secret-key 傳遞 $ aliterraformer import alicloud --access-key=xxxx --secret-key=xxx ... # 3. 通過 profile 機制來設定AK並傳遞 $ aliterraformer import alicloud --profile=default ...
用法
aliterraformer 目前共支援了五個命令:help,version,products,resources,import。在開源 Terraformer 的基礎上增加了 products、resources 兩個命令
help:查看當前支援的命令詳情
aliterraformer help
version:查看當前的 terraformer 版本
aliterraformer versionproducts:查看目前的版本支援匯入的產品列表
aliterraformer products
resources:查看目前的版本某一產品下支援匯入的資源清單,通過
-p指定aliterraformer resources -p <productName>

import:執行具體的匯入。阿里雲資源需要指定 alicloud,通過以下命令可查看阿里雲資源匯入支援的參數:
aliterraformer import alicloud -h
import 時需要先確定需要匯入的資源集合,再按需通過 filter 對資源進行過濾、通過 output-variables 變數將屬性抽取為參數
構建資源集合:
當前命令提供了四個 flag:<--products>、<--resources>、<--excludes-products>、<--excludes> 來指定要匯入的資源,通過對其進行組合可以便利地構造出資源集合。用法樣本如下:
匯入指定的資源
# 匯入 vpc、vswitch、ECS 執行個體 aliterraformer import alicloud -r=vpc,vswitch,instance匯入指定的產品
# 匯入 ACK、ALB 產品下所有資源 aliterraformer import alicloud --products=ACK,ALB匯入指定的產品及資源
# 匯入 ACK、ECS 產品下所有資源以及所有 vpc、vswitch aliterraformer import alicloud --products=ACK,ECS -r=vpc,vswitch匯入指定的產品,排除產品下部分資源
# 匯入 ACK 下除 alicloud_cs_kubernetes 外所有資源 aliterraformer import alicloud --products=ACK --excludes=cs_kubernetes匯入所有產品下的所有資源
# products 輸入 ALL 代表所有的產品 aliterraformer import alicloud --products=ALL匯入所有產品下所有資源,排除指定的部分產品
# 匯入除 VPNGateway,WAF 外的所有產品 aliterraformer import alicloud --products=ALL --excludes-products=VPNGateway,WAF匯入所有產品下所有資源,排除指定的部分產品及部分資源
# 匯入除 VPNGateway,WAF 外的所有產品,排除 alicloud_cs_kubernetes 資源 aliterraformer import alicloud --products=ALL --excludes-products=VPNGateway,WAF --excludes=cs_kubernetes
通過 filter 對資源進行過濾
此參數的格式為
--filter=Type1.AttrKey=AttrValue1;AttrValue2,Type2.AttrKey=AttrValue1;AttrValue2,Type 若預設,此過濾條件對所有資源生效匯入 vpc id為 vpc-123 的專用網路
# 若指定多個,用分號進行分割:--filter="vpc.id=vpc-123;vpc-456" aliterraformer import alicloud -r=vpc --filter="vpc.id=vpc-123"匯入名稱均為 tf-example 的 VPC 和 vSwitch
aliterraformer import alicloud -r=vpc,vswitch --filter="vpc.vpc_name=tf-example,vswitch.vswitch_name=tf-example"匯入資源群組均為rg-12345的 VPC、ECS 執行個體
aliterraformer import alicloud -r=vpc,instance --filter="resource_group_id=rg-12345"
通過 output-variables 指定將屬性抽取為參數變數
當前命令的格式為
r1:attr1,attr2;r2:attr1,attr2,attr3指定將 ECS 執行個體中 vpc_id、vswitch_id 抽取為變數
aliterraformer import alicloud -r=instance --output-variables="instance:vpc_id,vswitch_id"
樣本
下面展示如何匯入杭州地區下ID為vpc-12345的 VPC、vSwitch 和 ECS 執行個體,並將交換器的 zone_id 抽取為變數:
建立一個目錄用來存放匯入後的模板和狀態檔案
mkdir example && cd example構造匯入命令
aliterraformer import alicloud \ --regions=cn-hangzhou \ -r=vpc,vswitch,instance \ --filter="vpc.id=vpc-12345,vswitch.vpc_id=vpc-12345,instance.vpc_id=vpc-12345" \ --output-variables="vswitch:zone_id" \ --path-output=example \ --path-pattern={output} \ --compact--path-output:指定匯入的檔案夾--path-pattern:匯入資源模板的目錄結構格式,預設格式{output}/{provider}/{service}/,可選格式還有{output}/{provider}/以及{output}/。例如指定--path-pattern={output}代表將所有模板平鋪到一個檔案夾下--compact:不指定時資源將按照{service}.tf分開存放,指定後統一存放到resources.tf下
執行匯入,在 example 目錄產生了如下檔案
. ├── outputs.tf ├── provider.tf ├── resources.tf ├── terraform.tfstate └── variables.tf若不指定
--path-pattern={output},目錄結構如下所示:. └── alicloud ├── instance │ ├── provider.tf │ ├── terraform.tfstate │ └── variables.tf ├── vpc │ ├── outputs.tf │ ├── provider.tf │ ├── terraform.tfstate │ ├── variables.tf │ └── vpc.tf └── vswitch ├── outputs.tf ├── provider.tf ├── terraform.tfstate ├── variables.tf └── vswitch.tf若您本地的 Terraform 版本
>=0.13.0,您需要執行以下命令來對狀態檔案進行修改以適配新版本 Terraformterraform state replace-provider -auto-approve "registry.terraform.io/-/alicloud" "aliyun/alicloud"
反饋建議
如果您在使用教程或實踐過程中有任何問題或建議,可以加入客戶DingTalk群(DingTalk群號:34240022836)與我們的工程師線上交流,也可以直接在阿里雲Terraform Provider Github中提交Issue,將有專人跟進您的問題和建議。