Cut Azure costs by automatically removing inactive resource groups

Cost management is a very important aspect of a cloud governance strategy.  The Azure cloud give you a tremendous amount of tools to automate this as much as possible.  This blog post discusses one of the many approaches to minimize the costs for Azure development environments.

In such development subscriptions, developers typically get the flexibility and freedom to create resource groups and resources.  However, after a while, these resources are often not used anymore and are just burning money.  Below, you can find an approach that automatically detects inactive resource groups, based on the Azure Activity Log.  In case that such a resource group is identified, an email is send to the responsible to ask if the inactive resource group may be removed.  After confirmation, the resource group gets automatically deleted from your Azure subscription.  Let’s have a closer look!

Configure Log Analytics

First of all, we need to ensure that the Activity Log of the development subscription is continuously exported to a Log Analytics workspace.

  • Create a new Log Analytics workspace

CostMgmt1

  • Navigate to the subscription you want to monitor.   Select the Activity Log tab and click on Diagnostic settings.

CostMgmt2

  • Configure a continuous export to the previously created Logic Analytics workspace, via the Add diagnostic settings button.

CostMgmt3

Identify inactive resource groups

Now, it’s time to create a scheduled Logic App that loops across all resource groups of the subscription.

Therefore, you need to configure the following actions:

  • Recurrence: typically once per week
  • Azure Resource Manager connector: select the List resource groups action
  • For each: loop across all resource groups

CostMgmt4

For each resource group, we use the Logic Analytics connector with the Run query and list results action:

  • Select the previously created Log Analytics workspace
  • Write a Kusto query to select the number of administrative actions within the resource group for the last x days
  • The resource group is fetched via this expression:
    toUpper(items(‘For_each_resource_group’).name)

CostMgmt5

Now we have to call another Logic App, that will handle the resource group removal request in case there was no activity logged.

  • Add a decision action, that is configured with this expression:
    @first(body(‘Get_administrative_activity_count’)?[‘value’]).activityCount
  • If the count is zero, we call a Logic App and pass the following info:
    • Email
    • Reason
    • ResourceGroupName
    • SubscriptionId

CostMgmt6

Request removal of a resource group

In this Logic App, we first want to request confirmation of the resource group owner, before we delete it.  This is done via an approval email, which is an action that asynchronously waits for the user to confirm.

CostMgmt7

In case the user confirms by clicking Yes, we have to delete the resource group.

  • Add a decision action, that is configured with this expression:
    @body(‘Send_removal_request’)?[‘SelectedOption’]
  • If it’s a Yes, we use the Delete resource group action

CostMgmt8

See it in action

Let’s give this a try.

  • Create a brand new resource group.  In my case, it’s named “my-test-resource-group”.  This one won’t have any activity assigned to it, as no resources were created in the resource group.
  • Trigger the first Logic App.  This one runs successfully.

CostMgmt90

  • The next Logic Apps gets fired and sends out an email like this and waits for the response.

CostMgmt91

  • If you click on Yes, the Logic App continues processing and removes the resource group.

CostMgmt92

Conclusion

This blog shows the ease-of-use that Logic Apps brings in many scenarios, of which cost management is an important one.  This idea can be used as a starting point for your cost reduction strategy.  One drawback to this solution: many of the used connectors are still in preview.  Hopefully they “GA” pretty soon.

Cheers
Toon

About me

Hi! I’m Toon Vanhoutte, a hands-on Azure architect – based in Belgium – with a big passion for teaching and helping people out. I’m happy to assist you during your Azure journey with high-quality advisory and I would love to teach you Azure’s possibilities via my tailored training courses.

Subscribe to the blog