Skip to main content

Command Palette

Search for a command to run...

New ALZ Accelerator: lessons learned

Updated
12 min read
New ALZ Accelerator: lessons learned
D

Principal Solution Architect, working daily with Azure, primarily focusing on automation and "everything as code".

This post was written for the Azure Spring Clean 2025 event. Visit the official website to see the schedule and links to great content.

Introduction

Azure Landing Zones (ALZ) have become the de facto standard for designing and implementing scalable, secure, and well-governed cloud environments. As an integral part of the Cloud Adoption Framework for Azure, the ALZ methodology has significantly evolved over the years. Today, it is supported by a vibrant community that engages through GitHub discussions and community calls.

The coding assets for ALZ have also matured and expanded to address diverse scenarios and tooling requirements. The latest release of the ALZ Accelerator simplifies the bootstrapping and provisioning of cloud platforms, covering everything from source control repositories and pipelines to Azure resources for platform landing zones.

In this blog post, I will share my experience implementing this new accelerator. I will compare it with the original accelerator (now referred to as “classic”), highlight the pros and cons of the design choices, and point out areas where we applied additional customizations, explaining the rationale behind these decisions.

💡
This isn’t a comprehensive guide for using the ALZ Accelerator from start to finish but rather a reflection of a specific implementation I have done and its objectives, and what I have learned from it. Be aware that in some sections I am focusing on the Bicep experience, so some information will not be true or relevant for the Terraform path.

Core features of ALZ Accelerator

If you wanted an ‘elevator pitch’ for the new ALZ Accelerator, we could say, it:

  • breaks down the entire ALZ deployment experience into four phases: first two - Planning and Pre-requisites - are manual ones, but the other two - Bootstrap and Run - are fully automated.

  • uses an opiniated approach for deploying and managing the platform landing zones of the ALZ reference architecture. The Accelerator engineering team made a lot of design decisions to simplify the experience by abstracting the complexity of deploying the entire ‘ALZ stack’. The Accelerator doesn’t deal with workload landing zones, and it doesn’t integrate directly with the Vending machine module!

  • supports both Bicep and Terraform for IaC modules. Due to Terraform’s versatility with close to five thousand providers, it is used in the Bootstrap phase even if you choose Bicep as your IaC language.

  • creates a continuous delivery environment in either Azure DevOps or GitHub. Alternatively, you could ‘bring your own VCS’ as well and use other services like GitLab, but you need to configure such integration yourself.

  • uses a new ALZ PowerShell module that gathers user input, configures the bootstrap environment, and ensures you can deploy the platform landing zones from it.

Its main objective, in my view, is to accelerate, rather than to provide every conceivable design and configuration option. This is done through abstraction and end-to-end automation.

💡
The ALZ core team has introduced a new home for technical documentation. The work is still ongoing, but I would encourage you to bookmark aka.ms/ALZ/TechDocs link and start using it.

The big picture and phases

I like this diagram, breaking down the experience to components and phases:

Credit: Microsoft - ALZ Accelerator project - https://azure.github.io/Azure-Landing-Zones/accelerator/

I would encourage you to go through the documentation and learn the details but here is my simplified version of the entire process:

  1. Start with planning: most organizations have some footprint in Azure already (aka Brownfield), so you need to consider where you are going to ‘attach’ the new Management Group hierarchy (with policies and roles), what IaC language and VCS platform you want to use, etc.

    I assume you are familiar with the ALZ reference architecture, its principles, design areas, and all the design decisions you should carefully make for your production environment. Without this knowledge it is quite impossible to comprehend what the ALZ Accelerator does, and what value it provides!

    The documentation gives many recommendations you should consider like:

    • using Tenant Root Group as the parent management group

    • using Three subscription model with separate Management, Connectivity, and Identity platform subscriptions, and deploy bootstrap resources to the Management subscription.

    • choosing between public or private networking for either self-hosted or Microsoft/GitHub-hosted agents (runners).

There is a comprehensive spreadsheet available containing all configuration settings you could use and later fill out configuration files.

