Many of you are using Azure every day, have you ever stopped and thought about to make a cleanup of your cloud environment? If not, you should do that because there is many reasons behind why to do this. I like Azure Governance approaches and one of them is cutting off the cost for cloud service – understand that as cost optimization 😊 and make infrastructure and resources well-arranged. When you often deploy and remove resources for testing or development it can happen that some parts of resources will stay in your environment alone – so called orphans. As a nice example is deployment of virtual machine in Azure. Basically virtual machine needs resource group and virtual network where it will be deployed, then as a core parts NIC interface, sometimes public IP, definitely some managed disks and network security group. Quite lot of resources but needed ones!
What happens when you just remove VM from the portal? Mostly virtual machine itself is removed but the rest like NIC interface, public IP, managed disk stays in your subscription:
The fact is that you still pay for some of these resources – managed disks, public IPs and you definitely don’t want to pay for this! The rest of resources is for no cost but you also don’t want to have mess in growing environment, right?
To have a good overview of such “orphaned” resources I am using workbook which I created with few simple Kusto queries. It will tell me which resources are left in environment alone and I can think about their deletion:
Queries which I used in this workbook:
DISKs
Resources
| where type has "microsoft.compute/disks"
| extend diskState = tostring(properties.diskState)
| where managedBy == ""
or diskState == 'Unattached'
| project id, diskState, resourceGroup, location, subscriptionId
NICs
Resources
| where type has "microsoft.network/networkinterfaces"
| where properties !has 'privateLinkConnectionProperties'
| where properties !has 'virtualmachine'
| project id, resourceGroup, location, subscriptionId, properties.macAddress
NSGs
Resources
| where type =~ 'microsoft.network/networksecuritygroups' and isnull(properties.networkInterfaces) and isnull(properties.subnets)
| project Resource=id, resourceGroup, subscriptionId, location
Static PIPs
resources
| where type has "microsoft.network/publicipaddresses"
| where properties.publicIPAllocationMethod == "Static"
| where properties !has "ipConfiguration"
| project id, name, subscriptionId, location, resourceGroup
Dynamic PIPs
resources
| where type has "microsoft.network/publicipaddresses"
| where properties.publicIPAllocationMethod == "Dynamic"
| where properties !has "ipConfiguration"
| project id, name, subscriptionId, location, resourceGroup
You can find template for this workbook on my Github. You can import it or just copy/paste code when creating new Template Specs in Azure:
If you want to extend this workbook with your own Kusto queries for another resources which you would like to monitor if they left alone, then just simply edit workbook in Azure monitor and let me know what to add eventually in comments on my Github so I can add it directly to template.
There are of course other options how to automatically remove these leftovers and one of them is to check the options for auto-delete for disks, NIC, public IP when you are creating VM in Azure portal:
Another option should be adding the parameters into ARM templates if you deploy machines via DevOps or by TerraForm and other automatization tools.
Hopefully this article will help some of you to reduce some costs and make your environment better well-arranged for easy management.