Deploying Virtual Machines in Azure using Azure Resource Manager - PowerShell API (Part 1)

by [Published on 12 Jan. 2016 / Last Updated on 12 Jan. 2016]

This article is the first of a two-part series on deploying virtual machines in Azure. Part I will cover how to use Azure Resource Manager (ARM) PowerShell APIs to programmatically provision virtual machines. In Part Two, we will use ARM templates to perform the same provisioning actions.

If you would like to read the next part in this article series please go to Deploying Virtual Machines in Azure using Azure Resource Manager - ARM Templates (Part 2).

Azure APIs

Azure currently has two different deployment models: Service Management (also referred to now as “classic”) and Resource Management. Both models leverage REST APIs for all interfaces. The Azure Portal, Azure PowerShell, Azure command line interface, and other programmatic access to Azure leverage the REST APIs.

Service Management is the deployment model that Azure originally used and is utilized when connecting to It is also used when you develop PowerShell scripts using the Azure PowerShell module. Resource Management is the latest deployment model and is what you use when connecting to It is also used when you create PowerShell scripts using the AzureRM PowerShell modules.

With the rapid development model of Azure, new features and bug fixes are released monthly. The information in this article is based on the Azure PowerShell update 1.02 released in December 2015.

Deployment Requirements for PowerShell Scripts

Before you can deploy virtual machines in an Azure subscription using Azure PowerShell, you need to do the following:

  • Install the latest Azure PowerShell modules
  • Login to an Azure account
  • Select the Azure subscription to target
  • Configure the virtual networks in the Azure subscription

This article assumes that you have already completed these steps prior to running the scripts presented in the following sections.

VM Installation Model

The main difference between the Service Management and Resource Management deployment models for virtual machines is the modularity requirement of ARM. In Service Management, when you create a virtual machine, it automatically creates the virtual machine with a single network adapter, a public IP address, a private IP address connected to a subnet, and associated to a cloud service with a load balancer that has endpoints automatically defined for remote desktop and WinRM connections. Basically, this enables a virtual machine configured with network connectivity and external endpoints.

In ARM, every component is a building block that has to be assembled. Deploying a virtual machine using the ARM APIs requires you to create a virtual machine, a network adapter connected to a subnet with a private IP address, a public IP address, and the public endpoints. Finally, you must assemble these components together as part of the virtual machine deployment.

Of course, there are pros and cons to each model. Service Management does the assembly work for you, but may include components that might not actually be required. In addition, the assembled group of objects is managed as a single object. Resource Management requires you to perform the assembly, but allows for more efficient build block selection. It also allows each building block to be managed separately.

Constructing the Virtual Machine

All objects in the Azure Resource Manager deployment model must be placed in a Resource Group. The New-AzureRMresourceGroup cmdlet, which creates a new resource group, requires two parameters that include the name of the resource group and the Azure region location in which you want to create it. This is typically the first object that you create.

# Create the variable to hold the resource group name
$RGPName= ”VMResourceGroup”

# Create the variable to hold the Azure region
$location= ”West US”

# Create the Resource Group
New-AzureRmResourceGroup -Name $RGPName -Location $location

After this step, any additional building blocks for the virtual can be placed in the same resource group.

A virtual machine is created based on a VHD image that can be selected from existing Azure prebuilt gallery images, or it can be created from a custom image that was uploaded into a storage account in Azure. Regardless of the selected method, a storage account is required to place the VHD(s) for the virtual machine. The storage account needs to be in the same Azure location as the virtual machine is created, so you can use the same variables for the location and the resource group name. You should be aware that storage account names must use all lower case letters and must be composed of only letters and numbers. You also need to specify the type of storage model you will use: Standard_LRS, Standard_GRS, Standard_RAGRS, or Premium_LRS.

# Create the variable to hold the storage account name
$STAName= ”vmstorageaccount”

# Create the variable to hold the type of storage model to use
$STAType= “Standard_GRS”

# Create the storage account and store the reference to a variable
$STA = New-AzureRmStorageAccount -Name $STAName -ResourceGroupName $RGPName –Type $STAType -Location $location

The virtual machine must have a network adapter defined before you create the virtual machine. Network adapters must be attached to a subnet in Azure and then optionally can be assigned a public IP address that is accessible from the Internet. By default, when you attach the network adapter to the subnet, the private IP address is dynamically assigned by the Azure DHCP server. It is possible to assign a static private address to the NIC. That static address is just a free address from the subnet pool of addresses.

