First of all, this is a 50,000 foot view of both solutions with some key considerations to tempt fate and interest for further investigation. Now secondly, in the context of deploying IaaS Virtual Machine instances in Azure (note that my example in this blog is the deployment of said IaaS VMs with Azure DevOps #ShipIt) I wanted to go over using ARM Template Customer Script Extension vs PowerShell Desired State Configuration (via Azure Automation ASC). This is a precursor blog post to another on ATM Custom Script Extensions. I thought it worthwhile to get some thoughts on this out to finalise some design decisions I’ve recently made for a customer.
The two solutions can basically do the same thing, but fundamentally they are quite opposed in how they go about doing that. In addition, Desired State Configuration has a bigger arsenal up it sleaves when it comes to functionality to maintain a virtual machines specific state.
So, I’m not exactly talking immutable machines here which is by far the preferred option when it comes to cloud IaaS infrastructure. Let me get that view point out there to align myself with the cool kids. This is more in the context of getting a VM ready for consumption by downstream application teams.
So in this example I need to deploy some IaaS infrastructure with Azure DevOps Release Pipelines; the classic deployment model there. No YAML, all GUI, but all good; no really! For me, that pattern works well. But when it comes to deployment of Azure resources by way of Azure Resource Manager Templates- there’s an important decision to make around post deployment instance configuration.
Immediately after a VM is created with an ARM Template, you can call a module either in the main VM deployment module of “Microsoft.Compute/virtualMachines”, or after the VM is created, but immediately following in a “Microsoft.Resources/deployments” module. A Custom Script Extension (that’s a “type”: “CustomScriptExtension” on Windows and a “type”: “CustomScript” on Linux) downloads one or several scripts from your favourite source control (#GitHub) or public cloud repo (#AzureBlobStorage) and executes said script(s) on the VM. You can get down and dirty with whatever examples you sit fit here, but for the most part this immediate pattern is good for post deployment configuration (like domain join, setting specific permissions/access to the VM, or software deployment of some flavour). So important information around CSE’s:
There’s other good points in the Microsoft documentation on this available here.
On the spectrum of simple and fast, with CSE being on that end, Desired State Configuration is towards the opposite end. By that I mean a correct implementation of DSC takes more hours to design and implement in the correct way.
Where CSE’s provide some quick functionality in an ARM template to download and execute a script on a IaaS VM after creation, DSC can be used in Continuous Integration/Continuous Deployment pipelines (#BuzzWords) to maintain state. With this greater functionality comes the requirement to deploy additional infrastructure to run and maintain that DSC. With Azure, Automation State Configuration (ASC) can do that heavy lifting from a single service point of view. So important considerations and information on DSC is as follows:
Quick, easy, dirty, icky…. err yep; Custom Script Extensions. Why!!!???
For the specific use case the customer had, only a specific post deployment pattern needed to be run on VM instances. The overall pipeline was very much mutable, and apps deployed by app teams needed an environment to transition from legacy on-premises data centres. The AzDo deployment requirements and the initial state of the VM instance was that of getting them ready for consumption. Additional tooling after the fact would take care of the state. That tooling may very well have been Desired State Configuration or an equivalent solution. For me… out of scope, so I’m not 100% sure.
In a follow up blog to this I’ll go into a pattern on how to execute multiple scripts within an ARM Template for both Windows and Linux. I know in my use case Azure DevOps can be leveraged to do that with multiple ARM templates run across different Tasks in a specific Stage. That all seemed like the easy road. I took the hard road which eventually worked out quite well.