Bicep is the latest Azure infrastructure as code (IaC) language introduced by Microsoft. We have discussed about getting started with Bicep in the post "Azure Infrastructure as Code (IaC) with Bicep - Getting Started with Development". Let's look at how to implement an Azure pipeline to deploy infrastructure to Azure with Bicep in this post.
We have created a working demo of deploying an app service plan and a node Linux web app in the post "Passing Output Parameters from Bicep Modules". Let's try to deploy the same code with Azure pipeline. The code should be committed to an Azure git repo. For simplicity, the commit has been made directly to the main branch.
Note that our Bicep files are in a folder named Infra.
Next let's create a yaml pipeline file in a Pipelines/Deploy folder path.
Our main Bicep file in the post "Passing Output Parameters from Bicep Modules" requires the set of parameters shown below.
As the first step f the pipeline lets set trigger and couple of parameter values which are required for the Bicep file. The pipeline is set to execute with the latest ubuntu hosted agent. Notice how we have to supply the linuxFxVersion parameter as it is having a piping symbol. Piping symbol issue is discussed here.
trigger:
- main
name: Deploy Bicep files
variables:
azureServiceConnection: 'InfraDeploy'
rgName: 'rg-biceppipeline-001'
rgLocation: 'centralus'
planName: 'plan-biceppipeline-001'
planSKUName: 'B3'
planSKUCapacity: 1
planKind: 'linux'
webappName: 'app-biceppipeline-001'
linuxFxVersion: '"node|16-lts"'
templateFile: './Infra/main.bicep'
pool:
vmImage: 'ubuntu-latest'
The service connection InfraDeploy is created in the team project using an SPN having contributor role to the Azure subscription.
A job to check what happens if the Bicpe script is executed can be created as follows. Notice
stages:
- stage: Dev
displayName: Precheck deploy to Dev
jobs:
- deployment: PrepareForDev
environment: myInfra-dev
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: AzureCLI@2
displayName: See whats gonna happen
inputs:
azureSubscription: $(azureServiceConnection)
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
az --version
az deployment sub create --location $(rgLocation) \
--template-file $(templateFile) --parameters rgName=$(rgName) \
rgLocation=$(rgLocation) planName=$(planName) \
planSKUName=$(planSKUName) planSKUCapacity=$(planSKUCapacity) \
planKind=$(planKind) webappName=$(webappName) \
linuxFxVersion=$(linuxFxVersion) --what-if
The above job allows us to see what is going happen if the Bicep script is executed. You can see three resources, resource group, app service plan and an app would be created if we execute the Bicep script.
As you can see above we can use a manual intervention step in Azure pipeline to ensure we check and approve the changes to infra, before they are applied to the subscription. Pre validation is an important step in infra deployment specially in production scenarios to enable stable deployments of infrastructure. Manual intervention job can be added to pipeline as shown below.
- job: waitForValidation
dependsOn: PrepareForDev
displayName: Wait for external validation
pool: server
steps:
- task: ManualValidation@0
inputs:
notifyUsers: 'chaminda_chandrasekara@yahoo.com'
instructions: 'Validate infra deploy'
Once, the manual validation is done on what happens if the Bicep script is executed, we can approve if it is doing what we intend it to do.
We can set the next job to execute the Bicep script without --what-if to apply the changes to the infrastructure.
- deployment: DeployToDev
dependsOn: waitForValidation
environment: myInfra-dev
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: AzureCLI@2
displayName: Deploy resources to Azure
inputs:
azureSubscription: $(azureServiceConnection)
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
az --version
az deployment sub create --location $(rgLocation) \
--template-file $(templateFile) --parameters rgName=$(rgName) \
rgLocation=$(rgLocation) planName=$(planName) \
planSKUName=$(planSKUName) planSKUCapacity=$(planSKUCapacity) \
planKind=$(planKind) webappName=$(webappName) \
linuxFxVersion=$(linuxFxVersion)
When the pipeline completes we can see the resources created in Azure.
The complete pipeline code is as follows.
trigger:
- main
name: Deploy Bicep files
variables:
azureServiceConnection: 'InfraDeploy'
rgName: 'rg-biceppipeline-001'
rgLocation: 'centralus'
planName: 'plan-biceppipeline-001'
planSKUName: 'B3'
planSKUCapacity: 1
planKind: 'linux'
webappName: 'app-biceppipeline-001'
linuxFxVersion: '"node|16-lts"'
templateFile: './Infra/main.bicep'
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: Dev
displayName: Precheck deploy to Dev
jobs:
- deployment: PrepareForDev
environment: myInfra-dev
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: AzureCLI@2
displayName: See whats gonna happen
inputs:
azureSubscription: $(azureServiceConnection)
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
az --version
az deployment sub create --location $(rgLocation) \
--template-file $(templateFile) --parameters rgName=$(rgName) \
rgLocation=$(rgLocation) planName=$(planName) \
planSKUName=$(planSKUName) planSKUCapacity=$(planSKUCapacity) \
planKind=$(planKind) webappName=$(webappName) \
linuxFxVersion=$(linuxFxVersion) --what-if
- job: waitForValidation
dependsOn: PrepareForDev
displayName: Wait for external validation
pool: server
steps:
- task: ManualValidation@0
inputs:
notifyUsers: 'chaminda_chandrasekara@yahoo.com'
instructions: 'Validate infra deploy'
- deployment: DeployToDev
dependsOn: waitForValidation
environment: myInfra-dev
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: AzureCLI@2
displayName: Deploy resources to Azure
inputs:
azureSubscription: $(azureServiceConnection)
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
az --version
az deployment sub create --location $(rgLocation) \
--template-file $(templateFile) --parameters rgName=$(rgName) \
rgLocation=$(rgLocation) planName=$(planName) \
planSKUName=$(planSKUName) planSKUCapacity=$(planSKUCapacity) \
planKind=$(planKind) webappName=$(webappName) \
linuxFxVersion=$(linuxFxVersion)
No comments:
Post a Comment