Create a complete virtual machine scale set with PowerShell

This script creates a virtual machine scale set running Windows Server 2016. Individual resources are configured and created, rather than the using the built-in resource creation options available here in New-AzVmss. After running the script, you can access the VM instances through RDP.

If you don't have an Azure subscription, create an Azure free account before you begin.


This article uses the Azure Az PowerShell module, which is the recommended PowerShell module for interacting with Azure. To get started with the Az PowerShell module, see Install Azure PowerShell. To learn how to migrate to the Az PowerShell module, see Migrate Azure PowerShell from AzureRM to Az.

Sample script

# Provide your own secure password for use with the VM instances
$cred = Get-Credential
$Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($cred.Password)
$Password = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($Ptr)

# Define variables for resource names
$resourceGroupName = "myResourceGroup"
$scaleSetName = "myScaleSet"
$location = "EastUS"

# Create a resource group
New-AzResourceGroup -ResourceGroupName $resourceGroupName -Location $location

# Create a virtual network subnet
$subnet = New-AzVirtualNetworkSubnetConfig `
  -Name "mySubnet" `

# Create a virtual network
$vnet = New-AzVirtualNetwork `
  -ResourceGroupName $resourceGroupName `
  -Name "myVnet" `
  -Location $location `
  -AddressPrefix `
  -Subnet $subnet

# Create a public IP address
$publicIP = New-AzPublicIpAddress `
  -ResourceGroupName $resourceGroupName `
  -Location $location `
  -AllocationMethod Static `
  -Name "myPublicIP"

# Create a frontend and backend IP pool
$frontendIP = New-AzLoadBalancerFrontendIpConfig `
  -Name "myFrontEndPool" `
  -PublicIpAddress $publicIP
$backendPool = New-AzLoadBalancerBackendAddressPoolConfig -Name "myBackEndPool"

# Create a Network Address Translation (NAT) pool
# A rule for Remote Desktop Protocol (RDP) traffic is created on TCP port 3389
$inboundNATPool = New-AzLoadBalancerInboundNatPoolConfig `
  -Name "myRDPRule" `
  -FrontendIpConfigurationId $frontendIP.Id `
  -Protocol TCP `
  -FrontendPortRangeStart 50001 `
  -FrontendPortRangeEnd 50010 `
  -BackendPort 3389

# Create the load balancer
$lb = New-AzLoadBalancer `
  -ResourceGroupName $resourceGroupName `
  -Name "myLoadBalancer" `
  -Location $location `
  -FrontendIpConfiguration $frontendIP `
  -BackendAddressPool $backendPool `
  -InboundNatPool $inboundNATPool

# Create a load balancer health probe for TCP port 80
Add-AzLoadBalancerProbeConfig -Name "myHealthProbe" `
  -LoadBalancer $lb `
  -Protocol TCP `
  -Port 80 `
  -IntervalInSeconds 15 `
  -ProbeCount 2

# Create a load balancer rule to distribute traffic on port TCP 80
# The health probe from the previous step is used to make sure that traffic is
# only directed to healthy VM instances
Add-AzLoadBalancerRuleConfig `
  -Name "myLoadBalancerRule" `
  -LoadBalancer $lb `
  -FrontendIpConfiguration $lb.FrontendIpConfigurations[0] `
  -BackendAddressPool $lb.BackendAddressPools[0] `
  -Protocol TCP `
  -FrontendPort 80 `
  -BackendPort 80 `
  -Probe (Get-AzLoadBalancerProbeConfig -Name "myHealthProbe" -LoadBalancer $lb)

# Update the load balancer configuration
Set-AzLoadBalancer -LoadBalancer $lb

# Create IP address configurations
$ipConfig = New-AzVmssIpConfig `
  -Name "myIPConfig" `
  -LoadBalancerBackendAddressPoolsId $lb.BackendAddressPools[0].Id `
  -LoadBalancerInboundNatPoolsId $inboundNATPool.Id `
  -SubnetId $vnet.Subnets[0].Id

# Create a config object
# The VMSS config object stores the core information for creating a scale set
$vmssConfig = New-AzVmssConfig `
    -Location $location `
    -SkuCapacity 2 `
    -SkuName "Standard_DS2" `
    -UpgradePolicyMode "Automatic"

# Reference a virtual machine image from the gallery
Set-AzVmssStorageProfile $vmssConfig `
  -OsDiskCreateOption "FromImage" `
  -ImageReferencePublisher "MicrosoftWindowsServer" `
  -ImageReferenceOffer "WindowsServer" `
  -ImageReferenceSku "2016-Datacenter" `
  -ImageReferenceVersion "latest"

# Set up information for authenticating with the virtual machine
Set-AzVmssOsProfile $vmssConfig `
  -AdminUsername $cred.UserName `
  -AdminPassword $Password `
  -ComputerNamePrefix "myVM"

# Attach the virtual network to the config object
Add-AzVmssNetworkInterfaceConfiguration `
  -VirtualMachineScaleSet $vmssConfig `
  -Name "network-config" `
  -Primary $true `
  -IPConfiguration $ipConfig

# Create the scale set with the config object (this step might take a few minutes)
New-AzVmss `
  -ResourceGroupName $resourceGroupName `
  -Name $scaleSetName `
  -VirtualMachineScaleSet $vmssConfig

Clean up deployment

Run the following command to remove the resource group, scale set, and all related resources.

Remove-AzResourceGroup -Name $resourceGroupName

Script explanation

This script uses the following commands to create the deployment. Each item in the table links to command specific documentation.

Command Notes
New-AzResourceGroup Creates a resource group in which all resources are stored.
New-AzVirtualNetworkSubnetConfig Creates a subnet configuration. This configuration is used with the virtual network creation process.
New-AzVirtualNetwork Creates a virtual network.
New-AzPublicIpAddress Creates a public IP address.
New-AzLoadBalancerFrontendIpConfig Creates a front-end IP configuration for a load balancer.
New-AzLoadBalancerBackendAddressPoolConfig Creates a backend address pool configuration for a load balancer.
New-AzLoadBalancerInboundNatRuleConfig Creates an inbound NAT rule configuration for a load balancer.
New-AzLoadBalancer Creates a load balancer.
Add-AzLoadBalancerProbeConfig Creates a probe configuration for a load balancer.
Add-AzLoadBalancerRuleConfig Creates a rule configuration for a load balancer.
Set-AzLoadBalancer Update the load balancer with the provided information.
New-AzVmssIpConfig Create an IP configuration for the scale set VM instances. The VM instances are connected to the load balancer backend pool, NAT pool, and virtual network subnet.
New-AzVmssConfig Creates a scale set configuration. This configuration includes information such as number of VM instances to create, the VM SKU (size), and upgrade policy mode. The configuration is added to by additional cmdlets, and is used during scale set creation.
Set-AzVmssStorageProfile Define the image to be used for the VM instances, and add it to the scale set config.
Set-AzVmssOsProfile Define the administrative username and password credentials, and VM naming prefix. Add these values to the scale set config.
Add-AzVmssNetworkInterfaceConfiguration Add a virtual network interface to the VM instances, based on the IP configuration. Add these values to the scale set config.
New-AzVmss Create the scale set based on the information provided in the scale set configuration.
Remove-AzResourceGroup Removes a resource group and all resources contained within.

Next steps

For more information on the Azure PowerShell module, see Azure PowerShell documentation.