June 12, 2022

Harness Infrastructure Provisioners and ARM Templates - Part 2

Table of Contents

In the first part of this series, we learned how to deploy ARM templates using Harness provisioners. We also learned the basics of Azure ARM, and we covered how Harness services communicate with each other when you deploy ARM templates. I will recommend you get a refresher on this info by reading the first blog


In this second and final part of the series, we will learn how you can use Harness variables to templatize your ARM templates and how Harness provides rollback, which Azure does not.

Harness Variables in ARM Templates

Let's say we want to create a different Azure web app for different microservices, such as Order Service, Payment Service, User Service, etc. We can have one ARM template and the name of the web app can be defined as a parameter.

ARM template web app creation section:

{
      "apiVersion": "2016-08-01",
      "type": "Microsoft.Web/sites",
      "name": "[parameters('siteName')]",
      "location": "[resourceGroup().location]",
      "properties": {
        "siteConfig": {
          "name": "[parameters('siteName')]",
          "appSettings": [
            {
              "name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE",
              "value": "false"
            }
          ],
          "linuxFxVersion": "DOCKER|nginx:alpine"
        },
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]"
      ]
    }


As you can see, the name is defined as "name": "[parameters('siteName')]"

The parameter file will look something like this:

parameter file

Now, for each microservice, we need these parameters files:

microservice parameter files


Imagine having 30-50 microservices: you would need to maintain all these files, which could easily become a maintainability issue. It’s simply not scalable.

By using Harness variables, you could reduce this burden into only one parameter file. Users can leverage Harness in-built variables like Service, Environment, Secret, and Workflow in their ARM templates. Check out our official documentation on built-in variables for more details.

Harness resolves all these variables before it sends a request for ARM deployment to the Delegate. This is a powerful tool provided by Harness to templatize your ARM templates on top of ARM parameters.

You can also define the parameters in the parameter file as workflow variables, and while deploying, you can provide their value as OrderService, PaymentService, etc.

define parameters as workflow variables


During deployment, you can provide the value of these variables. You can create a pipeline with as many stages as you have microservices to deploy, and you can use the same workflows and provide different runtime values.

Stage 1 for PaymentService-webapp:

payment service webapp stage 1

Stage 2 for OrderService-webapp:

OrderService webapp


On the Azure portal, you will be able to see different web apps have been created using the same ARM templates & parameter files.

How Does Harness Provide Rollback Support for ARM Deployments?

During ARM deployments, we need to handle failures for the following scenarios:

  • If something fails while downloading ARM templates from Git.
  • If something fails while processing ARM templates.
  • If something fails on the Azure side after an ARM deployment has started.

For points one and two, we don’t need to do anything as the deployment has not yet started. For point three, Harness performs a rollback. Let’s dig into how. 

Imagine you have a Resource Group (let’s call it RG1) with two resources, R1 and R2. Let's say you’re trying to deploy additional resources (R3, R4) in incremental mode using ARM templates in RG1. R3 was created successfully, but while creating R4, something went wrong. Ideally, you’d be able to go back to the previous state (in this case, having only two resources: R1 and R2). However, Azure leaves your deployment as is instead of rolling back. You’d now have R1, R2, and R3 in RG1. This is because Azure doesn’t natively support rollbacks. 


Azure ARM deployment



Harness has overcome Azure’s limitations by saving the current state of the Resource Group before making any changes to the existing infrastructure. During rollback, the existing template is deployed in COMPLETE mode, which ensures that only the resources mentioned in the template will be deployed. For example, anything new that was deployed will be deleted.

Here’s a diagram of what happens before you start an ARM deployment:

Harness ARM deployment


  • The Manager service sends a request to start the ARM deployment.
  • The Delegate sends a request to Azure to generate the template for the existing Resource Group. 
  • Azure sends the ARM template to the Delegate.
  • The Delegate forwards the JSON response to the Manager.
  • The Manager saves the ARM template to MongoDB.
Harness ARM rollback flow


If something fails during an ARM Deployment:

  • The Manager sends a query to get the JSON template saved before execution starts.
  • The Manager gets the existing template using the current execution ID.
  • The Manager sends the new ARM deployment task to the Delegate.
  • The Delegate runs a new deployment using the existing ARM template in COMPLETE mode.
  • The Delegate polls for the deployment status.
  • Periodically, the deployment status is received from the Delegate and shown on the UI.

Conclusion

This concludes our blog series on Harness Infrastructure Provisioners and ARM Templates.

In this post, we learned about using Harness variables inside ARM templates, and how Harness provides rollback support.

To learn the basics, please feel free to refer back to the first blog of the series. Interested in learning more? Schedule your demo today

You might also like
No items found.

Similar Blogs

No items found.
Continuous Delivery & GitOps