更新VNet时遇ARM错误InUseSubnetCannotBeDeleted的解决咨询
I’ve run into this exact problem before—your ARM template is trying to delete and recreate the subnet instead of updating it in-place, which triggers the InUseSubnetCannotBeDeleted error because the subnet is attached to a VM. The root cause is how you’ve structured your subnet resources in the template: top-level subnet resources force a replace operation when properties change, whereas nesting subnets inside the virtual network resource tells ARM to perform an in-place update.
The Problem with Your Current Template
In your existing code, subnets are defined as separate Microsoft.Network/virtualNetworks/subnets resources at the top level. ARM treats these as independent resources, so when you modify properties like service endpoints, it tries to delete the old subnet and create a new one—something Azure blocks if the subnet is in use by a VM.
Here’s your original template for reference:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "vnetName": { "type": "string", "defaultValue": "VNet1", "metadata": { "description": "VNet name" } }, "vnetAddressPrefix": { "type": "string", "defaultValue": "10.0.0.0/16", "metadata": { "description": "Address prefix" } }, "subnets": { "type": "object" } }, "variables": { "location": "[resourceGroup().location]", "subnetcount": "[length(parameters('subnets').settings)]" }, "resources": [ { "apiVersion": "2018-06-01", "type": "Microsoft.Network/virtualNetworks", "name": "[parameters('vnetName')]", "location": "[variables('location')]", "properties": { "addressSpace": { "addressPrefixes": ["[parameters('vnetAddressPrefix')]"] } }, "resources": [ ] }, { "apiVersion": "2018-06-01", "type": "Microsoft.Network/virtualNetworks/subnets", "name": "[concat(parameters('vnetName') , '/' , parameters('subnets').settings[copyIndex()].name)]", "location": "[variables('location')]", "copy": { "name": "subnetLoop", "count": "[variables('subnetcount')]" }, "dependsOn": ["[parameters('vnetName')]"], "properties": { "addressPrefix": "[parameters('subnets').settings[copyIndex()].addressPrefix]" } } ] }
The Fix: Nest Subnets Inside the VNet Resource
To get ARM to update the subnet in-place, move the subnet definition into the resources array of the virtual network resource. This way, ARM recognizes the change as an update to the existing subnet, not a replacement. We’ll also add the serviceEndpoints property to your subnet configuration since that’s what you’re trying to modify.
Here’s the revised template:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "vnetName": { "type": "string", "defaultValue": "VNet1", "metadata": { "description": "VNet name" } }, "vnetAddressPrefix": { "type": "string", "defaultValue": "10.0.0.0/16", "metadata": { "description": "Address prefix" } }, "subnets": { "type": "object" } }, "variables": { "location": "[resourceGroup().location]", "subnetcount": "[length(parameters('subnets').settings)]" }, "resources": [ { "apiVersion": "2018-06-01", "type": "Microsoft.Network/virtualNetworks", "name": "[parameters('vnetName')]", "location": "[variables('location')]", "properties": { "addressSpace": { "addressPrefixes": ["[parameters('vnetAddressPrefix')]"] } }, "resources": [ { "apiVersion": "2018-06-01", "type": "subnets", "name": "[parameters('subnets').settings[copyIndex()].name]", "copy": { "name": "subnetLoop", "count": "[variables('subnetcount')]" }, "dependsOn": ["[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"], "properties": { "addressPrefix": "[parameters('subnets').settings[copyIndex()].addressPrefix]", "serviceEndpoints": "[parameters('subnets').settings[copyIndex()].serviceEndpoints]" } } ] } ] }
Key Changes Explained
- Nested Subnet Resource: The subnet is now inside the VNet’s
resourcesarray, using the simplified typesubnetsinstead of the fullMicrosoft.Network/virtualNetworks/subnetspath. This tells ARM to update the existing subnet rather than replace it. - Service Endpoints Property: Added
serviceEndpointsto the subnet properties, which allows you to pass in the service endpoints you want to configure via thesubnetsparameter. - Simplified Resource ID: The
dependsOnuses the VNet’s resource ID, which is more reliable than just the name.
Example Parameters for Service Endpoints
When deploying the revised template, use a subnets parameter that includes the serviceEndpoints configuration. For example:
{ "vnetName": { "value": "VNet1" }, "vnetAddressPrefix": { "value": "10.0.0.0/16" }, "subnets": { "value": { "settings": [ { "name": "Subnet1", "addressPrefix": "10.0.1.0/24", "serviceEndpoints": [ { "service": "Microsoft.Storage", "locations": ["eastus"] } ] } ] } } }
Verification
When you deploy this revised template, Azure will update the subnet’s service endpoints in-place without attempting to delete the subnet. This matches the behavior you see in the Azure Portal and PowerShell, where you can modify service endpoints on a used subnet without issues.
内容的提问来源于stack exchange,提问作者Kamsiinov

