u/Wise_Soft6978

▲ 3 r/AZURE

Finding idle and orphaned Azure managed disks, including the ones the standard query misses

Disclosure: I work at a storage optimization vendor. Everything here uses native Azure tooling.

I cleaned up disks across a few subscriptions last week. The standard "unattached disks" query found 65 disks costing about $4,759/month. The checks below found 35 more, costing about $2,563/month.

Fix the base query

Filtering on Unattached alone misses two states:

Reserved: the disk is on a deallocated VM. The VM costs nothing while stopped, but the disk still bills in full. This was our biggest miss.

ActiveSAS: the disk is unattached but has an open export SAS.

Resources

| where type =~ 'microsoft.compute/disks'

| where properties.diskState in~ ('Unattached', 'Reserved', 'ActiveSAS')

| project name, resourceGroup, subscriptionId,

state = tostring(properties.diskState),

sku = tostring(sku.name),

sizeGB = toint(properties.diskSizeGB)

| order by sizeGB desc

What that still misses

  1. Orphaned snapshots. These are snapshots whose source disk is gone.

Resources

| where type =~ 'microsoft.compute/snapshots'

| extend src = tolower(tostring(properties.creationData.sourceResourceId))

| join kind=leftanti (

Resources | where type =~ 'microsoft.compute/disks' | project src = tolower(id)

  ) on src

| project name, resourceGroup, subscriptionId, sizeGB = toint(properties.diskSizeGB)

  1. Attached but never mounted. Azure reports these disks as healthy. Inside the VM, the disk was never formatted, or it was mounted without an fstab entry and lost at reboot. You have to check from the guest:

Linux: lsblk -f shows the disk with no filesystem type and no mount point.

Windows: Get-Disk | Where-Object PartitionStyle -eq 'RAW'

  1. Mounted but idle. These disks are in use on paper but not earning their cost:

No I/O: disk read and write operations have been near zero for 30 days.

Mostly empty: for example, 5% used on 1 TB. Azure disk metrics don't show filesystem usage, so you need VM Insights:

InsightsMetrics  

| where TimeGenerated > ago(30d)  

| where Namespace == "LogicalDisk" and Name == "FreeSpacePercentage"  

| extend mount = tostring(parse_json(Tags)["vm.azm.ms/mountId"])  

| where mount !in ("/", "/boot", "/mnt", "C:", "D:")  

| summarize minFreePct = min(Val) by Computer, mount  

| where minFreePct > 80  

Wrong tier: a P30 doing 40 IOPS could be an E30 at about a third of the cost.

Before you delete anything

Some disks look orphaned but aren't:

-ASRReplica disks belong to Azure Site Recovery.

AzureBackupRG_* resource groups hold Azure Backup restore points.

MC_* resource groups hold AKS volumes.

Databricks-managed resource groups break if you touch them.

If you're not sure, snapshot first.

reddit.com
u/Wise_Soft6978 — 14 days ago