如何自动导入资源到Terraform状态并实现多资源状态隔离?
问题1:实现两个资源组的状态相互隔离
你当前遇到部署A删B的问题,核心原因是所有操作都在同一个Terraform工作目录下,共用同一个状态文件,Terraform会将新变量对应的资源判定为目标状态,删除旧变量对应的资源。可以通过以下方案解决:
- 方案1:使用Terraform工作区(Workspace)
每个资源组对应独立工作区,不同工作区的状态完全隔离,操作命令如下:# 创建并切换到资源组A的工作区 terraform workspace new rg-a terraform apply -var="source_file=resource_group_a.yml" # 创建并切换到资源组B的工作区 terraform workspace new rg-b terraform apply -var="source_file=resource_group_b.yml" - 方案2:指定独立的状态文件路径
每次apply时通过-state参数指定不同的状态文件存储路径:terraform apply -var="source_file=resource_group_a.yml" -state=rg-a.tfstate terraform apply -var="source_file=resource_group_b.yml" -state=rg-b.tfstate - 方案3:批量部署多套资源(无需分开apply)
直接修改代码读取目录下所有YAML配置,用for_each批量创建资源,所有资源同属一个状态文件,不会互相覆盖:# deploy/main.tf variable "source_dir" { type = string default = "./resource_groups" # 存放所有资源组YAML的目录 } locals { # 读取目录下所有yml文件 rg_files = fileset(var.source_dir, "*.yml") rgs = { for f in local.rg_files : trimsuffix(f, ".yml") => yamldecode(file("${var.source_dir}/${f}")) } } resource "azurerm_resource_group" "rg" { for_each = local.rgs name = each.value.name location = each.value.location }
问题2:运行terraform apply时自动导入已存在的资源
Terraform 1.5及以上版本原生支持import代码块,无需手动执行import命令即可自动导入已存在资源:
- 在代码中添加import块,和你的资源逻辑匹配即可:
import { for_each = local.rgs # 和创建资源的for_each逻辑保持一致 to = azurerm_resource_group.rg[each.key] # 拼接资源的Azure资源ID,替换为你的实际订阅ID id = "/subscriptions/<替换为你的订阅ID>/resourceGroups/${each.value.name}" } - 直接执行
terraform apply,Terraform会自动检查对应资源是否存在,存在则自动导入状态,不存在则新建,不会抛出已存在的报错。
如果你使用的是1.5以下版本的Terraform,可以写shell脚本批量生成并执行import命令,示例:
#!/bin/bash SUBSCRIPTION_ID="替换为你的订阅ID" for yml_file in ./resource_groups/*.yml; do rg_key=$(basename ${yml_file} .yml) rg_name=$(yq '.name' ${yml_file}) terraform import "azurerm_resource_group.rg[\"${rg_key}\"]" "/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${rg_name}" done
内容的提问来源于stack exchange,提问作者Mike Henderson
相关产品推荐
相关产品推荐

