存量资源管理
本文介绍如何使用 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 命令,详细可参考官网使用说明
示例
下面展示如何导入一个对象存储实例:
创建一个工作目录,并在目录下创建名为 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 导入一个对象存储实例:
创建一个工作目录,并在目录下创建名为 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"
反馈建议
如果您在使用教程或实践过程中有任何问题或建议,可以加入客户钉钉群(钉钉群号:34240022836)与我们的工程师在线交流,也可以直接在阿里云Terraform Provider Github中提交Issue,将有专人跟进您的问题和建议。
