Pros and Cons of Azure CLI and Arm templates for Deployments

David Robertson
Sep 25 · 5 min read

Cloud infrastructure enables managing infrastructure such as VMs, web servers, etc, in a repeatable, programmatic way, this is known as infrastructure as code.

One of the benefits of infrastructure as code is that you can automate the creation, updates, etc, of different resources/environments, giving only slight changes should need to be changed by human operators. Automating the creating of resources reduces manual changes, accidental mistakes and speeds up the process. Some of the other potential benefits can include:

• Schedule automated deployment — less out of hours work for operations staff

• Automate deployment smoke testing — its deployed are our components working, if not what is not working

• Self-healing on known potential errors

• If cannot be self-fixed, could auto roll to last known good configuration on critical errors

• Can notify on call of failures / or auto — rollback if required

Azure can help you implement infrastructure as code by providing resource deployment automation options; the commonly adopted tool is “Arm templates”, one of the other options is Azure CLI. For the two examples, I’ll be deploying both via Azure DevOps.

The example scenario:

There is a requirement to create an API app on Azure, this API app will receive requests from different client applications for authenticated users (web, mobile, etc). Once this API app has received a request from these clients, it will talk to different systems and collect the data requested (per the user’s permissions) and return that data to the user.

The API has to authenticate to different systems using different credentials (key/value pairs such as username/password and client/secret), we host the API app on an Azure app service and to store the API app credentials in an Azure Key Vault, the API app must be able to request and read values from the key vault which is achieved by giving the Api app a “system assigned identity” and creating a read access policy on the Keyvault for that identity.

For both examples in the Azure DevOps release pipeline each stage/environment will have the following 5 variables:

· apiapp

· appservice

· keyvault

· location

· resourceGroupName

ARM templates example

To deploy these resources to Azure via Azure DevOps using arm templates inside an Azure DevOps release can be achieved using 3 Azure DevOps task, 5 files and library variables (keep in mind we will one this to be repeatable for future environments with minimal differences, ideally only slight name changes for the resources).

The library variables used for this are:

· apiapp = demoapiapparm

· appservice = demoappservicearm

· keyvault = demokeyvaultarm

· location = UK South

· resourceGroupName = demoarm

1. Task one — Azure Resource group deployment, deploy/create the API APP with app service and a system identity then output the system identity (setting the tasks deployment outputs to “armoutputs”

a. File one resource template

b. Parameters file

2. Task two — PowerShell to convert outputted “identity” to a release variable

PowerShell to convert

3. Task three, deploy/create the KeyVault with a read access policy for the API app’s system identity

a. File one resource template

b. Parameters file

Azure CLI example

To deploy these resources to Azure via Azure DevOps using Azure CLI, inside an Azure DevOps release can be achieved using 1 Azure DevOps task, 1 file and library variables. Note, with the Azure CLI, it’s one line of code per resource, however, a lot less of the resource’s properties are defined.

The library variables used for this are:

· apiapp = demoapiappcli

· appservice = demoappservicecli

· keyvault = demokeyvaultcli

· location = UK South

· resourceGroupName = democli

Task one — Azure CLI;

  1. Create the resource group
  2. Create the app service
  3. Create the API app with the above app service
  4. Assign the API app a system identity then
  5. Create the Keyvault
  6. Give the API App access to the Keyvault (get permissions for keys and secrets)


Both are additive/non-destructive, which can allow idempotent deployments however this means changes manually after creation which are not defined by either of these approaches, will not be reset on future deployments (unless the resource is deleted by some other method)

· ARM templates /Azure CLI

· Declarative / Imperative

· JSON(JavaScript object notation) for defining ideal state — easier to read/understand objects and used to define what/Batch/shell for defining implementation — easier to read/understand order of events/logic and define HOW

· Can download template after manual creation of resources / easier understand and implement logic developers are familiar with for code efficiency, such as iterative code (for each loop)

· Potentially lots of lines of code and files / Potentially long lines of code

I started with ARM templates, which are deployed via Azure DevOps using one template file per resource and a parameters file per resource per environment (dev, test, prod) etc.

It ended up for one resource across environments would require many JSON files, you would need to manually change each one for each environment which is counter-intuitive to automation.

I changed the releases to need one parameter file for all environments and remove standard settings for our resources, then using Azure DevOps I used the override template parameters function to supply the environment-specific variables.

Often Azure resources need to work together to give the managed system identity of the app access to the key vault, I took the outputs from the deployment and used PowerShell to set the identity as a variable, then did a new resource deployment task to deploy the key vault giving access to the app.

Azure CLI can use a few simple lines of codes to create your resources and use logic all from one task/script, its easier to read and understand the order,however I soon realized just using Azure CLI does have its downsides when you need to define a lot of properties for your “desired state” of your resources.

Maybe the best of both worlds?

Since my initial experience and time to getting around to write this I have discovered the following article Deploy resources with Resource Manager templates and Azure CLI

To deploy ARM templates using Azure CLI, potentially you can abstractly define objects/resources using arm templates and define your logic/specific implementation of these arm objects/resources using Azure CLI.

For the above example, you could use Azure CLIs “ az group deployment create” providing the template and parameters for your resources, get the system identity and add it to the key vault access policies. The benefit is you can use these in the most advantageous ways.

az group deployment create \

— name ExampleDeployment \

— resource-group ExampleGroup \

— template-file storage.json \

— parameters storageAccountType=Standard_GRS


As with other tools/technology you should use the best tool for the job and although these two different tools can in most cases be used to start your infrastructure as code journey, if used together appropriately can make that goal a lot easier to achieve.

Join the Capgemini Microsoft team, open roles here.

Capgemini Microsoft team

To share best practices, knowledge and experiences of the Capgemini Microsoft team

David Robertson

Written by

Capgemini Microsoft team

To share best practices, knowledge and experiences of the Capgemini Microsoft team

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade