Infrastructure as Code Using Azure CLI

Todd Horn Architecture, Azure, DevOps, Tutorial Leave a Comment

Infrastructure as Code (or IaC) is the process of using code and versioning in the same way you do your source code to manage your networks, VMS, and Azure resources. It generates the same environment every time it is applied, and it’s an important DevOps practice to use alongside continuous delivery. Using Azure CLI and Azure DevOps Release Pipeline, we can implement IaC.

The goal of IaC is to always set the target environment into the same configuration, regardless of the starting state. You make changes to the code environment description and version the configuration model.

The release pipeline executes this model to configure target environments. If you need to make any changes, you edit the source, not the target environment. This allows you to create reliable and stable environments on-demand that can be validated, tested, and repeated.

In this blog, we’ll look at how we can use Azure CLI and Azure DevOps Release Pipelines to achieve IaC. I’ll walk you through all the steps you need to take to get set up.

First things first, you will need to create an Azure account if you don’t already have one. We will also be using Azure DevOps. Check out Visual Studio Dev Essentials for everything you need to get started.

Step1: Azure CLI

We will need some of the basics from Azure CLI. If you need help getting started and set up, check out the Azure CLI Documentation.

These are the CLI commands we will look at for this example:

Create a Resource Group:

az group create  --name $resourceGroupName  --location $location

Azure CLI Reference

Create a Storage Account:

az storage account create  --name $storageAccountName  --resource-group $resourceGroupName  --location $location  --sku $storagesku

Azure CLI Reference

Create an App Service Plan:

az appservice plan create  --is-linux  --name $appServicePlanName  --resource-group $resourceGroupName  --sku $pricingTier  --location $location

Azure CLI Reference

Create a Web App:

az webapp create  --name $webAppName  --resource-group $resourceGroupName  --plan $appServicePlanName  --runtime $runtime

Azure CLI Reference

Create an Azure Table:

az storage table create  --name $azureTableName  --connection-string $connectionString

Azure CLI Reference

Step 2: Azure DevOps

Now let’s move over to Azure DevOps and start putting all this together. If you are not familiar with Release Pipelines or need to create one, this article can get you started.

Log into Azure DevOps.

Then, go to Pipelines –> Releases, select the release you want, and click Edit.

This will take you to the Edit Pipeline page.

Right now, I only have one Stage (“Dev”) defined, but you can add multiple stages to create your pipeline for Continuous Delivery (for example, Dev, QA, UAT, Prod).

Let’s add some variables to start. Click Variables.

Below are the variables that I will use in this example.

To add variables, click +Add in the lower left-hand corner.

If you have multiple stages, you can set the Scope to correspond with the Stage it should. (Release is the default – this allows for different variables in Dev, QA, UAT, etc.)

Next, select the Task dropdown. Then, click on the stage you want (in my case, “Dev”).

This will take you to the Task page. You can add an Agent job by clicking the icon with three dots in the right-hand corner.

Now, let’s add some Tasks.

First, click the + to the right of Agent Job. Then, search for Azure CLI using the search box. Finally, click Add.

As you are prompted to do, enter a Display name, and select an Azure Resource Manager connection.

Select Powershell Core as your Script Type. Then set Script Location to Inline script.

In the Inline Script box, we’ll put together some of the Azure CLI commands we talked about in the last section.

The Variables we added before can be included directly within the script in Script Arguments.

Create a Storage Resource:

Use Create Resource Group (az group create) with Create Storage Account (az storage account create).

Create a Storage Resource YAML:

variables:
  resource-group-name: 'iac-demo'
  location: 'centralus'
  storage-account-name: 'khsiacdemo'
  storage-sku: 'Standard_LRS'

steps:
- task: [email protected]
  displayName: 'Azure CLI - Create Storage Resource'
  inputs:
    azureSubscription: 'Azure subscription 1'
    scriptType: pscore
    scriptLocation: inlineScript
    inlineScript: |
     [CmdletBinding()]
     param (
         [string]$location,
         [string]$resourceGroupName,
         [string]$storageAccount,
         [string]$storageSku
     )
     
     Write-Output "Creating resource group..."
     az group create `
         --location $location `
         --name $resourceGroupName 
     
     Write-Output "Creating storage account..."
     az storage account create `
         --name $storageAccount `
         --resource-group $resourceGroupName `
         --location $location `
         --sku $storageSku 
    arguments: '-resourceGroupName "$(resource-group-name)" -location "$(location)" -storageAccount "$(storage-account-name)" -storageSku "$(storage-sku)"'