In this example, we assign an address from the subnet called Subnet1 and make it a static address. A public IP address is also created and assigned to the network interface. In order to assign the network adapter to the subnet, the resource ID of the subnet is required. You can obtain the resource ID from a query of the virtual network for the defined subnet. Therefore, a reference to the subnet is also obtained.

# Create the variable to hold the name of the NIC

# Create the variable to hold the static IP address that will be assigned to the NIC
$staticIP= “”

# Create the variable to hold the virtual network name
$vNetName= “VirtualNetwork1”

# Create the variable to hold the subnet name
$SubnetName= “Subnet1”

# Get the reference to the vNet that has the subnet being targeted
$vNet = Get-AzureRMVirtualNetwork -ResourceGroupName $RGPName -Name $vNetName

# Get a reference to the Subnet to attach the NIC
$Subnet = $vNet.Subnets | Where-Object {$_.Name -eq $SubnetName}

# Create a public IP address object that can be assigned to the NIC
$pubIP = New-AzureRmPublicIpAddress -Name $NICName -ResourceGroupName $RGPName -Location $location -AllocationMethod Dynamic

#Create the NIC attached to a subnet, with a public facing IP, and a static private IP
$NIC = New-AzureRmNetworkInterface -Name $NICName -ResourceGroupName $RGPName -Location $location -SubnetId $Subnet.Id -PublicIpAddressId $pubIP.Id -PrivateIpAddress $staticIP

Now that the storage account and the network adapter are instantiated, the next step is the creation of the virtual machine. However, before you can actually create the virtual machine, you must specify the configuration information. In order to do this, you first create the configuration object that will store all the configuration information.

# Create the variable that will hold the name of the virtual machine

# Create the variable that will store the size of the VM

# Create the virtual machine configuration object and save a reference to it
$vm = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize

Now that the virtual machine configuration object is created, the configuration information can be assigned to it. This includes defining the operating system, the base gallery image, and the previously created network adapter that you want to assign to the virtual machine. Optionally, you can also specify a name for the operating system VHD. If you do not specify one, Azure will assign a name automatically.

In order to define the gallery image, the publisher, offer, and the SKU for the gallery image is needed. You can refer to the following article to understand how to do determine the available values to use:

For this example, a Windows Server 2012 R2 Datacenter image is specified in the configuration information.

# Create the variable to hold the publisher name
$pubName = ”MicrosoftWindowsServer”

# Create the variable to hold the offer name
$offerName = ”WindowsServer”

# Create the variable to hold the SKU name
$skuName = ”2012-R2-Datacenter”

# Create the variable to hold the OS disk name
$diskName = ”VM1OSDisk”

# Prompt for credentials that will be used for the local admin password for the VM
$cred = Get-Credential -Message “Type the name and password of the local administrator account.”

# Assign the operating system to the VM configuration
$vm = Set-AzureRmVMOperatingSystem -VM $vm -Windows -ComputerName $vmName -Credential $cred -ProvisionVMAgent -EnableAutoUpdate

# Assign the gallery image to the VM configuration
$vm = Set-AzureRmVMSourceImage -VM $vm -PublisherName $pubName -Offer $offerName -Skus $skuName -Version "latest"

# Assign the NIC to the VM configuration
$vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $NIC.Id

# Create the URI to store the OS disk VHD
$OSDiskUri = $STA.PrimaryEndpoints.Blob.ToString() + "vhds/" + $diskName  + ".vhd"

# [optional] Assign the OS Disk name and location to the VM configuration
$vm = Set-AzureRmVMOSDisk -VM $vm -Name $diskName -VhdUri $OSDiskUri -CreateOption fromImage

With the virtual machine configuration defined, the actual virtual machine is created using the New-AzureRMVM cmdlet with the configuration information passed as an argument.

New-AzureRmVM -ResourceGroupName $RGPName -Location $location -VM $vm

You can check the status of the provisioning using Get-AzureRMVM, passing it the resource group and VM name parameters. This retrieves the virtual machine configuration information. When the ProvisioningState value shows “Succeeded”, then the virtual machine creation completed successfully, and the virtual machine should be in the running state.

Get-AzureRmVM -ResourceGroupName $RGPName -Name $vmName


In Part I of this article, you learned how to create and provision an Azure virtual machine using Resource Management APIs and PowerShell cmdlets. In Part II of this article, you will learn how to perform the same steps using Azure Resource Manager templates.

If you would like to read the next part in this article series please go to Deploying Virtual Machines in Azure using Azure Resource Manager - ARM Templates (Part 2).

See Also

The Author — Janique Carbone

Janique Carbone avatar

Janique Carbone has spent the better part of 15+ years in the IT industry, including 7 years at Microsoft as a Senior Consultant and Technical Account Manager.


Featured Links