Azure Template to deploy a forest with two domains, Part 3 -- visualizing the template

This is part 3 in a series about writing a complex Azure AMR template. This is the full list:

In the final part of this series I want to have a brief look at the template design, and in particular at the dependency part. I'm talking about the dependsOn element in an example like this:

[javascript]
{
"parameters": {},
"variables": {},
"resources": [
{
"name": "[parameters('vmName')]",
"type": "Microsoft.Compute/virtualMachines",
"dependsOn": [
"[resourceId('Microsoft.Network/networkInterfaces',variables('vmNicName'))]"
],
"properties": {
[...]
]
}
],
}
[/javascript]

It says that the deployment of this resource (a virtualMachine) can only be started after the resources listed in the dependsOn element have finished successfully. In this case, it says that a particular networkInterface must exist.

This is simple enough. But the template we are talking about in this series (here it is again) has a lot of dependencies that tripped me up more than once. So I tried to come up with a way of visualizing the dependencies of an ARM deployment. First I tried the web-based visualizer at armviz.io, but this has not been working for me lately. Either the site would not load, or the drawing would not complete. So I came up with the following simple scheme. This example shows the dependencies in an ARM VM, with the assumption that a VNET and storage group already exist.

 

dependency-drawing-forest-2-domains-for-blogpost

The black arrows are the dependencies; read them as "depends on". From the point of view of the VM, the VM can only be created when the NIC is created, which in turn can only be made when the Public IP address is done. Once the VM is done, we can inject some Powershell DSC into it. The time flows contrary to the dependencies, of course. Note the color coding of the blocks. The green ones actually create something in Azure, while the blue ones do something to an existing object like a VM.

Coming to the point, the following diagram is the dependency diagram to create the full forest with two domains, with two DCs each. It is still hiding some complexities from child templates, but let's accept that for now. You will note that the deployment of VMs in a child template deployment, the one seen above.

dependency-drawing-forest-2-domains-for-blogpost-main-template

 

From the top down, we see the basic building blocks deployed first: the VNET, a storage account, and availability groups for the VMs. Each VM takes a dependency on each of them, three in total. All three must be finished deploying before the VM can start. But, once the VMs can start deploying, they can deploy all at the same time which is a big plus: 4 time-consuming deployments that do not depend on each other. Simultaneously, the network continues to configure itself by adding a Network Security Group and adding this NSG to the subnet. There is no dependency on the VMs at this time.

The first real action after the VMs are created, is to build the forest in the first VM using Powershell DSC. Clearly the "create forest" action must wait on VM1 to finish, but nothing else. Once the forest is there, the child domain can be created, if its VM3 has finished deploying. That was one of my initial mistakes; I had forgotten the dependency of "create child" on VM3. 90% of the time this would be fine, but sometimes it would just fail because the VM was not ready to process the required Powershell DSC. With a diagram like this it's easy to see, but mistakes like these are not so obvious if  you can only stare at code ...

After the child domain is live, the forest as a logical entity is complete. Additional DCs can be added, and the DNS references on the VNET should be finalized. With these DNS settings in place, you can add any VM you like to the VNET and it will get DNS references ready to join it to the domain.

I have mentioned this in my previous post, but the action "add DC to root" for VM2 depends on the child domain and not on the root domain as you might expect. The problem is not the promotion of VM2 itself. You can definitely do that before you add the child domain. The problem is with adding the child domain on VM3. Initially, I created the template to build the root domain in VM1, and then to deploy VM2 (additional DC in root) and VM3 (first DC of child) at the same time. But then something nasty can happen, sometimes. When VM1 is ready, but VM2 is not quite ready, it can happen that VM3 (child) uses VM2 for DNS which remains non-responding during initial sync after promotion. This breaks the promotion of VM3. When I finally finished troubleshooting that, I decided to change the order of the actions to complete building the forest first, and the template has been stable after that.

So now you know what's in the template and why, feel free to fork it on GitHub, copy it, or to just use it as a child template from your own. If you want to link to the template directly, use the "1.0-stable" branch that I use for maintaining the initial release. It will not change except for possible bugfixes.