A screenshot showing a portion of the ALZ Accelerator checklist spreadsheet.

  1. Validate you have all pre-requisites in place: from tools installed on your admin machine (PWSH, Az CLI, Git), configuration of your chosen VCS (things like PAT tokens and permissions), to having empty Azure subscriptions for platform LZs and an account with sufficient roles assigned).

    💡
    Tip: Once you download the ALZ module, there is a handy Test-AcceleratorRequirements cmdlet you could use to validate your machine.
  2. Bootstrap phase: Here you install the ALZ module and based on chosen VCS and IaC combination, you follow additional guidance to create a local folder structure and prepare a bootstrap configuration file.

    Once ready, you can trigger the bootstrap by calling Deploy-Accelerator cmdlet with a few parameters. Behind the scenes, it calls Terraform to provision a collection of resources both in Azure and your chosen VCS side.

    To give you a concrete example, when choosing Bicep with Azure DevOps and public networking scenario, it creates: two user assigned managed identities with federated credentials, a project, a repository with environments, a group, pipelines for CI and CD, service connections with workload identity federation, and a variable group. There could be some additional components based on the choices you make and declare in the bootstrap configuration yaml file. There are several sample config files available to pick and modify like this one for Azure DevOps and Bicep.

    Note: This phase uses IaC module stored in the Azure/accelerator-boostrap-modules repository on GitHub. You can see all the code if you are curious about how it was designed and written.

    The Bootstrap is meant to be executed once and when completed, you would leverage the CD pipeline (workflow) in your chosen VCS to deploy the platform LZs and maintain their lifecycle there.
  3. When you check your terminal output to see that the bootstrap went well, it is time to head to your new repository. That’s where you Run the continuous delivery pipeline for the first time and use Starter Modules to deploy a specific platform landing zone configuration.

Customization

There are several ways for customizing your ALZ environment and its configuration:

  • Bootstrap configuration file (e.g., input.yaml) - mainly used to provide config choices for provisioning VCS components and Azure resources that support the CI/CD workflow. Some of this configuration is reused in the Starter module (and copied over to the config/parameters.json file).

  • Names for bootstrap resources in Azure use a service name and environment name parameter values. If you want to use an alternative naming convention for resources, it can be overridden by following this guidance.

  • Two additional options are available, but only for Terraform:

    • Platform Landing Zone Configuration File (for TF ALZ Starter module)

    • Platform Landing Zone Library (lib) Folder. (for Platform Landing Zone Starter module)

  • You could fork and modify the modules directly as described in this Consumer Guide. This will, however, be out of sync with the CD pipeline created by the Accelerator since it always pulls the entire modules package from its upstream (Azure/ALZ-Bicep).

There might be additional areas for changing the configuration stored in the repository once you pass the Bootstrap phase (before you run the CD pipeline for the first time), but I couldn’t find any reference to it in the documentation:

  • Modify the /config/parameters.json file and add module variables to further customize the environment.

  • Modify the parameter files (in JSON format) in the config/custom-parameters folder. By inspecting the workflow definition files it does seem they are used for every CD run, but the documentation doesn’t mention it (or at least I couldn’t find it).

I will update this blog post later if I find more information about these additional customization options or test them in my sandbox environment.

Code repositories in the ALZ universe

I always like to build a mental map of different ‘building blocks’ / code sources and how they relate to one another. The diagram I made focuses on the Bicep path of the Accelerator (with some components being common for the Terraform path):

  • Your journey with the ALZ Accelerator should begin with the new documentation page - Azure Landing Zones Documentation. It is available using the handy aka.ms/alz/accelerator shortcut and it is sourced from the Azure\Azure-Landing-Zones repository.

  • You will download and install the ALZ module from the PowerShell Gallery. The source for the code is in the Azure\ALZ-PowerShell-Module repository.

  • During the Bootstrap phase, the automation is leveraging the Bootstrap modules hosted in the Azure/accelerator-bootstrap-modules repository. It uses Terraform due to its ability to provision resources in Azure, Azure DevOps, and GitHub, but it doesn’t limit your options for selecting Bicep as your IaC language for the Run phase.

  • When you trigger the continuous delivery pipeline (workflow) in your VCS repository or a project, as part of the flow it downloads the latest release (zip) of ALZ-Bicep modules package (for Terraform, it is a different source repository). That one is maintained in the Azure/ALZ-Bicep repo.

    • When you inspect that repository and its code, you will see that all Bicep modules (except one: ptn/network/private-link-private-dns-zones) are stored locally.

    • Being able to use and reference these modules directly from the Microsoft Public Bicep Registry through the Azure Verified Modules initiative is on the roadmap, which is why there isn’t a “link” between the ALZ-Bicep repo and the AVM repository for Bicep - Azure/bicep-registry-modules - in my diagram.

    • You can even spot traces of AMV’s predecessor CARML (in the CRML folder).

  • I understood from one ALZ external community call that when it comes to custom policy definitions for ALZ, the upstream repository is still the original Azure/Enterprise-Scale and there is a workflow making sure the downstream ALZ-Bicep is updated on a regular basis. This might not be entirely correct!

  • As I mentioned above, the Bicep module for Subscription Vending - Azure/bicep-lz-vending - is not directly integrated with the Accelerator.

