关于 aztfexport
aztfexport 技能指导将现有 Azure 资源导出为 Terraform 配置和状态,面向从 Azure 基础设施启动 IaC 的用户。内容涵盖单个资源、资源组和 Resource Graph 查询导出,以及验证与常见问题处理。
主要功能
- 01导出单个 Azure 资源
- 02导出整个资源组
- 03按 Resource Graph 查询导出
- 04生成 Terraform 配置与状态
- 05提供验证和故障排查指导
适用场景
- 01将 Azure 资源导入 Terraform
- 02为资源组建立 IaC 配置
- 03按查询筛选资源并导出
- 04检查导出结果并运行 Terraform plan
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ julianobarbosa/ claude-code-skills --skill aztfexport安装后在 Claude Code 中输入/aztfexport确认已加载。
附带文件references/RESOURCE-DISCOVERY.md
详细介绍
aztfexport — 将 Azure 资源导出到 Terraform
概述
aztfexport 是 Microsoft 提供的工具,可将现有 Azure 资源导出为 Terraform HCL 和状态文件。它会对运行中的 Azure 基础设施进行逆向工程,生成 Terraform 配置。适用于仅涉及 Azure 的工作流,或使用 Terraform 1.14 原生 terraform query 功能之前的版本。
适用场景
- 将单个 Azure 资源导出到 Terraform →
aztfexport resource - 导出整个资源组 →
aztfexport resource-group - 导出与 Azure Resource Graph 查询匹配的资源 →
aztfexport query - 根据现有 Azure 基础设施搭建 IaC
以下情况请改用 terraform-search-import 技能: Terraform >= 1.14,使用 terraform query 和批量导入(适用于多云场景,而非 Azure 专用)。
前置条件
- 已安装 aztfexport:
brew install aztfexport(macOS),或参阅 GitHub 发布版本 - 已通过 Azure CLI 完成身份验证:
az login,并选择正确的订阅 - 检查架构(macOS 上尤为重要):
如果不匹配(例如在 arm64 Mac 上使用 x86_64 二进制文件),请重新安装适用于正确架构的版本。file $(which aztfexport) # Check binary arch uname -m # Check system arch
工作流
第 1 步:查找资源 ID
使用 Azure CLI 查找资源 ID。按资源类型查看相关模式,请参阅 references/RESOURCE-DISCOVERY.md。
通用备选方法:
az resource list --query "[?name=='RESOURCE_NAME']" -o table
第 2 步:验证 aztfexport 二进制文件
file $(which aztfexport)
uname -m
aztfexport --version
架构不匹配会导致难以诊断的故障。在新机器上首次使用前,请务必验证架构。
第 3 步:运行 aztfexport
单个资源:
aztfexport resource \
--non-interactive \
--plain-ui \
-o ./terraform-export \
"/subscriptions/SUB_ID/resourceGroups/RG/providers/TYPE/NAME"
资源组:
aztfexport resource-group \
--non-interactive \
--plain-ui \
-o ./terraform-export \
RESOURCE_GROUP_NAME
Azure Resource Graph 查询:
aztfexport query \
--non-interactive \
--plain-ui \
-o ./terraform-export \
"resources | where name == 'MY_RESOURCE'"
第 4 步:检查生成的文件
ls ./terraform-export/
# Expect: main.tf, provider.tf, terraform.tfstate, import.tf (sometimes)
main.tf— 生成的 HCL,资源名称采用res-0这类格式provider.tf— AzureRM Provider 配置terraform.tfstate— 导入的状态文件- 可考虑将
res-0重命名为有描述性的名称(同时更新 HCL 和状态文件)
第 5 步:验证
cd ./terraform-export
terraform init
terraform plan
计划中没有变更,表示导出成功。计算属性可能会出现少量差异;请检查并在适当时使用 lifecycle { ignore_changes } 忽略这些差异。
重要标志
| 标志 | 用途 | 何时需要 |
|---|---|---|
--non-interactive | 跳过交互式提示 | 在 CI/无头环境/Claude 中始终需要 |
--plain-ui | 禁用 TUI(终端界面) | 始终与 --non-interactive 搭配使用——否则在没有 /dev/tty 时会失败 |
-o <dir> | 输出目录 | 始终需要(目录必须为空或不存在) |
--append | 追加到现有 Terraform 目录 | 向现有配置添加内容时(但请参阅下方的注意事项) |
--overwrite | 覆盖现有文件 | 重新导出到同一目录时 |
--hcl-only | 生成 HCL,但不导入状态 | 只需要代码时 |
注意事项与故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
二进制文件无提示崩溃或出现 exec format error | 架构不匹配(在 ARM Mac 上使用 x86) | 运行 file $(which aztfexport) 和 uname -m,然后重新安装适用于正确架构的版本 |
单独使用 --non-interactive 失败 | 无头环境中没有 /dev/tty | 始终与 --plain-ui 搭配使用 |
| 出现 "directory is not empty" 错误 | 输出目录中已有文件 | 使用 -o <fresh-dir> 或 --overwrite |
在没有状态文件的非空目录中使用 --append 失败 | aztfexport 需要已有的 Terraform 状态 | 使用 -o 指定新的子目录 |
| 找不到 Azure 资源 ID | 资源类型未知或 API 错误 | 尝试多个 az 命令——参阅 RESOURCE-DISCOVERY.md |
输出中的资源名称采用 res-0 这类格式 | aztfexport 的默认命名方式 | 导出后同时重命名 HCL 和状态文件中的名称 |
导出后 terraform plan 显示差异 | 计算属性/服务器端属性 | 检查差异——对无害的差异使用 ignore_changes |
示例:导出活动日志警报
# Step 1: Find the resource ID
az monitor activity-log alert list -g myResourceGroup \
--query "[?name=='my-alert'].id" -o tsv
# Step 2: Export
aztfexport resource \
--non-interactive \
--plain-ui \
-o ./alert-export \
"/subscriptions/xxxx/resourceGroups/myRG/providers/Microsoft.Insights/activityLogAlerts/my-alert"
# Step 3: Verify
cd ./alert-export
terraform init
terraform plan
注意事项
- aztfexport 二进制文件与 AzureRM 提供程序的 CGO 绑定架构不匹配——Apple Silicon 需要 ARM64 版本,在 M 系列芯片上运行 x86 二进制文件会悄然降级。
- 资源名称正则表达式默认会排除特殊字符——名称中包含
.的资源(如 FQDN 等)会被悄然跳过。 - 生成的
import块(Terraform 1.5+)与state import命令——aztfexport 现在会写入块;依赖 state-import 调用的旧工作流会失效。 - 默认关闭
--include-role-assignment——RBAC 不会纳入状态,而这通常恰恰是你不想要的。 - 固定提供程序版本:aztfexport 在其导入配置中固定了特定 AzureRM 版本;目标堆栈中的提供程序版本不匹配会导致无关的计划差异。
- 非交互模式(
-n)会跳过名称自定义——如果不检查,自动生成的 TF 名称(如azurerm_storage_account_001)就会永久留在代码中。
评论
支持 Markdown