In this article, we are going to learn how to reuse the Bicep Infrastructure as Code with your team and other teams across the Organization.
Introduction
Azure Bicep is a Domain Specific Language (DSL) for deploying Azure resources declaratively. It provides concise syntax and a high-level abstraction over Azure Resource Manager (ARM) templates. Reusability in the Bicep can be achieved through modules.
Example of a Module used in one Business Unit
A Module in Bicep is a reusable component that can take inputs as Bicep Parameters; it does the job and finally can return Output values
Let’s say, you are part of a Business Unit and you are responsible for developing Re-usable Bicep Components that could be used within your Business Unit (say BU1).
As shown above, you create the below three Bicep Modules (they are just .bicep files).
AppService.Bicep (App Service Module)
resource azbicepasp1 'Microsoft.Web/serverfarms@2022-03-01' = {
name: 'azbicep-dev-eus-asp1'
location: resourceGroup().location
sku: {
name: 'S1'
capacity: 1
}
}
resource azbicepas 'Microsoft.Web/sites@2022-03-01' = {
name: 'azbicep-dev-eus-wapp1'
location: resourceGroup().location
properties: {
serverFarmId: resourceId('Microsoft.Web/serverfarms', 'azbicep-dev-eus-asp1')
}
dependsOn: [
azbicepasp1
]
}
(Storage.Bicep) Storage Account Module
param pStorageAccountName string
param pLocation string
resource storageaccount 'Microsoft.Storage/storageAccounts@2021-02-01' = {
name: pStorageAccountName
location: pLocation
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
}
output StorageAccountId string = storageaccount.id
(Database.Bicep) Database Module
param pSQLServer string
param pAdministratorLogin string
@secure()
param pAdministratorLoginPassword string
param pLocation string = resourceGroup().location
resource sqlServer 'Microsoft.Sql/servers@2014-04-01' = {
name: pSQLServer
location: pLocation
properties: {
administratorLogin: pAdministratorLogin
administratorLoginPassword: pAdministratorLoginPassword
}
}
resource sqlServerDatabase 'Microsoft.Sql/servers/databases@2014-04-01' = {
parent: sqlServer
name: 'database1'
location: pLocation
properties: {
collation: 'SQL_Latin1_General_CP1_CI_AS'
edition: 'Basic'
maxSizeBytes: '2147483648'
requestedServiceObjectiveName: 'Basic'
}
}
Once the bicep modules are ready, they can be invoked by another Bicep file by passing the appropriate input Parameters as shown below.
Main.Bicep
param Env string = 'dev'
param pAppServicePlan string
param pAppService string
param pSQLServer string = 'azbicep-dev-eus-sqlserver'
param pAdministratorLogin string
param pLocation string = resourceGroup().location
param pSKUName string = (Env == 'dev')? 'F1' : 'S2'
param pSKUCapacity int = (Env == 'dev')? 1 : 2
resource KeyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
name: 'azbicep-dev-eus-kv1'
}
module AppServicePlan '2.AppServicePlan.bicep' = {
name: 'AppServicePlan'
params: {
pAppService: pAppService
pAppServicePlan: pAppServicePlan
pInstrumentationKey: AppInsights.outputs.oInstrumentationKey
pLocation: pLocation
pSKUName: pSKUName
pSKUCapacity: pSKUCapacity
pEnv: Env
}
}
module SqlDatabase '3.SQLDatabase.bicep' = {
name: 'SQLDatabase'
params: {
pSQLServer: pSQLServer
pAdministratorLogin: pAdministratorLogin
pAdministratorLoginPassword: KeyVault.getSecret('sqladminpassword')
pLocation: pLocation
}
}
Example of Bicep Modules used in another Business Unit
As shown below, another team working for Business Unit 2 might also implement a similar design where they also create these modules which is nothing by duplicate work. Below is how it would look.
Let’s now understand how to refactor the code in such a way that you have one set of reusable components that are accessible by all the Business Units across the organization.
Below is the ideal design for refactoring the reusable components.
Bicep supports the above design by letting the Bicep Developers publish the Modules to a Private Registry in Azure as of this writing. Microsoft Azure team has plans to support the publishing of Modules to Docker Hub in the future.
Below are the advantages of publishing the modules to a Container Registry.
- Centralized Repository: A container registry provides a centralized location to store and manage your modules. This makes it easier for teams to access, share, and collaborate on reusable infrastructure components.
- Versioning: Container registries typically support versioning of modules. This enables you to manage different versions of your modules, facilitating backward compatibility and ensuring that deployments are predictable and reliable. In our example, BU1 and BU2 can have their own versions of modules if required.
- Security: Container registries offer security features such as access control and encryption to protect your modules from unauthorized access and tampering. You can control who has access to the modules stored in the registry, ensuring that only authorized users can deploy them.
- Integration with CI/CD Pipelines: Container registries integrate seamlessly with continuous integration and continuous deployment (CI/CD) pipelines, enabling automated testing, building, and deployment of modules. You can configure your CI/CD pipeline to automatically publish updated versions of modules to the registry, streamlining the development and deployment process.
Overall, publishing modules to a container registry offers a robust and secure way to manage, share, and deploy reusable infrastructure components, enhancing collaboration, scalability, and reliability in your cloud deployments.
Working with Private Registries in Azure for publishing the Bicep modules needs infrastructure. Below is how the Private Registries are organized and used.
Next Steps
- Creating an Azure Container Registry (ACR) & Enabling Authentication for ACR.
- Developing Bicep modules &publishing each module.
- Invoking each module by referring to the ACR Repository.
Summary
In this article, we explored creating Bicep modules for common infrastructure components like App Service, Storage Account, and Database. These modules can then be invoked in a main Bicep file by passing appropriate parameters.
However, duplicating module creation across business units leads to redundancy. To address this, in the next set of articles, we will discuss leveraging private registries in Azure for sharing modules organization-wide. Publishing modules to a container registry offers several advantages, including centralized repository management, versioning, security features, and seamless organization of the Infrastructure as code.
In summary, leveraging private registries in Azure enhances collaboration, scalability, and reliability in managing and sharing reusable infrastructure components across an organization.
Thanks for reading, and good luck in organizing your code.