top of page
gs9074

Get Faster Azure Resource Graph Multi-Subscription Queries

Updated: Apr 9, 2023

Are you tired of waiting for PowerShell cmdlets looping through all your subscriptions to find resources in Azure? Do you need a more efficient and powerful way to query and explore resource data across multiple subscriptions? Look no further than Azure Resource Graph (ARG).

ARG is a unified API and query language that enables you to retrieve resource data from multiple Azure subscriptions and management services. With its highly optimized engine, ARG can quickly retrieve large amounts of data and perform complex queries that are not easily achievable with PowerShell cmdlets.

One key advantage of ARG over PowerShell is its performance. While PowerShell cmdlets can be slower and less efficient when querying large amounts of data, ARG can handle large amounts of data quickly and efficiently. This makes it an ideal tool for users who need to perform complex queries that involve multiple resources or services.


Performance is one of ARG's key advantages over PowerShell cmdlets. To prove this, Microsoft conducted a performance comparison test using both ARG and PowerShell to query a large number of resources. The test involved querying over 40,000 resources across 250 subscriptions.

The results of the test showed that ARG was significantly faster than PowerShell when retrieving data across multiple subscriptions. Specifically, ARG was able to complete the query in just over 13 seconds, while PowerShell took over 30 minutes to complete the same query.


In addition to its performance advantages, ARG can also provide insights into resource utilization and cost. By creating custom reports and dashboards, you can track resource usage, cost trends, and other metrics to optimize your spending in Azure. This can be particularly useful for organizations that need to closely manage their Azure spending.

ARG is also highly flexible and can be used to query resources across multiple subscriptions, management groups, and tenants. This makes it an ideal tool for users with complex Azure environments and subscriptions.


Let's say you need to retrieve all the virtual machines across across all your subscriptions in Azure.



$subscriptions = Get-AzSubscription

$virtualMachines = foreach ($subscription in $subscriptions) {
    Set-AzContext -Subscription $subscription.Id
    Get-AzVM
}

$virtualMachines

Using PowerShell, you would need to first log in to each subscription one by one using the Connect-AzAccount cmdlet or as the above example set the subscription as the current the context. Then, you would need to run the Get-AzVM cmdlet to retrieve the information for each virtual machine in each subscription. This could be a time-consuming process, especially if you have a large number of subscriptions.


In contrast, using Azure Resource Graph, you can retrieve this information with a single query. For example, you could run the following ARG query to retrieve the same information:



resources
| where type == "microsoft.compute/virtualmachines"
| project name, resourceGroup

Sounds great, so how do I call it from desktop or my pipeline?


Using PowerShell of course! The magic cmdlet is Search-AzGraph.


To use Azure Resource Graph with PowerShell, you need to have the Resource Graph module installed. If you don't have it installed, you can follow the steps on this https://learn.microsoft.com/en-us/azure/governance/resource-graph/first-query-powershell#add-the-resource-graph-module to install it.



$query = @"
resources 
| where type == "microsoft.compute/virtualmachines"
| project name, resourceGroup
"@

$virtualMachines = Search-AzGraph -Query $query

But there is a catch. The above query will return 100 results, if you try to run the query through the portal you'll find it returns a lot more.


In your search you come across this page.



Scenario: Too many subscriptions
Issue

Customers with access to more than 1,000 subscriptions, including cross-tenant subscriptions with Azure Lighthouse, can't fetch data across all subscriptions in a single call to Azure Resource Graph.

The troubleshooting page explains the cause and offers an example solution. Which I've copied below.


# Replace this query with your own
$query = 'Resources | project type'

# Fetch the full array of subscription IDs
$subscriptions = Get-AzSubscription
$subscriptionIds = $subscriptions.Id

# Create a counter, set the batch size, and prepare a variable for the results
$counter = [PSCustomObject] @{ Value = 0 }
$batchSize = 1000
$response = @()

# Group the subscriptions into batches
$subscriptionsBatch = $subscriptionIds | Group -Property { [math]::Floor($counter.Value++ / $batchSize) }

# Run the query for each batch
foreach ($batch in $subscriptionsBatch){ $response += Search-AzGraph -Query $query -Subscription $batch.Group }

# View the completed results of the query on all subscriptions
$response

The above solution gets all the subscriptions and loops over each one issuing the Resource Graph Query. Weren't we trying to avoid iterating over subscriptions?


Yes, and the above solution is correct if we want to limit the query to more than a thousand or so subscriptions in PowerShell.


What the explanation doesn't clearly state is the 1000 subscription limit is only applicable to the Search-AzGraph cmdlet's subscription parameter. I have come across many pieces of production code that have taken and adapted the above solution believing it to would overcome the first 100 row limitation.


They may have blissfully been aware that the query should also add the -First parameter set to its maximum value of 1000.


So the command becomes



$query = @"
resources 
| where type == "microsoft.compute/virtualmachines"
| project name, resourceGroup
"@

$virtualMachines = Search-AzGraph -Query $query -First 1000

Great the command now returns 1000 rows but a quyick check through the portal shows there's more. So how do you get the result of the results?


The Search-AzGraph cmdlet supports paging results by returning a continuation token in the output when the maximum number of results has been reached. The continuation token can be used to retrieve the next page of results.

Here's an example of how to use tokens to page search results when using PowerShell's Search-AzGraph cmdlet:



# note the query now adds the id column and sorts the results by it
$query = Search-AzGraph -Query @"
Resources 
| where type == "microsoft.mompute/virtualmachines"
| project id, name, resourceGroup
| order by id
"@

$searchResults = Search-AzGraph -Query $query -First 1000
$skipToken = $searchResults.SkipToken

while ($skipToken) {
    $searchResults = Search-AzGraph -Query $query -SkipToken $skipToken -First 1000
    $skipToken = $searchResults.SkipToken

    $allResults += $searchResults.Data
}

Note the query has changed slightly. To maintain the integrity of the search results now includes the id column and sorts by. It doesn't have to be the id column but a unique column helps and the column is readily available.


There you have it. If you're finding PowerShell slow when querying resources in Azure, Azure Resource Graph is a useful tool to have in your arsenal of solutions. It has its own gotcha when managing the volume of results but I have detailed how it can be handled. Give it a try and see how it can help you streamline your Azure management tasks.

33 views0 comments

留言


bottom of page