Create a Web App Resource:

Use Create Resource Group (az group create) with Create App Service Plan (az appservice plan create) and Create Web App (az webapp create ( + config and update)).

Create a Web App Resource YAML:

variables:
  resource-group-name: 'iac-demo'
  location: 'centralus'
  app-service-plan-name: 'iac-demo-service-plan'
  web-app-name: 'iac-demo-web-app'
  pricing-tier: 'B1'

steps:
- task: [email protected]
  displayName: 'Azure CLI - Create Web App Resource'
  inputs:
    azureSubscription: 'Azure subscription 1'
    scriptType: pscore
    scriptLocation: inlineScript
    inlineScript: |
     [CmdletBinding()]
     param (
         [string]$location,
         [string]$resourceGroupName,
         [string]$appServicePlanName,
         [string]$webAppName,
         [string]$runtime,
         [string]$pricingTier
     )
     
     Write-Output "Creating resource group..."
     az group create `
       --location $location `
       --name $resourceGroupName
     
     Write-Output "Creating service plan..."
     az appservice plan create `
       --is-linux `
       --name $appServicePlanName `
       --resource-group $resourceGroupName `
       --sku $pricingTier `
       --location $location
     
     Write-Output "Creating web app..."
     az webapp create `
       --name $webAppName `
       --resource-group $resourceGroupName `
       --plan $appServicePlanName `
       --runtime $runtime
     
     Write-Output "Setting api options..."
     az webapp config set `
       --resource-group $resourceGroupName `
       --name $webAppName  `
       --min-tls-version "1.2" `
       --linux-fx-version $runtime
     
     Write-Output "Setting api to HTTPS only..."
     az webapp update `
       --resource-group $resourceGroupName `
       --name $webAppName `
       --set httpsOnly=true
     
    arguments: '-resourceGroupName $(resource-group-name) -location $(location) -appServicePlanName $(app-service-plan-name) -webAppName $(web-app-name) -runtime ''"DOTNETCORE|3.1"'' -pricingTier $(pricing-tier)'

Create an Azure Table Resource:

Use Create Resource Group (az group create) with Create Storage Account (az storage account create) and Create Azure Table (az storage table create ( + a call to get the storage account connection string)).

Create an Azure Table Resource YAML:

variables:
  resource-group-name: 'iac-demo'
  storage-account-name: 'khsiacdemo'
  azure-table-name: 'Weather'
  storage-sku: 'Standard_LRS'
  location: 'centralus'

steps:
- task: [email protected]
  displayName: 'Azure CLI - Create Azure Table Resource'
  inputs:
    azureSubscription: 'Azure subscription 1'
    scriptType: pscore
    scriptLocation: inlineScript
    inlineScript: |
     [CmdletBinding()]
     param (
         [string]$location,
         [string]$resourceGroupName,
         [string]$storageAccount,
         [string]$azureTableName,
         [string]$sku
     )
     
     Write-Output "Creating resource group..."
     az group create `
         --location $location `
         --name $resourceGroupName 
     
     Write-Output "Creating storage account..."
     az storage account create `
         --name $storageAccount `
         --resource-group $resourceGroupName `
         --location $location `
         --sku $sku 
     
     Write-Output "Get connection-string..."
     $response = az storage account show-connection-string `
         --name $storageAccount `
         --resource-group $resourceGroupName | ConvertFrom-Json
     
     $connectionString = $response.connectionString
     
     Write-Output "Creating azure table..."
     az storage table create `
         --name $azureTableName `
         --connection-string "$connectionString"
    arguments: '-resourceGroupName $(resource-group-name) -storageAccount $(storage-account-name) -azureTableName $(azure-table-name) -sku "$(storage-sku)" -location "$(location)"'

When you are all done, make sure you click Save in the upper right-hand corner.

To run the Release, click Create Release in the upper right corner. Then, go to the Release and click Deploy.

The Result

After a successful Release run, you will see the following over in your Azure Portal.

Storage Account

App Service Plan

Web App

Azure Table

By adding Variables for each Stage, this process allows you to create a repeatable environment and a set of Azure Resources whenever needed.

Going further, you can create Task Groups, which will allow these Tasks to be included in any Release Pipeline.

In Summary

Hopefully, this quick dive into IaC and Azure CLI has been helpful for you. My goal was to at least peak your interest to automate a few things around Azure Resources!

Your DevOps teams can work better together using a good set of practices and tools to deliver applications and their supporting infrastructures quickly, reliably, and to scale.

Addition Resources

5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments