Project Bicep, the ARM DSL from Microsoft
*Updated post with the latest news available
What’s Project Bicep?
Bicep is the DSL (Domain Specific Language) for deploying Azure resources in a declarative way. It aims to simplify the experience we are currently having with ARM templates for deploying Azure resources, with a cleaner syntax, modularity, and re-usability.
It provides a transparent abstraction over ARM templates (we know ARM templates are not the easiest to author), all the things we can do with ARM templates until now (and in the future), can be done with bicep (excepting known limitations that Microsoft expects to solve in further versions). However, is ready for production use. Using Bicep and some of the tooling in this post, it is now much easier to build out ARM templates.
Therefore, I wanted to make a simple introduction, because I find useful to know about this new DSL, its simplicity and features it will have over traditional ARM templates to deploy Azure resources. It will allow devs to build ARM templates quicker and easier than ever.
Why should I care about Bicep?
There already are alternatives like Terraform, Pulumi, and other IaC offerings to avoid the complexity of ARM templates… Well, I would like to admit I have used Terraform for Azure in some projects and I am very happy with it, its Azure providers are really awesome, but in some cases, with new Azure features, products or configurations, we will have to wait to the provider to implement this changes (or will not be available in a foreseeable future, such the Azure Portal integration). Using the “AzAPI Provider” instead of the “AzureRM provider” solves the wait for the provider to implement support for newest changes in Azure. If using the “AzAPI Provider”, we will be using the same API as Bicep uses for deploying resources. Nevertheless, we will have to deal with the Terraform state, without Azure Portal integration and missing some integration features such as Azure Policies.
Instead of this, Bicep is covered in all Azure support plans since the 0.3 version. As it compiles down directly to standard ARM template JSON files and its supported and backed-up by Microsoft, we should have all the new features, products, and configurations available out-of-the-box (which is reassuring), as well as an awesome Azure Portal integration and some better integration.
In my opinion, I think it deserves a try for devs deploying resources to Azure. However, it is important to highlight that there is no reason to switch to Bicep if you are already using terraform or other IaC provider, since there is so much effort after its providers to make them work great with Azure, and Microsoft itself it is backing up this effort. The reality is that there are so many projects using ARM templates and Microsoft is trying to make it easier to manage this and to provide its own tooling to start with IaC (without having to depend on third sources).
Bicep vs Terraform
What are the differences between Bicep and Terraform? Both are two leading IaC (Infrastructure as Code) offers. Regarding infrastructure, integration and usability, both have very user-friendly features which makes them really similar in some aspects. A key concept to know is that there are not important usability features when using Bicep versus Terraform.
Their infrastructure and integration features make it easier for developers to implement IaC solutions. The only important decision to consider is if you are deploying to more than one cloud provider (or if your infrastructure will consist of a multi/hybrid cloud environment). If the answer is yes, then Terraform will fit you the best, since Bicep is solely for Azure resources.
Performing a more in depth comparison, there are some key differences that we need to know:
Regarding integration and infrastructure
- State and Backend: both are desired state configuration (DSC). Nevertheless, Terraform stores state and configuration information while Bicep does not. This information is used by Terraform and can be stored in a local file or remotely (for example in an Azure Storage container). On the other hand, Bicep relies on incremental deployment.
- Infrastructure targets: Bicep is Azure-specific and not designed to work with other cloud services. With Terraform we can work with several cloud services: AWS, Azure, Google Cloud… and the list goes on.
- Tooling: Terraform uses its own CLI while Bicep integrates with Azure CLI (with az bicep and az deployment). Note that Bicep can also be used as a separate CLI tool.
- Processing: with Bicep, processing occurs within the core Azure infrastructure service side. With Terraform, processing is done within the Terraform client, which involves no calls to Azure to determine the required changes (using the saved state).
- Authentication: Bicep uses an authorization token supplied during the request to submit a file or template. On the other hand, Terraform authenticates based on provider credentials (Azure CLI, service principal or managed identities).
- On Azure: Bicep offers better integration with Azure features, such as Azure Policy, which are evaluated previously to determine if a resource will be denied by a policy and fail the deployment. In this specific case, Terraform will fail while deploying the resource.
- Portal integration: one of the main advantages while working with Bicep in Azure, is the ability to automate portal actions. You can use the Azure portal to export templates and use it later, helping us to understand how to do it with Bicep (and all its possible parameters). Terraform does not provide this same portal integration as Bicep. Nevertheless, with other tools such as Azure Terrafy, we can take existing Azure infrastructure under Terraform management.
- Out-of-band changes: when making changes in infrastructure outside of the context of the tool, you will need to reconcile them with Bicep and the ARM template code (to avoid those changes to be overwritten on the next deployment). In the case of Terraform, you will need to import these changes into the Terraform state and update the Terraform related files (which can be tedious sometimes).
- Cloud frameworks: Bicep simplifies the process for deploying landing zones with a portal experience based on ARM templates and landing-zone implementation. Terraform uses an Enterprise-Scale Landing Zones module to deploy, manage and make operations with Azure.
Regarding usability
- Language: Bicep and Terraform are easy to use, domain-specific languages (DSL). Both have similar keywords and concepts such as parameterization, multi-file projects, external modules… However, Terraform offers built-in functionalify for certain tasks. Both are declarative languages and offer language helpers to simplify coding tasks. Also, the code authoring experience can be really nice using extensions for the IDE of your choice (for example both offer add-ins for Visual Studio Code).
- Modules: both Bicep and Terraform support the concept of Modules, which allow you to create reusable components from your code.
- Provisioning lifecycle: both Bicep and Terraform allow to validate configuration before deployments and then apply the desired changes (with terraform plan or Bicep what-if operation). Nevertheless, Terraform provides more flexibility to destroy all the remote objects managed by a particular configuration.
- Getting started: it is easy and straightforward to get started with Bicep or Terraform: both offer resources to help you. For Bicep, you can check out Microsoft Learn and its documentation in Microsoft Docs. In the case of Terraform, you can checkout HashiCorp Learn and its documentation in Terraform docs.
- On Azure: Bicep has a clear advantage over Terraform when it comes to Azure and configuring Azure resources. Bicep is more integrated with Azure services with immediate support for new Azure features. With Terraform, we have two main providers that allow users to manage Azure:
- AzureRM: a stable experience for Azure services, with a little bit of delay with new Azure features.
- AzAPI: a layer on top of the Azure ARM REST APIs, which enables immediate support for Azure features.
- Community and Support: both communities offer a high level of engagement and support.
- For Bicep we have Bicep documentation on the Microsoft Docs and the possibility to checkout Bicep source code and filing bugs.
- For Terraform we have Terraform documentation on the Microsoft Docs, the possibility to checkout provider source code and filing bugs, getting answers to Terraform core questions and Terraform provider-related questions.
Be sure to consider the previous concepts (and your infrastructure requirements and preferences) to make the best choice for your organization.
Getting started with Project Bicep
It is very simple getting started. We only need the Azure CLI. It is up to you to install other tooling (CLI, the VS Code extension, etc.). The process for these tools is simple and documented in their repository. Note that is also a Bicep PowerShell Module, if we want to have a great wrapper for the Bicep CLI in PowerShell.
The next step is to learn about Bicep and its syntax. A good start point it’s the official tutorial. There are also great resources to try Bicep, such as the Bicep Playground and the Visual Studio Code Devcontainer/Codespaces repo.
After this process, and after playing for a while, we should be ready to use it and ease our Azure deployment templates.
Interpreting the schema above, the process would be as simple as:
bicep build my-deployment.bicep # Just this extra step
az deployment group create my-deployment.json
But we can skip that extra step! Since both Az CLI (2.20.0+) and the PowerShell Az module (v5.6.0+) have Bicep support built-in:
az deployment group create my-deployment.bicep
With Bicep, we are simplifying the process of creating ARM templates a lot and getting a lot of benefits. One of them I found very interesting is the possibility of making separate bicep files to generate a single ARM file, its modularity feature.
Let’s take a quick look in differences between a bicep and an ARM file (which are equivalent), from a simple quickstart template from the Azure repo:
Looks simple and it is, but…
How convert ARM templates to the Bicep format?
There are two different approaches:
- There is a cheat-sheet available to compare the ARM template syntax and the native Bicep equivalent. This document should allow us to start converting existing ARM templates to its Bicep equivalent and starting to simplify them and using its features.
- The ‘decompile’ option available in the Bicep CLI. This option is really great and usually works very well. It is important to note that because there is no guaranteed conversion from JSON to Bicep, decompilation may fail, or you may be left with errors/warnings in the generated Bicep file to fix up. However, is the easiest way to get bicep files out of our ARM ones. Just as simple as executing: bicep decompile my-arm-template.json or az bicep decompile my-arm-template.json.
Nevertheless, it is important to highlight that, since Bicep compiles down to ARM templates, we could also have Bicep and ARM templates coexisting at the same time, and incrementally convert the templates or let the old stay as standard ARM templates (as the developer wants).
The approach in our deployment process will almost be the same since we only introduce one extra step in our deployment process: the compilation of Bicep files down to its JSON ARM template equivalent before deploying the ARM templates.
Supporting Bicep in our Continuous Deployment Pipelines
Since Bicep its “only” tooling, we could easily implement compilation of Bicep files in almost every environment. A simple and generic approach would be to download the binary from the GitHub releases and execute the binary with our Bicep files to JSON. But this it is not necessary at all as commented out before, with the newer versions of Azure CLI and the PowerShell Az module.
While being simple to implement this generic approach, the community and Microsoft itself it’s starting to provide us the necessary extensions, packages, and actions to include Bicep tooling (if we need it) in our pipelines.
Azure DevOps Pipelines
For Azure DevOps Pipelines, I have already some implemented tasks to abstract and simplify the process for Bicep in a pair of tasks, which can be found in the README of the official project or in the Visual Studio Marketplace.
Nevertheless, if you do not like to include third-party extensions in your Azure DevOps organization, we can do our own pipeline (downloading the tooling by ourselves).
GitHub Actions
There is a community developed GitHub Action to include Bicep in our deployment process when using GitHub Actions. As said in the Azure DevOps Pipelines section, we could implement our own action (downloading the tooling by ourselves).
Other CI/CD environments
Bicep it is only a binary that can run cross-platform. So nowadays, I think there would be no problem in any CI/CD environment to introduce an extra step to handle ‘.bicep’ files. Note that only for deployment purposes it is not necessary at all.
It would only be an executable that could be downloaded in every run or saved in our environment, that we need to run against a series of ‘.bicep’ files.
There is really no reason to start embracing Microsoft Bicep…
There is much more to discover (and features to come!), for now, we wanted to give you this series of initial concepts so you start testing what Project Bicep can offer.