Identify and Manage Unattached Disks in Azure Storage

Azure Cost Optimization

To be successful in the cloud, organizations need to find ways to make it easier to manage their cloud resources.  While the goal may be to fully automate the management that may not be practical for all environments.  A good first step is to use Azure Policies to flag issues for review with the audit status, and then leverage a library of PowerShell scripts to help make the changes needed.

Being Billed for Unattached Disks

I have come across several scenarios where customers are being billed for resources that are no longer being used.  A common example relates to virtual machines that have been de-provisioned, but the disks remain in the storage account.  Charges continue to be incurred even if the VMs are no longer running.  This may not be unexpected if the resources are intended to be used for a hybrid disaster recovery scenario or in place for occasional use, but in several cases, it was just an oversight.  One key step in managing and optimizing costs is to ensure that you are only paying for what you need, and to remove what you do not need.  When looking at the charges as a percentage of total spend, this is important in all environments from small to very large.

Azure Policies

In my article, Foundations of Azure Governance, I included Azure Policies as a foundational pillar of my governance approach.  By defining policies, it gives the administrators or auditors a central place to monitor the compliance and adherence to the policies.

In many of the organizations I work with, the resource management duties are distributed across the teams.  There are multiple teams that can provision and maintain resources (Contributor role) within the environment.  This can lead to tricky situations where the core tenant administrators or owners do not know the details of what is being created or removed.  Policies, along with logging, can help address this shortcoming and help to flag resources that need to be reviewed and perhaps removed.  By using Azure Policies, this process is much quicker and easier to manage in a consistent way.

One of the great things about Azure Policy definitions is that you can control the scope and exclusions.  For the purpose of this policy, I would recommend applying the assignment at the subscription level.  This has the benefit of casting a wide net and should be able to identify any disks that become unattached from anywhere in the scope.  If you have some VMs that are only used occasionally, it is possible to add those resources to the exclusions list to prevent them from being flagged by the audit process.  It may be best to group those resources into one or more dedicated resource groups so that the exclusion can be applied to the entire resource group if applicable.

Audit Unassigned Disks Policy

The policy for auditing unassigned disks is very simple.   It identifies the objects to review “Microsoft.Compute/disks” and then checks the diskState property for a status of “Unnattached”.  Any items that are found are flagged for audit.

{
  "properties": {
    "displayName": "Audit unnattached disks",
    "description": "Audit unnattached disks. Checks the Microsoft.Compute/disks/diskState property",
    "mode": "all",
    "parameters": {},
    "policyRule": {
      "if": {
        "allOf": [{
          "field": "type",
          "equals": "Microsoft.Compute/disks"
        },
        {
          "field": "Microsoft.Compute/disks/diskState",
          "equals": "Unnattached"
        }]},
        "then": {
          "effect": "audit"
        }
      }
    }
}

If you are unfamiliar with how to create policy definitions, you can follow the tutorials here:  https://docs.microsoft.com/en-us/azure/governance/policy/tutorials/create-custom-policy-definition

If you are unfamiliar with how to create policy assignments, you can follow the tutorial here:  https://docs.microsoft.com/en-us/azure/governance/policy/assign-policy-portal

Here is an example PowerShell script that does both.

# Set the Id of the subscription to apply the policy to
$rgName = "MyResourceGroup"

# Get a ref to the sub that will be the scope of the assignment
$rg = Get-AzResourceGroup -Name $rgName

# Create the new policy and get a ref to the definition object
$definition = New-AzPolicyDefinition 
​-Name "Audit unnattached disks" `
-DisplayName "Audit unnattached disks" `
​-Metadata '{"Category":"Storage"}' `
-Policy '{"if": {"allOf": [{ "field": "type", `
"equals": "Microsoft.Compute/disks" },`
{"field": "Microsoft.Compute/disks/diskState","equals": "Unnattached"}]},`
"then": {"effect": "audit"}}'

# Create the policy assignment with the built-in definition against your resource group
New-AzPolicyAssignment -Name 'audit-unattached-disks' `
-DisplayName 'Audit unnattached disks' `
-Scope $rg.ResourceId `
-PolicyDefinition $definition

Cleaning Up Unattached Disks with PowerShell

Cleaning up the unattached disks is a very simple operation.  Using some simple PowerShell scripts, you can easily identify and delete the unattached disks.  My scripts were developed based on the Microsoft documentation so instead of showing them here, I will point to their source examples.

Managed Disks:  https://docs.microsoft.com/en-us/azure/virtual-machines/windows/find-unattached-disks#managed-disks-find-and-delete-unattached-disks

Unmanaged Disks:  https://docs.microsoft.com/en-us/azure/virtual-machines/windows/find-unattached-disks#unmanaged-disks-find-and-delete-unattached-disks

If you are using unmanaged disks and if all the disks in the storage account have been removed, you may also want to delete the storage account to prevent additional billing of those storage resources.  Again, you are billed based on allocated space, not used space.

Alternatively, if you have exclusions in place and only want to work with objects that are out of compliance, the following PowerShell will get a list of resources flagged as out of compliance.

# Get the resources in specified resource group that are not compliant 
# with the unattached disks policy assignment
Get-AzPolicyState -ResourceGroupName $rg.ResourceGroupName `
-PolicyAssignmentName 'audit-unattached-disks' `
-Filter 'IsCompliant eq false'

Wrap- Up

Using the info in this article you can take the first steps in addressing the life-cycle of VMs and associated disks after the VMs are no longer needed.  By leveraging Azure Policies, we can easily raise the audit flag to identify when we have unattached disks, and then using the simple PowerShell scripts we can remove the disk files that are no longer needed.  Using this process will help optimize your storage, and ensure you are only paying for resources you are using.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: