In nowadays, using Terraform to deploy resources is becoming more and more popular and
in demand, and if you are looking for a new job as DevOps the first thing you will be
asked about is: do you use Terraform ?.
In this blog post, I’m going to show you how to use Terraform with Azure DevOps, and in a next
blog post (or video) I will share with you how I claimed the Terraform associate exam.
First of all, what is Terraform?
Terraform is an open-source infrastructure as a code software tool that provides a consistent CLI workflow to manage hundreds of cloud services. Terraform codifies cloud APIs into declarative configuration files.
Now, what’s Azure DevOps ??
Server (formerly Team Foundation Server (TFS) and Visual Studio Team System (VSTS)) is a Microsoft product that provides version control (either with Team Foundation Version Control (TFVC) or Git), reporting, requirements management, project management (for both agile software development and waterfall teams), automated builds, testing and release management capabilities.
What do we need to do first before Start deploying?
1-State File :
As you know, if you have used a bit Terraform we need to save the state file on Cloud to map azure resources to the configuration that we want to deploy, for that we are going to save it in the azure storage account container.
Note : we don’t need to store tfstate on the cloud even on-prem would work fine , however, working on the tfstate on the team will need that to be shared and here I’m considering we are working on a team project.
2-DevOps :
In order to have a clear vision, we are going to create a brain new project for the demo and we are going to see how to give access to the project to Azure by using Azure services principal
3-Terraform :
Well, in this part we are going to create a simple Terraform code to :
- Create a storage account container to save the State file :
In this part, I’m going to share a few power shell commands that will create a resource group and a storage account ( you will find all source code used in this blog post inside my GitHub repo )
# you can use this command to get the list of all the locations #Get-AzLocation | select Location ## Input Parameters $resourceGroupName="terraformdemoachraf2021" $storageAccName="achrafterraform2021" $storageContainerName="container2021" $location = "francecentral" ## Connect to Azure Account #if you are already connected you don't need this command else you will need to connect and also select the propriate subscription #Connect-AzAccount ## Function to create the storage container Function CreateStorageContainer { Write-Host -ForegroundColor Green "Creating resource groupe.." New-AzResourceGroup -Name $resourceGroupName -Location $location Write-Host -ForegroundColor Green "Creating storage account.." New-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccName -Location $location -SkuName Standard_LRS Write-Host -ForegroundColor Green "Creating storage container.." ## Get the storage account in which container has to be created $storageAcc=Get-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccName ## Get the storage account context $ctx=$storageAcc.Context ## Check if the storage container exists if(Get-AzStorageContainer -Name $storageContainerName -Context $ctx -ErrorAction SilentlyContinue) { Write-Host -ForegroundColor Magenta $storageContainerName "- container already exists." } else { Write-Host -ForegroundColor Magenta $storageContainerName "- container does not exist." ## Create a new Azure Storage Account New-AzStorageContainer -Name $storageContainerName -Context $ctx -Permission Container } } CreateStorageContainer ## Disconnect from Azure Account #Disconnect-AzAccount
- Azure DevOps project :
To deploy Terraform using azure DevOps, we are going to create a new project, and we are going to name it :
AzureDemoTerraform
First , we need to go to azure devops .
- Azure Service Principal :
The Azure service principal is used as an identity to authenticate you within an azure subscription to allow you to deploy the infrastructure that we are going to create based on Terraform code.
It’s quite simple, we are going to follow a couple of steps, first by going to project settings
than we look for service connection :
Now let’s add the connection :
In the next step, make sure to choose the right subscription where we have created the storage account and also make sure to choose the resource group that contains the storage account (earlier when we have used the power shell script we have named our resource group: terraformdemoachraf2021 )
The Service connection name in yellow we are going to use later, make sure to save it and click save.
Now after we did that we need to add our SPN access as a contributor to our subscription
so it can create resources.
Now we need to go to our subscription and add this as a contributor for ROLE.
Terraform…Here we GO!
Now with everything ready, all we need to do is to write our terraform configuration
Ps: I will explain all source code here.
provider "azurerm" { # The "feature" block is required for AzureRM provider 2.x. # If you're using version 1.x, the "features" block is not allowed. version = "~>2.0" features {} } terraform { backend "azurerm" {} } data "azurerm_client_config" "current" {} #here we are going to create a new resource groupe called : hellodemo-01 resource "azurerm_resource_group" "achrafrg" { name = "hellodemo-01" location = "francecentral" } #in the previous group now we are going to create a storage account named demostorage01 resource "azurerm_storage_account" "demoachraf" { name = "demostorage01" resource_group_name = azurerm_resource_group.achrafrg.name location = azurerm_resource_group.achrafrg.location account_tier = "Standard" account_replication_type = "LRS" }
Now the next step is to push our code to Azure Repos :
It’s Time to enable Terraform for Azure DevOps :
This is a one-time step, is to enable Azure DevOps for our project, we need to install Terraform Extension from here that will allow us to run
Terraform tasks (Init ,validate,plan,apply ,destroy).
How to Setup the pipeline?
Now to start this step is so easy, with the help and guidance of Azure DevOps you can set up your build by clicking on “Setup up Build” :
Next, you will be redirected to choose your pipeline and here we are going to choose
Starter pipeline.
Now what are we going to here is we are going to create our own YAML configuration
So , basically, we are going to validate and deploy our infrastructure, if the validation step is
successfully we will go to the deploy task.
Remember when earlier I said we need to save the data for the state file storage account and for the service connection?
Now we are going to need them.
stages : - stage: validate jobs: - job: validate continueOnError: false steps: - task: TerraformInstaller@0 displayName: 'install' inputs: terraformVersion: '0.12.3' - task: TerraformTaskV1@0 displayName: 'init' inputs: provider: 'azurerm' command: 'init' backendServiceArm: 'terraformdemoachraf2021SPN' backendAzureRmResourceGroupName: 'terraformdemoachraf2021' backendAzureRmStorageAccountName: 'achrafterraform2021' backendAzureRmContainerName: 'container2021' backendAzureRmKey: 'terraform.tfstate' - task: TerraformTaskV1@0 displayName: 'validate' inputs: provider: 'azurerm' command: 'validate' - stage: deploy jobs: - deployment: deploy_terraform continueOnError: false environment: 'dev' strategy: runOnce: deploy: steps: - checkout: self - task: TerraformInstaller@0 displayName: 'install' inputs: terraformVersion: '0.12.3' - task: TerraformTaskV1@0 displayName: 'init' inputs: provider: 'azurerm' command: 'init' backendServiceArm: 'terraformdemoachraf2021SPN' backendAzureRmResourceGroupName: 'terraformdemoachraf2021' backendAzureRmStorageAccountName: 'achrafterraform2021' backendAzureRmContainerName: 'container2021' backendAzureRmKey: 'terraform.tfstate' - task: TerraformTaskV1@0 displayName: 'plan' inputs: provider: 'azurerm' command: 'plan' environmentServiceNameAzureRM: 'terraformdemoachraf2021SPN' - task: TerraformTaskV1@0 displayName: 'apply' inputs: provider: 'azurerm' command: 'apply' environmentServiceNameAzureRM: 'terraformdemoachraf2021SPN'
Now, everything is ready to let’s wait for our pipeline to finish
Now let’s go and check if the resources have been created or not!
ok, now what if we want to add a website or maybe delete the already created infrastructure,
will this be automatically updated?
The answer is yes!
For that, we are going to update our source code as below and we are going to push
it to the repo, we are going to remove the storage account and we are going to create a web app for that we need an app service plan and app service
provider "azurerm" { # The "feature" block is required for AzureRM provider 2.x. # If you're using version 1.x, the "features" block is not allowed. version = "~>2.0" features {} } terraform { backend "azurerm" {} } data "azurerm_client_config" "current" {} #here we are going to create a new resource groupe called : hellodemo-01 resource "azurerm_resource_group" "achrafrg" { name = "hellodemo-01" location = "francecentral" } # # #in the previous group now we are going to create a storage account named demostorage001 # resource "azurerm_storage_account" "demoachraf" { # name = "demoachrafstorage0001" # resource_group_name = azurerm_resource_group.achrafrg.name # location = azurerm_resource_group.achrafrg.location # account_tier = "Standard" # account_replication_type = "LRS" # } resource "azurerm_app_service_plan" "example" { name = "terrafplanwebapp" location = azurerm_resource_group.achrafrg.location resource_group_name = azurerm_resource_group.achrafrg.name sku { tier = "Standard" size = "S1" } } resource "azurerm_app_service" "example" { name = "appnameusingterraform2021" location = azurerm_resource_group.achrafrg.location resource_group_name = azurerm_resource_group.achrafrg.name app_service_plan_id = azurerm_app_service_plan.example.id site_config { dotnet_framework_version = "v4.0" scm_type = "LocalGit" } }
well as you can see the build has started and when we click on Plan we can see
the real changes here that will be done are marked in green for adding and red for “destroyed” or deleted
and as you can see our resources have been created successfuly =)
Hope you enjoyed this tutorial =)
Full sources: Link
I’ve tried to follow these steps, but I come unstuck at the point of creating the starter YML file and the next step of running it as when I add the stages code everything fails, so bit confused as to where to add this code.
any help would be great or documentation updated to show the step in detail would be helpful
Hi ashley ,
You can find the source code in this link :
https://github.com/achrafbenalaya/TerraformDevOpsAzue