Microsoft Azure: How to execute a synchronous Azure PowerShell cmdlet multiple times at once, using a single PowerShell session

 

Overview

Often times, Microsoft Azure customers have requirements to create multiple resources of the same type, and they wish to have these resources created as quickly as possible in a scripted solution.

Many of the Azure PowerShell cmdlets are synchronous in nature, where the cmdlet will not return until provisioning is complete.

Synchronous operations in PowerShell can significantly slow down a scripted deployment, and the purpose of this post is to help Azure customers script synchronous cmdlets in multiple threads within a single PowerShell session to speed up deployment times.

The example we will demonstrate is the creation of PublicIpAddress resources in Azure Resource Manager (ARM). The cmdlet used is: New-AzureRmPublicIpAddress

Disclaimer

This post contains a link to a PowerShell code sample. This sample is being provided only as a sample, and is not intended to serve as a solution to any technical issue. Microsoft provides this code sample without support, warranties, and confers no rights. By executing any portion of this code sample, you are agreeing to do so at your own risk.

 

Sample Scenario

  • You have a requirement to create 15 PublicIpAddress resources in Azure
  • You have written a simple for loop like this:for($i=0;$i -lt 15;$i++){New-AzureRmPublicIpAddress -Name "piptest$($i)" -ResourceGroupName contosoRg -Location "East US" -AllocationMethod Dynamic}
  • Result: 15 PublicIpAddress resources are created in roughly 8 minutes, 30 seconds. This is not fast enough, so you decide to try this in Powershell jobs, like this:Start-Job -Name createPip -ScriptBlock {New-AzureRmPublicIpAddress -Name "piptest1" -ResourceGroupName contosoRg -Location "East US" -AllocationMethod Dynamic}
  • Result: The Powershell job fails because you need to execute Login-AzureRmAccount. This happens because Start-Job does not execute within the context of your existing PowerShell session. The Azure PowerShell module will expect you to authenticate each job.

Final Solution

There is a trick to making this work with a single Azure Powershell session. The key is the use of [Powershell]::Create() and then passing in and invoking a script block with arguments.

  1. Save a  .ps1 file containing the following code sample:

TechNet Gallery Code Sample

     2. Execute the code sample by calling the saved .ps1 file using arguments for the following:

a. Count – Number of resources you need to create

b. NamePrefix – Resources will be created as “NamePrefixY” where Y is an integer counter for the count of resources created (i.e. – “PipTest1” – “PipTest15” where “PipTest” is the NamePrefix value)

c. RgName – Name of the Azure Resource Group within your Azure subscription (this must already exist, as the script sample does not create a new Resource Group)

d. Location – A valid Azure location (i.e. – “East US” or “North Europe”)

Sample Syntax

C:\PipTest.ps1 -Count 15 -NamePrefix “PipTest” -RgName “ContosoRg” -Location “East US”

 

Sample Output

Job for PublicIpAddress PipTest1 - started

Job for PublicIpAddress PipTest2 - started

Job for PublicIpAddress PipTest3 - started

Job for PublicIpAddress PipTest4 - started

Job for PublicIpAddress PipTest5 - started

Job for PublicIpAddress PipTest6 - started

Job for PublicIpAddress PipTest7 - started

Job for PublicIpAddress PipTest8 - started

Job for PublicIpAddress PipTest9 - started

Job for PublicIpAddress PipTest10 - started

Job for PublicIpAddress PipTest11 - started

Job for PublicIpAddress PipTest12 - started

Job for PublicIpAddress PipTest13 - started

Job for PublicIpAddress PipTest14 - started

Job for PublicIpAddress PipTest15 - started

Completed in 0 minutes, 39 seconds

 

To conclude, we can execute synchronous Azure PowerShell cmdlets in an asynchronous fashion while sharing Azure authentication across script blocks in a single PowerShell session. This sample demonstrates a time advantage of nearly 8 minutes for deployment of 15 resources of a single resource type (PublicIpAddress). This sample could be modified to utilize other Azure PowerShell cmdlets to suit your deployment needs.

Enjoy!
Adam Conkle - MSFT