Terraform:将整个资源组移动到新的 Azure 订阅

dme*_*meu 3 infrastructure azure terraform terraform-provider-azure

历史上增长的项目及其在 Azure 上的相关基础设施必须进行拆分。幸运的是,它的结构良好,因此很明显我们需要将两个资源组及其附属资源移动到新的 Azure 订阅。

  • 我已经检查过,大部分资源都可以移动,因此不必重新创建并且可以保留数据。

  • 对于那些无法移动的资源,幸运的是我们正在使用terraform,可以运行它来重新创建这些资源。

  • 需要移动的资源是整个terraform项目,因此不需要从当前配置文件中删除资源。所有这些都需要进行新的订阅。

到目前为止一切顺利,但现在我需要了解如何实际进行,以便 terraform 知道移动的资源。我当前看到的唯一选项是手动移动 Azure 门户上的资源,更改 CLI/for terraform 上的订阅,然后为每个资源运行terraform state rm; terraform import或 a 。terraform mv

难道没有更简单的方法来实现这一目标吗?这似乎过于麻烦,基本上可以更轻松地删除当前订阅中的整个基础设施,并通过新订阅中的 terraform 重新创建它(不是一个选项!)

小智 5

仅通过更改*tf 文件中的参数来将资源从一个资源组移动到另一个资源组是不可能的。resource_group_nameTerraform 1.0.2 将尝试销毁此类资源,因此尝试设置多订阅 terraform 工作区是徒劳的。也正如文档所说:

resource_group_name -(必需)Linux 虚拟机应存在于其中的资源组的名称。改变这一点会强制创建新资源。

TL;DR - 没有用于通过 terraform 在资源组或订阅之间迁移 Azure 资源的本机机制

正如您所指出的,手动移动资源并将其保留在 Terraform 中需要进行一些状态文件操作。幸运的是,Azure 资源 ID 非常简单,因此在 bash 中进行简单的字符串处理就可以实现这一目的。

快速而肮脏的 bash 脚本可以用新的替换旧的订阅 UUID,并且与此类似(警告 - 正确的实现取决于您的设置 - 在运行所有语句之前进行一些测试):

# Extract the identifying URLs using terraform plan
terraform  plan | grep "Refreshing state" > terraform-current-states.txt
# Extract the states we know from the configuration
terraform state list > terraform-state-list.txt

# Subscription strings
OLD_SUBSCRIPTION=11111111-1111-1111-1111-111111111111
NEW_SUBSCRIPTION=00000000-0000-0000-0000-000000000000
# Resource group strings (other name)
OLD_RG='SOME_NAME'
NEW_RG='ANOTHER_NAME'

# Iterate over state list
cat terraform-state-list.txt | while read RESOURCE; do
  AZURE_ID=$(grep "${RESOURCE}"  terraform-current-states.txt | cut -d"=" -f2 | tr -d ']')

  # null resources etc can be filtered out - no AZURE_ID
  if [ -z "$AZURE_ID" ]; then
    continue
  fi

  # print out the current resource and azure id mapping as a comment
  echo "# ${RESOURCE} ${AZURE_ID}"

  # replace the subscription and resource group strings (and remove weird characters from terraform
  NEW_AZURE_ID=$(echo ${AZURE_ID} | sed "s/${OLD_SUBSCRIPTION}/${NEW_SUBSCRIPTION}/" | sed "s/${OLD_RG}/${NEW_RG}/g" | sed "s/\x1b\[[0-9;]*m//g")

  # replace the current terraform state with a "state rm" and then "import" command
  echo "terraform state rm ${RESOURCE}; terraform import ${RESOURCE} ${NEW_AZURE_ID}
  "
done > terraform-migration-generated-script.sh
Run Code Online (Sandbox Code Playgroud)

上面生成了一个带有和命令的现成terraform-migration-generated-script.sh脚本。terraform rmterraform import

在开始之前,不要忘记状态备份,甚至terraform state pull备份到不同的位置。push

  • 这似乎有效。请注意,我必须更改 bash 脚本中的很多内容,但总体思路大致相同。我将这些更改合并到您的答案中(显然我可以做到这一点......)以供将来参考。再次感谢您的输入! (2认同)