adaptive.run TECH BLOG

Cloud can be tricky sometimes. Find out what scenarios we've ran into that are worth being mentioned and explained.

Infrastructure as Code and Post Deployment Configurations

Level: 400
Publishing date: 07-Feb-2020
Author: Catalin Popa

If you already have a good level of Azure and successfully delivered a few projects, you might know by now that most of the infrastructure deployments or configurations of services/features in Azure are done through Infrastructure as Code.

No matter if it's Azure ARM Templates, Terraform or newer ways of Infrastructure-as-Code (as Pulumi), this is the efficient way of deploying/migrating/managing large cloud environments.

Today's post will focus on ARM templates, but keep in mind that Infra-as-Code can be achieved with any tool/language designed to have the same scope.

First of all, let's answer to the most important question - What is Infrastructure as Code?
In short, Infrastructure as code (IaC) is the process of managing and provisioning infrastructure in computer data centers through machine-readable definition files.

Basically, all the things that you ever created/deployed/configured/managed in Azure are translated into code, at some point. Azure's native way of doing this is through ARM templates, which basically are JSON files that define the infrastructure.

Now you probably wonder why should we make deployments through ARM templates, when making a few clicks in the portal is easier. Well, the top benefits of ARM templates, in my opinion, are the following:

1) Saves time for big deployments. 
Imagine deploying 100 VMs from the portal for a new project and doing the same repetitive process. Wouldn't it be easier to just create an ARM template with a function that will create all these VMs?

2) Can be automated.
Creating a solution and automating it to be deployed by ARM templates means that you can then create an exact replica (or modify that existing environment) by just editing a JSON file. Way simpler than starting again from scratch, right?

3) Can be integrated with other processes.
"DevOps" can actually be "DevOps" - having a pipeline to create and configure the infrastructure and then linking other pipelines to directly deploy the artifacts of your applications/databases into the infrastructure can enable you to have a "One-Click-Deployment environment".


If you ever felt curious in Azure and accessed the "Export template" blade of a resource, you would have seen the ARM template that was used for the resource. No matter if you deploy/configure things through the portal, through Azure CLI or through Azure PowerShell, all these ways of deployment/configuration are just frontends to send requests to the main Azure Resources API. Of course, you can also deploy/configure things by making requests directly on the API.

Don't take my word for it? Then access https://resources.azure.com - here you'll see the Azure Resources API and you'll be able to drop-down through the ARM templates that are currently in use for your Azure environment - all the way from subscription level to single resources/sub-resources. 

Regarding ARM templates, as previously said, they follow a JSON structure. The simplest structure looks like this:

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

Not all elements are required to be defined. You can find out more about the structure and syntax of ARM templates by accessing this official Microsoft documentation.

Also, if you feel uncomfortable to yet create an ARM template from scratch, you can start by using the templates that Microsoft posted on GitHub. These templates address various scenarios/deployments and if you need to deploy some common scenarios, you might find here directly the ARM template that you need. However, I can guarantee that big deployments and big configurations will require creation/configuration from your side on the ARM templates, so you better have good dev skills.

After you have your desired ARM template, you'll probably wonder how you can deploy it. The two most common ways of deploying an ARM template are:

1) Through a PowerShell command/script.
Usually this script is also used to configure to overwrite the parameters of the ARM template with your desired parameters. But the specific command that deploys an ARM template to Azure is New-AzResourceGroupDeployment. To this command various parameters can be pushed, the most common ones being Mode of deployment (Incremental/Complete), the Resource Group in which you want to deploy, the path of the Template File that you want to deploy and the Parameter Objects that you want to push to overwrite as parameters.

I'll just give you an example:

New-AzResourceGroupDeployment -ResourceGroupName "my-resourcegroup" -Mode Incremental -TemplateFile "C:\Folder\armtemplate.json" -TemplateParameterObject $parameters

(where $parameters is an array of parameters defined in PowerShell).

2) Through a CI/CD Pipeline (Azure DevOps)

Azure DevOps provides various ways on how you can do this. Either doing it by YAML or by the classic editor, you will be able to do this.
If you are doing it through the classic editor, just look for the Azure Deployment task:


Now, in terms post-deployment configurations on the Azure Services that you deploy with ARM templates, it really depends on which type of service you are aiming:

1) If you need post-deployment configurations for PaaS services like App Services, you can easily create CI/CD for your applications. The most common way of doing it is through Azure DevOps and GitHub, but and CI/CD tool can be used. 
Just imagine - having an ARM template to create 10 WebApps in Azure and then pipelines to deploy the application files in that infrastructure just created.

2) Databases can be populated/configured the same way as in step 1). Either pipelines from a CI/CD tool or automating integration/migration tools from Azure (like Data Factory), you can have it all in just one complete process.

3) When it comes to post-deployment configurations on Virtual Machines, there are actually multiple possibilities of doing it. I am going to share with you two ways of executing a PowerShell script into an Azure VM:

a) Directly from the ARM template, by just mentioning a CustomScriptExtension or a DSC extension on the ARM template of the VM:

        "resources": [
      { 
            "type": "extensions",
            "name": "CustomScriptExtension",
            "apiVersion": "2017-03-30",
            "location": "[parameters('location')]",
            "dependsOn": [
              "[concat('Microsoft.Compute/virtualMachines/', parameters('vmname1'))]",
            ],
            "properties": {
              "publisher": "Microsoft.Compute",
              "type": "CustomScriptExtension",
              "typeHandlerVersion": "1.8",
              "autoUpgradeMinorVersion": true,
              "settings": {
                "fileUris": [
                  "https://depscripts.blob.core.windows.net/code/setupVM.ps1"
                ],
                "commandToExecute": "[concat('powershell -ExecutionPolicy Unrestricted -File setupVM.ps1 -domainname ', parameters('domainname'), ' -biosname ', parameters('netbiosname'), ' -adminname ', parameters('adminUsername'), ' -adminpwd ', parameters('adminPassword'))]"
              }
            }
          }
        ]


The above bit of ARM template creates a CustomScriptExtension on the VM that I will be creating (vmname1), executing a PowerShell script (located at that specific fileURI) with that specific command to execute (commandToExecute).

Basically, that PowerShell script will be executed once my Virtual Machine will be deployed and running in Azure.

b) From PowerShell, with the following command:

Invoke-AzVMRunCommand -ResourceGroupName "my-resourcegroup" -VMName 'vmname1' -CommandId 'RunPowerShellScript' -ScriptPath 'setupVM.ps1' -Parameter @{parameter1inScript = $parameterToPush }

Notice how these post-deployment configuration scrips can also be overwritten with parameters that you can (and probably will) retrieve from previous automation steps.


By using these tools we have the possiblity of creating complex automation procedures in any cloud environment, regardless if it is for deployment, configuration or management.

adaptive.run

Transform your business.
Run adaptive.

Contact

Phone: +40 72 444 3842
Email: hello@adaptive.run

© Copyright  2019-2024 adaptive.run- All Rights Reserved