Sam's Space

Starting With Azure Bicep

In the hope of building out a demo and test environment to play around with Azure services, I wanted to build out an means of spinning up and down services as-needed without rebuilding the whole service each time. While I’ve worked in the past with Terraform I thought it would be a good opportunity to see what other IaC tooling can do and the tradeoffs.

The plan

To have a usable demo service, I wanted to include a few components. From an infrastructure perspective, a virtual machine scale set, NAT gateway, some form of load balancer and basic security policies to block traffic the minimum viable product. In time, it’s my plan to expand out to include a database of some kind, log analytics and so on, as well as a sample applcation that can be pulled down onto the scale sets to have a functional service instead of a collection of services that resemble one.

Building it out

Step 0 was building the infrastructure in the Azure portal. I spun up a new Resource Group and set out adding in the various components to be added and spun it up to make sure there weren’t any errors that were glaringly obvious - it’s been a while since I’ve used Azure so re-familiarising myself with the interface and components took a moment or two. Eventually though I had my MVP created and seemingly successfully starting up. With this I thought I’d be able to export from the Azure portal, paste the code into my Bicep file, moderately refactor and be done with it.

Reworking the code

On dropping the code into VS Code, no less than 23 errors popped up, and any hope I had of a quick change was undone. Do as I say, not as I do apparently. The Bicep config from the portal dropped all the components into a single file, so step one was to find the resources I wanted to group together and move them into separate modules. I ended up with the following structure:

/root
│   main.bicep
│── config
│    └─ prod.bicepparam
└── modules
     │─ loadBalancer.bicep
     │─ vmScaleSet.bicep
     └─ vnet.bicep

With vnet.bicep holding most of the networking configuration, vmScaleSet.bicep holding the VMSS configuration and the load balancer and backend pool information in the loadBalancer.bicep file. Naturally. Once the chunks had been moved into their respecitve modules I started the cleanup process. Most of this broke down into a couple of categories:

  • Replacing hard-coded values with parameters (such as the location of the resource group, or naming of resources)
  • Removing circular dependencies

On the latter, it seems that most of the errors were the result of resources referencing themselves, such as the backend pool in the load balancer requiring the id of the pool before it could be set up, which was unable to be set up as the backend pool wasn’t able to be deployed. Additionally, I found a few instances where resources were defined twice, such as the VM Scale Set defining the template VM, and then the template VM itself that was active in the subscription having its own declaration. Between some ChatGPT assistance and reading heavily through the Bicep resources documentation though, I managed to eventually get everything eventually configured and running without issue.

I should note, Microsoft’s reference documentation for Bicep and PowerShell both are just awesome pieces of documentation to work through. I can’t think of any other vendor who have provided the same level of documentation about responses and configuration flags for their products. For all their issues, they know how to write a good reference doc.

The next steps

Now that the bare minimum has been achieved, there’s a few next steps to take care of. First of all will be to replace the load balancer with Azure Application Gateway to allow some smarter routing and SSL/TLS termination. Expanding from that, building a simple container application that each VM can start up and register when scaling out, plus a database of some sort in the backend for longer-term state will be the next two steps. Finally, expanding out to include monitoring and log analysis will let me eventually have a more end-to-end demo offering that I can use to practice Azure system creation and also integrate with various observability tools. Beyond that, probably then repeating the same with AWS in the far future.

Once some more of the code has been created and tested successfully, a link to the code is planned to be included here or in another post.