💡
I hope this breakdown helped you to ‘connect the dots’ and better understand how the entire code base for ALZ is distributed and intertwined, but you can certainly use the ALZ Accelerator without it 😀.

New vs. Classic Accelerator

For those of you who tried the earlier versions of the ALZ Bicep Accelerator, you might have seen this disclaimer in the ALZ Bicep Wiki:

The Classic Accelerator used a collection of workflows and respective PowerShell scripts to manage parts of the Platform Landing Zone.

The new ALZ Accelerator uses only two pipelines (workflows): CI and CD. It also leverages reusable workflows (or pipeline templates).

Also, all parts of the platform are treated as steps and the provisioning is sequenced inside one job, as shown in the screenshot below from one of my test deployments with Azure DevOps and Bicep combo:

My implementation

I planned to deploy the ALZ reference architecture in our internal tenant (in a Brownfield fashion) and at the same time assess the new Accelerator and its new features. It seemed to be a great fit, especially since I wanted to use IaC and the gitops style of managing the landing zones.

For the Bootstrap phase, I selected:

  • Bicep as iac_type

  • alz-github as bootstrap_module_name

  • Complete starter_module_name

  • Tenant Root Group as the Parent MG

  • I went with the ‘Three subscriptions model’ and deployed the boostrap resources in the Management subscription

  • I didn’t see compelling reasons for using private networking and self-hosted runners. This would have been different if I chose Terraform as IaC, even though there are two ways for keeping the state file in a secured blob storage - Large Runners or Azure VNet integration.

What didn’t work for us

While I was studying the composition of this solution and its customization options, I quickly realized that I would need to deviate from my desired “layout” and that several of my key requirements are not compatible with the new Accelerator and its design:

  • Store the configuration of each platform landing zone in a separate code repository:

    • I want to delegate access to different platform LZs to separate teams. The Accelerator uses the ‘monorepo’ approach for storing configuration, so delegating the responsibility for parts of the configuration to different teams would be cumbersome, especially since it uses one primary configuration file (config/parameters.json).

    • Such distribution to several repos and respective workflows could simplify and speed up redeployments and configuration changes.

  • Be true to the code-first infrastructure provisioning principle and treat the code repository as a single source of truth:

    • The Accelerator doesn’t honor this principle, since it provisions the bootstrap resources (managed identities, ACR, etc.) in ‘fire and forget’ fashion. I know this is a classic ‘chicken and egg’ problem, but it would be great to be able to ‘import’ those resources to the Management LZ repo.
  • I prefer having a more direct access to IaC deployment files and its parameters over such high level of abstraction:

    • I wanted to be able to add additional components to platform LZs that are either not part of the reference implementation (e.g., replica domain controllers, Azure VNet Manager) or aren’t implemented in a flexible enough way (e.g., Azure Firewall policies).

Path we are (probably) taking

At the time of writing this blog post, we haven’t completely decided what implementation approach we are going to choose but considering the requirements I described above, we will most likely:

  • avoid using the ALZ Accelerator due to the abovementioned reasons

  • create four GitHub repositories (not counting the existing repo for reusable workflows we already have in the organization) and map them to three Platform subscriptions:

  • fork the ALZ Bicep modules from the Azure/ALZ-Bicep repo to a Private Modules Library and publish them in our Private Bicep Registry.

    💡
    I wrote an article about building such a library, you can find it here.
  • follow the Module Deployment Sequencing guidance but split it in a way to match it with the repos-subs mapping

Obviously, this requires a lot of additional engineering work, but this approach could give us the needed level of flexibility and align with the overall Azure Landing Zone Journey. Once the Project Uplift is complete and ALZ-Bicep modules are converted to AVM modules, we could easily switch the reference to br/public in our deployment templates.

Conclusion

The new ALZ Accelerator is a very robust and interesting attempt to automate the deployment and lifecycle management of platform landing zones beyond what was possible previously with the original accelerators (the Portal experience, JSON ARM, Terraform, and Bicep).

The level of abstraction and the way it pulls the entire package of ALZ modules might not be a good fit for every customer, but it has clear benefits over a more complex DYI approach.

My wish is it eventually switches to a model, that it leverages AVMs both for Terraform and Bicep. The good news is it is on the roadmap already and there is an open issue in the Azure/ALZ-Bicep repo:

💡
TIP: If you are wondering about the ALZ roadmap, you can follow it up at aka.ms/alz/roadmap (GitHub Project).