Wednesday, June 1, 2016

Best Practices for Creating Azure Resource Manager Templates- Part I

Azure Resource Manager (ARM) is the new set of APIs for deploying and managing Microsoft Azure services, From Microsoft point of view they are terming this as revolutionized way of resource management.

AWS has had this capability for quite sometimes, they have named it as CloudFormation. While ARM Templates and CloudFormation are quite identical in their behavior and are trying to achieve similar goals, under the hood there are some basic differences which is beyond the context of this article.

Though Microsoft has got a large repository of ARM Quick Start Templates which is accessible here... yet being a new service overall documentation of ARM is still evolving. At times it's difficult to find samples sufficing your custom requirements, if you are caught into that space there are few tips which definitely would help you.Under this article i will outline few important considerations while authoring your own ARM Template-

1. Best Authoring Tool For ARM Template :Visual Studio 2015


The ability to author and manage ARM Templates within Visual Studio 2015 is contained within the “Azure Resource Group” project template. This integration of ARM template and VS2015 has given developers a sense of belonging towards solution-oriented templates. Here with this they can visualize the resources and parameters using JSON outline. With Visual Studio you can add resources easily, make great inbuilt IntelliSense and validation of Visual Studio JSON editor. It also offers support for wizard based deployment, as part of best practices you can integrate your artifacts and deployment templates with source control.

2. A tool for assistance:Azure Resource Explorer


This is an essential tool for anybody writing ARM templates. It can be a great way to understand the resource hierarchy and find where to put configuration. You can deploy a resource using the portal and use the resource explorer to see the JSON schema for the resource you just created you can make a change in the Portal and then find the corresponding entries in Resource Explorer and include it to your template! That way it can help you figure out the settings for your templates. https://resources.azure.com/

3. Version your Azure Resource Manager Templates


ContentVersion is a required element of ARM Template structure. This specifies Version of the template (such as 1.0.0.0). You can provide any value for this element. When deploying resources using the template, this value can be used to make sure that the right template is being used. Another benefit is it makes template artifact-able with version control.
{
  "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
   "contentVersion": "",
   "parameters": {  },
   "variables": {  },
   "resources": [  ],
   "outputs": {  }
}
4. Use Latest version of the resource provider API

{
   "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
   "contentVersion": "",
   "parameters": {  },
   "variables": {  },
   "resources": [  ],
   "outputs": {  }
}

Location of the JSON schema file that describes the version of the template language. This will pull in the proper version of all the child schemas. to get the latest Api Version for the resource providers you’re going to use keep checking this 
Always try to use the updated Schema. But in general you should be able to stick with the top level schema.
5. Use Input Parameters

Under this section specify values you can input while deploying the resources. These parameter values enable you to customize the deployment by providing values that are tailored for a particular environment, Site Name , Region etc.. To our benefit this makes the While template configurable and maintainable.

"parameters": {
   "siteName": {
      "type": "string",
      "minLength": 2,
      "maxLength": 60
   },
   "siteLocation": {
      "type": "string",
      "minLength": 2
   },
   "hostingPlanName": {
      "type": "string"
   },  
   "hostingPlanSku": {
      "type": "string",
      "allowedValues": [
        "Free",
        "Shared",
        "Basic",
        "Standard",
        "Premium"
      ],
      "defaultValue": "Free"
   },
   "instancesCount": {
      "type": "int",
      "maxValue": 10
   }
   
}
For region Mapping always go with Drop-down,that can be achieved by specifying values in allowed value section..   
6. Work With Variables

Variables in ARM template can be used to simplify the template.Under this section we construct values that can be used throughout our template. Cases where same thing (ie Connection String) has to used multiple places it's not worthy repeating the same string again & again.Any sort of human errors will result in failure during the deployment. Instead, we can assign these things as a value to a variable and refer that variable within the template as needed. Also, variables in ARM template language will let us expand or construct other variable values.

"variables": {
   "connectionString": "[concat('Name=', parameters('username'), ';Password=', parameters('password'))]"
}

7. Decompose The Larger Deployment– Using Linked Templates

As part of ARM Template best practice considerations It's recommended to separate your template into multiple templates,if applicable, into multiple target-specific templates. Think of this as creating re-usable code. You can leverage the re-usable parts of your code within multiple aspects of your application or the deployment.

Template linking enables you to link to and execute another template,It enables you to decompose your deployment into a set of targeted, purpose-specific templates. Just as with decomposing an application into a number of code classes, decomposition provides benefits in terms of testing, re-use, and readability.


You create a link between two templates by adding a deployment resource within the main template that points to the linked template. You set the templateLink property to the URI of the linked template.

"resources": [ 
  { 
     "apiVersion": "2015-01-01", 
     "name": "nestedTemplate", 
     "type": "Microsoft.Resources/deployments", 
     "properties": { 
       "mode": "incremental", 
       "templateLink": {
          "uri": "https://www.contoso.com/AzureTemplates/newStorageAccount.json",
          "contentVersion": "1.0.0.0"
       }, 
       "parameters": { 
          "StorageAccountName":{"value": "[parameters('StorageAccountName')]"} 
       } 
     } 
  } 
] 

It's also takes care of any limit imposed by Microsoft from Template size prospective...
8. Deploying multiple instances of resources: Use copy Object

you’ll want to deploy multiple instances of a given resource,For example- multiple web servers or your Hadoop cluster might have multiple data nodes.Within the resource to create the same multiple times, you can define a copy object that specifies the number of times to iterate.
You can use the copyIndex() function in a template to provide details about the current index of the loop being executed(Current Iteration).

"parameters": { 
  "count": { 
    "type": "int", 
    "defaultValue": 3 
  } 
}, 
"resources": [ 
  { 
      "name": "[concat('examplecopy-', copyIndex())]", 
      "type": "Microsoft.Web/sites", 
      "location": "East US", 
      "apiVersion": "2015-08-01",
      "copy": { 
         "name": "websitescopy", 
         "count": "[parameters('count')]" 
      }, 
      "properties": {
          "serverFarmId": "hostingPlanName"
      }
  } 
]
9. Defining Resource Dependencies:Use DependsOn

For a given resource, there can be other resources that must exist before the resource is deployed. For an Example- Say for a given VM, you may be dependent on having a database resource successfully provisioned.You define this relationship by marking one resource as dependent on the other resource. You can define dependencies on other resources using dependsOn and resources property of a resource. A dependency can also be specified using the reference function.

{
  "type": "Microsoft.Compute/virtualMachineScaleSets",
  "name": "[variables('namingInfix')]",
  "location": "[variables('location')]",
  "apiVersion": "2016-03-30",
  "tags": {
    "displayName": "VMScaleSet"
  },
  "dependsOn": [
    "storageLoop",
    "[concat('Microsoft.Network/loadBalancers/', variables('loadBalancerName'))]",
    "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
  ],
  ...
}

Above example shows a virtual machine scale set that is dependent on a load balancer, virtual network, and a loop that creates multiple storage accounts.


10. Define Api Versions for different Resource Providers as variables instead of parameters, Much easier to find and replace.

Related Articles : Best Practice For Creating ARM Template

3 comments:

  1. your blog look nice and informative which I found on internet.thank you for your post .
    Devops Online Training banglore

    ReplyDelete
  2. Very good Article for beginners...Easy to understand

    ReplyDelete
  3. • Nice and good article. It is very useful for me to learn and understand easily. Thanks for sharing your valuable information and time. Please keep updatingAzure Online Training

    ReplyDelete