1. Home
  2. Training Library
  3. Microsoft Azure
  4. Courses
  5. Introduction to Azure Resource Manager

Demo: Azure JSON Template Authoring

Start course
Duration1h 30m


During this video demonstration, we will take an existing Azure Resource Manager (ARM) JSON template, and go through, at a granular level, the different pieces that make it up. Although we won't be making any major changes to the template, it is helpful to understand the bits and pieces that make up a more complex template. This ARM JSON Template will contain resource definitions for a Virtual Network, Storage Account, two (2) Virtual Machines in an Availability Set, a Load Balancer, and the other supporting components, such as Network Interfaces.


Okay, so in this example, we've actually got a template that we can use. So I'm going to come out to the Azure Quickstart templates page and search for "load balancers." Now, if we go down far enough, you'll see that there's some more advance templates that already include load balancers and virtual machines. So, this particular template is called 2 VMs with Internal Load Balancer. So it's going to create two virtual machines, and Internal Load Balancer and it's going to have the load balancing rules pre-created for the virtual machines. So let's go ahead and inspect this a little bit more closely. I'm going to click on the AzureDeploy.json file which gives us the raw template. I'm going to go ahead and copy and paste the contents into my editor called Atom. So inside the Atom editor, I'm going to hit Control Shift P on my Windows keyboard, and that brings up the command palette. So I can change the grammar for this file over to JSON. Okay, so now I've got this template file that contains a Load Balancer, two virtual machines, and all of the supporting resources such as network interfaces and storage accounts for the architecture that we want. So I went ahead and collapsed the parameters section here and the variables section because, for the time being, we want to focus on the architecture of the resources themselves. So under the resources section here, you can see that we've got a storage account. The storage account has a name which is coming from an input parameter and it has an account type such as locally redundant storage or geo-redundant storage that comes from a variable. So, if we open up our parameters, and scroll down a little bit here, you can see that we have a storage account name. So that storage account name is the one that's going to get created when we actually deploy this template. So, let's go ahead and collapse the storage account. And next, we have an availability set. The availability set name is coming from a variable. And the variable's simply called "Availability Set Name." So the Availability Set Name is AV set. Okay, next we have a virtual network. So the virtual network's name is going to come from the input parameters to this template and the address space is actually hard coded into the template here under the address space property. We also have to subdivide that address space into subnets. So you can see that we have a single subnet here, and the subnet's name is actually coming from a variable, and the address prefix is hard coded into the template. So we have next a network interface. And the network interface is defined a little bit differently than the other resources. In this case, we actually need two different network interfaces for each of the virtual machines that we're deploying in this template. So, one of the special things you're going to see about this resource definition is the copy property. So the copy property allows us to basically take this entire resource for a network interface, and make multiple instances of it. How many instances are we going to create? Well, that's defined in the count property, and as you can see, we're referencing a variable called number of instances that determines how many network interfaces to create. And, under the variables section here, you can see that the number of instances variable is set to two. So, we're going to get two network interfaces out of this. And the name of each network interface has to be unique. And the way that we make it unique is by using a special function called copyindex which is the current iteration of the copy loop that we defined in the copy property. So, basically the network interface name is coming from a parameter. So as you can see, we've got an input parameter called network interface name. And it's going to be concatenated along with the copyindex. So whatever value we specify for the input parameter network interface name, let's just call it NIC right now, so we'd have NIC one, and the next time it loops we'd have NIC two. So, inside the network interface configuration, we are also allocating a private IP address dynamically on the virtual network. We're also associating that network interface with the back-end address pool for the load balancer. And the address pool for the back-end to load balancer essentially allows us to define which network interfaces belong to the virtual machines that we're going to put the load balancer in front of. Next, we have the load balancer itself. So, the name of the load balancer is going to come from an input parameter. We also have a dependency on the virtual network. So the virtual network will have to get created first, and then we can deploy the load balancer into that virtual network. We have the front-end IP configuration, which is going to have a private IP address because remember, that this is an internal load balancer, not an external load balancer. So the virtual machines will be load balanced behind this address of That's what the application will be exposed through. And you can see that in this case, we're actually assigning a static address to this load balancer to ensure that its IP doesn't change. We also define the back-end address pool, here. And all we do is specify the back-end address pool's name. The network interfaces themselves actually define the association to this back-end address pool. Next, we have the load balancing rules. So, the front-end IP configuration is defined here as a reference to the front-end IP configuration that's defined on the load balancer itself. The same thing with the back-end address pool. And then finally, we configure a probe. So the load balancer probe allows us to ensure the availability of that application or service on each of the virtual machines that's behind the load balancer. So, the front-end IP configuration, the back-end address pool, and the probe are all references to the front-end IP configuration, the back-end address pool, and finally, the probe that is defined on the load balancer down here. After we've defined the load balancer, let's go ahead and collapse that, the next resource that we define is the virtual machines themselves. So the virtual machines, much like the network interfaces, have the copy property defined on them so that we will actually get more than one instance of a virtual machine. So as you can see, the name of the loop itself is called virtualMachineLoop, and the count is that same number of instances variable which we looked earlier and we found out is set to two. So the virtual machine has several dependencies. And first of all, we have the dependency on the storage account. Next, we have a dependency on the network interfaces. So the network interfaces will get provisioned before the virtual machines. And then finally, we have the availability set. So the availability set will need to be provisioned by the resource manager API before we can actually put the virtual machines into that availability set. Under the properties of the virtual machine, we have quite an array of options. So first, we have the availability set, and we're basically referencing the availability set that we created earlier in the template. Next, we have the hardware profile which allows us to define the size of the virtual machine, so how many CPU cores and how much memory the VM has. And that's coming from an input parameter, as you can see. Next, we have the operating system profile which allows us to define the computer's name, the admin username and password that will log in to the VM after it's been provisioned. Next, we have the storage profile, and the storage profile allows us to create the operating system disk and deploy the operating system from an image in the image gallery. So we have an image reference that allows us to specify the metadata to pull the appropriate image. So first, we need to specify the publisher, the offer, the SKU, and then finally, the version. And most of those are coming from input parameters on the template itself. We also have the OS disk property which allows us to configure the operating system's VHD file inside of blob storage. So as you can see, we're actually building the path to the blob dynamically using the ARM template concat function. We're referencing a parameter which is the storage account name we're going to create. And then we're also using the copy index to insure that we have a unique VHD name for each virtual machine that's in the copy property. We also specify the caching mechanism so we're going to use ReadWrite caching and we're also telling it that we want to create the operating system disk from an image in the gallery, rather than an existing VHD that we have in a storage account. Next, we have the network profile, and the network profile simply allows us to bind the network interface that we defined earlier to each virtual machine. And because we created more than one network interface, we have to make sure that each VM gets the appropriate NIC. And we do that by using the copy index function to grab the current iteration such as one or two of the virtual machine. The last property we have here is called the diagnostics profile. And as you can see, we've configured boot diagnostics for this virtual machine. Actually, it's going to be multiple virtual machine instances. And you can see that we're putting the boot diagnostics directly into a storage account that's referenced by a parameter. So, now that we've talked through this entire template, let's go ahead and actually deploy it. Okay, so the first thing we need to do in order to deploy this template is to save it to a file. Let's save it to C:\CloudAcademy\AzureDeploy.json Great. So, now we've saved that file to disk. Now, we're going to switch over to the Powershell ISE and we're going to call the New-AzureRmResourceGroup command to create a new resource group. We're going to call the resource group CloudAcademyLoadBalancer. And we're going to create that resource group in the West US region. So, let's go ahead and run that command by hitting the F8 key in the Powershell ISE. And then the next command we're going to run is called New-AzureRmResourceGroupDeployment. So we're going to specify the resource group that we want to deploy to, which is CloudAcademyLoadBalancer. We're going to specify the mode, which is actually going to be incremental in this case. We're going to specify the template file which we saved under C:\CloudAcademy\AzureDeploy.json. And then finally, we need to specify all of the properties or input parameters for that template. So as you can see, Powershell is actually dynamically prompting us for parameters because it was able to read in the template from the AzureDeploy.json file. But instead, what we're going to do is we're actually going to create a hash table of parameters and then we'll pass that in instead. So let's go ahead and switch back over to our template here. We're going to open up the parameters section. And we'll just go ahead and collapse most of these. As you can see, some of these parameters actually have a default value assigned to them, so we don't have to specify those parameters. So VM name, prefix, image offer, image SKU, VM storage account container name, VM name, storage account name, and the VM size is actually built in as well. So, all the properties that I've collapsed are the ones that we need to specify. So, let's start by specifying virtual network name. So we'll call that vnetLB. Next we need to specify the network interface name. And we'll just call that nic. Next, we need to specify the load balancer name, and we'll call that CloudAcademyLB. Next, we need to specify the admin user name, which we'll call CloudAcademy. And then finally, the admin password for the user account. And then, we also need to specify...all of these have built in the next one we need to specify is actually going to be VM name. And we'll just call that cloudac. And that'll be appended by a one or two. And then finally, we have the storage account name. So the storage account name we'll set to cloudacademyLB. Okay, so now I've defined our input template parameters, let's go ahead and try to deploy this. So actually, I need to also add the template parameter object parameter and pass in my template params. Okay, so now if I hit that F8 key, we'll go ahead and create a new deployment. While that's deploying in the background, let's go ahead and switch over to the Microsoft Azure Portal and monitor the success of that deployment. So I'm going to go at And the first thing that I'm going to do is go to resource groups. So I've already created the resource group called CloudAcademyLoad Balancer. That was the first step we went through. And as you can see, the load balancer template is now in the deploying state. And you can see under the resources section here which resources have actually been provisioned. So far, the availability set, the load balancer, which is dependent on the virtual network, and the storage account have all been provisioned. If we click on the status here, we can go over to Azure Deploy, which is the actual deployment object inside the resource group. And if we scroll down towards the bottom, we can actually see a better breakdown of all the individual resources that have been provisioned. So, our two network interfaces have been provisioned, the load balancer, the virtual network, the storage account, and the availability set. The two remaining tasks for the Azure Resource Manager API are to deploy the back-end VM number one, and the backend VM number two. So this template will take a few minutes to deploy and after a few minutes, the virtual machines will be up and running and ready to go. Once we're completed with this template, we can go ahead and call Remove-AzureRmRecourceGroup specify the name, which is CloudAcademyLoadBalancer. And then specify the force parameter to prevent it from prompting us. So that's all there is to the Load Balancer Azure Resource Manager JSON Template.

About the Author

Trevor Sullivan is a Microsoft MVP for Windows PowerShell, and enjoys working with cloud and automation technologies. As a strong, vocal veteran of the Microsoft-centric IT field since 2004, Trevor has developed open source projects, provided significant amounts of product feedback, authored a large variety of training resources, and presented at IT functions including worldwide user groups and conferences.