You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform azurerm重复执行报InUseSubnetCannotBeDeleted错误

问题背景

我在搭建Terraform项目,用于在Azure订阅内创建全量所需资源,覆盖资源组、虚拟网络(vnet)、子网(subnet)、虚拟机(VM)等。
首次执行部署成功后,我没有对subnet以及关联的VM做任何配置修改,二次执行时系统提示无法删除被占用的subnet,具体报错如下:

Error: creating/updating Virtual Network: (Name "" / Resource Group ""): network.VirtualNetworksClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="InUseSubnetCannotBeDeleted" Message="Subnet build-agent is in use by /subscriptions/mysub/resourceGroups/myrg/providers/Microsoft.Network/networkInterfaces/mynic/ipConfigurations/internal and cannot be deleted. In order to delete the subnet, delete all the resources within the subnet. See aka.ms/deletesubnet." Details=[]

对应Terraform配置代码如下:

terraform {
  required_version = ">= 1.1.0"
  backend "azurerm" {
  }
  required_providers {
    azurerm = {
      version = "=3.5.0"
      source  = "hashicorp/azurerm"
    }
  }
}

# Configure the Microsoft Azure Provider
provider "azurerm" {
  features {}
}

locals {
    name_suffix = "<mysuffix>"
}

resource "azurerm_resource_group" "rg-infra" {
  name     = "rg-${local.name_suffix}"
  location = "UK South"
}

resource "azurerm_virtual_network" "vnet-mgmt" {
  name                = "vnet-${local.name_suffix}"
  location            = azurerm_resource_group.rg-infra.location
  resource_group_name = azurerm_resource_group.rg-infra.name
  address_space       = ["<myiprange>"]

  subnet {
    name           = "virtual-machines"
    address_prefix = "<myiprange>"
  }

  subnet {
    name           = "databases"
    address_prefix = "<myiprange>"
  }
}

data "azurerm_virtual_network" "network" {
  name                = "vnet-${local.name_suffix}"
  resource_group_name = azurerm_resource_group.rg-infra.name
}

resource "azurerm_subnet" "sb-ansible" {
  name                 = "build-agent"
  resource_group_name  = azurerm_resource_group.rg-infra.name
  virtual_network_name = data.azurerm_virtual_network.network.name
  address_prefixes     = ["<myiprange>"]
  depends_on           = [azurerm_virtual_network.vnet-mgmt]

}

data "azurerm_subnet" "prd-subnet" {
    name = "build-agent"
    virtual_network_name = data.azurerm_virtual_network.network.name
    resource_group_name = azurerm_resource_group.rg-infra.name
    depends_on          = [azurerm_subnet.sb-ansible]
}


resource "azurerm_network_interface" "ni-ansible" {
  name                = "nic-ansible-${local.name_suffix}"
  location            = azurerm_resource_group.rg-infra.location
  resource_group_name = azurerm_resource_group.rg-infra.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = data.azurerm_subnet.prd-subnet.id
    private_ip_address_allocation = "Dynamic"
  }

  lifecycle {
    ignore_changes = ["ip_configuration"]
  }

  depends_on           = [azurerm_subnet.sb-ansible]
}

resource "azurerm_linux_virtual_machine" "ansible-vm" {
  name                = "ansible-build-agent"
  resource_group_name = azurerm_resource_group.rg-infra.name
  location            = azurerm_resource_group.rg-infra.location
  size                = "Standard_D2as_v4"
  admin_username      = "myadminuser"
  network_interface_ids = [
    azurerm_network_interface.ni-ansible.id,
  ]

  admin_ssh_key {
    username   = "myadminuser"
    public_key = ""
  }

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "18.04-LTS"
    version   = "latest"
  }

  lifecycle {
    ignore_changes = ["source_image_reference"]
  }

  depends_on           = [azurerm_network_interface.ni-ansible]
}
问题根因

报错由Terraform AzureRM provider的子网管理逻辑冲突导致:

  • 你在azurerm_virtual_network资源块内用内嵌subnet块定义了2个子网,同时又单独用azurerm_subnet资源定义了第三个build-agent子网
  • AzureRM 3.x版本中,不允许同时混用vnet内嵌subnet块和独立azurerm_subnet资源管理同一个vnet下的子网。首次部署时Terraform能顺序创建资源,但二次执行做状态对齐时,会认为vnet内嵌配置里不存在build-agent子网,触发vnet更新逻辑要删掉这个子网,而此时子网已经被网卡挂载占用,直接触发Azure侧的删除拦截报错。
  • 配置中多组不必要的depends_on、用data源引用同栈内创建的资源,也放大了状态判定的时序问题。
修复方案

按以下步骤调整配置即可彻底解决:

  1. 移除azurerm_virtual_network块里所有内嵌的subnet配置块,所有子网全部改用独立的azurerm_subnet资源定义,包括原来的virtual-machines和databases两个子网
  2. 删除不必要的data源引用:同Terraform栈内创建的vnet和subnet,直接引用资源属性即可,不需要再通过data源重复查询,去掉data "azurerm_virtual_network" "network"和data "azurerm_subnet" "prd-subnet"两个块
  3. 清理冗余的depends_on配置:资源间通过属性引用建立隐式依赖就足够,不需要手动加显式依赖
  4. 调整后先执行一次terraform apply刷新状态,后续再执行就不会出现误删子网的问题

调整后的核心vnet和子网配置参考:

resource "azurerm_virtual_network" "vnet-mgmt" {
  name                = "vnet-${local.name_suffix}"
  location            = azurerm_resource_group.rg-infra.location
  resource_group_name = azurerm_resource_group.rg-infra.name
  address_space       = ["<myiprange>"]
  # 移除所有内嵌subnet块
}

# 所有子网全部用独立资源定义
resource "azurerm_subnet" "sb_vms" {
  name                 = "virtual-machines"
  resource_group_name  = azurerm_resource_group.rg-infra.name
  virtual_network_name = azurerm_virtual_network.vnet-mgmt.name
  address_prefixes     = ["<myiprange>"]
}

resource "azurerm_subnet" "sb_dbs" {
  name                 = "databases"
  resource_group_name  = azurerm_resource_group.rg-infra.name
  virtual_network_name = azurerm_virtual_network.vnet-mgmt.name
  address_prefixes     = ["<myiprange>"]
}

resource "azurerm_subnet" "sb_ansible" {
  name                 = "build-agent"
  resource_group_name  = azurerm_resource_group.rg-infra.name
  virtual_network_name = azurerm_virtual_network.vnet-mgmt.name
  address_prefixes     = ["<myiprange>"]
}

# 网卡直接引用subnet资源属性,不需要data源
resource "azurerm_network_interface" "ni-ansible" {
  name                = "nic-ansible-${local.name_suffix}"
  location            = azurerm_resource_group.rg-infra.location
  resource_group_name = azurerm_resource_group.rg-infra.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.sb_ansible.id
    private_ip_address_allocation = "Dynamic"
  }

  lifecycle {
    ignore_changes = ["ip_configuration"]
  }
}
临时规避方案

如果不想大改现有配置,可以在azurerm_virtual_network资源块里加lifecycle规则,忽略vnet下子网的变更检测,这样Terraform就不会触发vnet层面的子网删除逻辑:

resource "azurerm_virtual_network" "vnet-mgmt" {
  // ...原有配置保留
  lifecycle {
    ignore_changes = [subnet]
  }
}

注意:这个方案只是临时规避,长期维护还是建议统一子网管理方式,不要混用内嵌块和独立资源


内容的提问来源于stack exchange,提问作者milesb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 07:24:24