all Technical posts

Building Landing Zones with CARML

A landing zone provides a foundation for deploying workloads in Azure while adhering to organizational policies and standards. These days, many companies are investing in building up Landing Zones in order to provide standardization, consistency, security, governance, compliancy and more to their future workloads. Let's take a look at some possible approaches to building an enterprise landing zone using Bicep.

Building Landing Zones

To create complex infrastructures with Bicep, there are mainly two approaches I’ve seen so far:
  • build your own bicep modules.
  • use the Common Azure Resource Modules Library (aka CARML, a library of mature bicep modules curated by Microsoft.
This repo ALZ-Bicep is an example of what normally happens when I create my own bicep modules to encapsulate part of my deployments: basically, by having two levels of modules and orchestrations.
  1. One or multiple modules for the networking, one module per supporting support services, application modules, etc.
  2. The modules normally contain a set of resource definitions.
  3. Modules are then called in the right sequence by bicep orchestration files.
This setup works like a charm, but over time makes you feel as if you are writing the same modules over and over again.

Leveraging the CARML

Now let’s look at how we could approach a hypothetical landing zone project with CARML.
The main objective of CARML is to offer you reusable building blocks, allowing you to concentrate on what truly matters. CARML expedites solution development, reduces testing time, facilitates seamless integration, and ensures uniformity across your infrastructure deployments. In the CARML modules, concepts like RBAC, Logs, Metrics, Locks and child resources are heavily integrated and fully parametrized, giving you the opportunity to cover multiple setups without the need to maintain multiple module instances for different use cases. 
So how can we structure our Enterprise-Scale landing zone templates with CARML? We could have:
  1. One orchestrator per subscription (Management, Connectivity, Identity, Sandbox, etc.) plus one orchestrator for the management group creation and subscription placement. Basically, this means having one orchestrator per design area for Enterprise-scale landing zones.
  2. Multiple bicep modules to assemble the CARML modules in a reusable way. In this way, I can design chunks of the architecture.
  3. A multitude of the CARML modules curated by Microsoft. Each CARML module is tied to a specific resource type (virtualNetwork, ipGroup, routeTable, etc.) and grouped by resource providers (Microsoft.Network).
This approach allows us to reduce the number of level-2 modules to be developed. However, as we rely on the quality of the CARML we are introduced to more moving parts, and questions about how to version and upgrade the different modules, and additional questions about how to securely give access to the shared modules arise.

Share the CARML modules

The most effective way to share and consume the bicep modules is via a Bicep registry (private or public). By using a Bicep private registry you can:
  • leverage the Azure RBAC and provide access to the proper identities by assigning push and pull permission to the ACR.
  • reference your modules with an intuitive syntax (e.g. module modNetworkWatcher ‘br/networking:watcher:1.0.epsilon’ ={} )
  • reduce the external dependencies.
When we deal with this 3-layer approach, the orchestrations are normally saved on the customer repository along with the parametrization, the CICD, and other support artifacts. The second-level modules are subject to changes depending on the customer’s needs. It, therefore, makes sense to save them in the customer repo and then publish them to a private ACR hosted by the customer.
But what about the CARML modules? Should we use a private repo, a partner repo (to offer additional services on top of CARML) or a public repo (hosted by Microsoft)?
The following image illustrates three options:
What is the best choice? Well, this depends on your security requirements, the versioning strategy, the deprecation strategy, and more.
  • The use of the public registry is the simplest and the cheapest solution. If that external dependency works for you, you can begin quickly. If you need to deviate to the CARML, you can build your own version and push it to the customer registry. Unfortunately, at the time of writing a limited number of modules are available.
  • Publishing the CARML on the customer private registry makes the security tighter, but you have to put a procedure in place to maintain the CARML, intake a new version, and make sure you have a deprecation strategy. That’s not an easy procedure: the cloud is moving fast, and new services are popping up at the same pace as deprecations.
  • A better solution might be to delegate the maintenance of a registry to a partner and use the Azure Lighthouse to grant access to the partner registry. The partner will take care of introducing new features when needed, such as upgrades, deprecations, and more. This guarantees peace of mind, along with a fully managed service.


By leveraging modularization with Bicep and Bicep Registry, you can improve code reuse, simplify infrastructure management, foster collaboration, and benefit from the ecosystem and best practices established by the community. This offers a more efficient and scalable approach to building and managing infrastructure as code solutions as landing zones.
Happy Infrastructure as Code, everyone!

Subscribe to our RSS feed

Thanks, we've sent the link to your inbox

Invalid email address


Your download should start shortly!

Stay in Touch - Subscribe to Our Newsletter

Keep up to date with industry trends, events and the latest customer stories

Invalid email address


Great you’re on the list!