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.
- Save a .ps1 file containing the following 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