Introduction:
Terraform is an Infrastructure-as-Code (IAC) tool that enables users to define and deploy infrastructure resources like computing, storage, and networking using simple, human-readable configuration files. In this blog, we will provide an overview of the steps for deploying infrastructure in Azure using Terraform and Azure DevOps pipelines.
How Terraform Works?
Terraform manages cloud resources and services via APIs.
main.tf: This is the main configuration file where we define our resources.
variables.tf: We are going to define our variables in this file.
outputs.tf: This file contains output definitions for our resources.
backend.tf: Specifies the path where Terraform stores its state data files for the current infrastructure. Terraform keeps track of the managed resources. This state can be stored locally or remotely(remote backend).
The State File: Contains full details of resources in our terraform code. When you modify and apply something to your code to the cloud, Terraform will look into the state file and compare the changes made in the code from that state file and the changes to the infrastructure based on the state file.
When you run the Terraform apply command to create an infrastructure on the cloud, Terraform creates a state file called “terraform.tfstate"
version.tf: Terraform will check the version of the installed Terraform binary that executes the Terraform configuration.
terraform.tfvars: Systematic management of variable assignments is possible by using files with the extensions .tfvars or .tfvars.json. There are a couple of other ways of doing this, such as via environment variables passed through the CLI command etc.
Terraform core → Core is responsible for the life cycle management of infrastructure.
Terraform Provider → A plugin for Terraform that makes a collection of related resources available.
Terraform Flow
1. Initialize the Terraform Provider
Initializes the Terraform working directory, downloading any necessary provider plugins.
Command used:
terraform init
2. Run Terraform Plan
The “terraform plan” command helps you to review the changes that Terraform intends to make to your infrastructure. Before making any changes, Terraform creates a plan that shows you what it will do. In creating the plan, Terraform checks the existing state of remote objects first to ensure that everything is up-to-date. By previewing the plan, you can see which changes will be made before they happen.
Command used:
terraform plan
3. Run Terraform Apply
Create the cloud resources defined in your Terraform configuration and update the state file to match the desired state of infra with the actual state of infrastructure.
Command used:
terraform apply
Demo Preparation
Import Terraform repository
You start with the important repository below with the Terraform code in your Azure DevOps Repo. Please make the changes to the tfvars file and backend file as per your requirements.
https://github.com/SaiKiranDuddula/Terraform-AzureDevOps-Sample
Setup the remote backend
You can use the below Azure CLI commands to set the terraform remote backend, or you can do it via the portal.
#!/bin/bash
## The Storage account name must be unique, and the values below should match your backend.tf
RESOURCE_GROUP_NAME=demo-resources
STORAGE_ACCOUNT_NAME=azurewithsai
CONTAINER_NAME=prod-tfstate
# Create resource group
az group create --name $RESOURCE_GROUP_NAME --location canadacentral
# Create storage account
az storage account create --resource-group $RESOURCE_GROUP_NAME --name $STORAGE_ACCOUNT_NAME --sku Standard_LRS --encryption-services blob
# Create blob container
az storage container create --name $CONTAINER_NAME --account-name $STORAGE_ACCOUNT_NAME
Optionally, you can validate the terraform configuration using the below CLI commands:
## 1) login to the CLI
az login --use-device-code
### 2) set alias
alias tf=terraform
### 3) initialize the providers
tf init
### 4) Run the plan
tf plan
### 5) Apply the changes
tf apply --auto-approve
Let's Implement this using Azure DevOps
We will run all the steps, such as code checkout, tf init, tf plan, and tf apply, as part of the Azure DevOps pipeline, as shown in the diagram below.
We will be using the Azure DevOps build pipeline for terraform pre-requisites and planning, and the Azure DevOps Release pipeline to run the terraform apply for resource provisioning into multiple Azure environments.
Build Pipeline
Below is the YAML code for Build Pipeline:
trigger:
- main
stages:
- stage: Build
jobs:
- job: Build
pool:
vmImage: 'ubuntu-latest'
steps:
- task: TerraformTaskV4@4
displayName: Tf init
inputs:
provider: 'azurerm'
command: 'init'
backendServiceArm: '${SERVICECONNECTION}'
backendAzureRmResourceGroupName: 'demo-resources'
backendAzureRmStorageAccountName: 'azurewithsai'
backendAzureRmContainerName: 'prod-tfstate'
backendAzureRmKey: 'prod.terraform.tfstate'
- task: TerraformTaskV4@4
displayName: Tf validate
inputs:
provider: 'azurerm'
command: 'validate'
- task: TerraformTaskV4@4
displayName: Tf fmt
inputs:
provider: 'azurerm'
command: 'custom'
customCommand: 'fmt'
outputTo: 'console'
environmentServiceNameAzureRM: '${SERVICECONNECTION}'
- task: TerraformTaskV4@4
displayName: Tf plan
inputs:
provider: 'azurerm'
command: 'plan'
commandOptions: '-out $(Build.SourcesDirectory)/tfplanfile'
environmentServiceNameAzureRM: '${SERVICECONNECTION}'
- task: ArchiveFiles@2
displayName: Archive files
inputs:
rootFolderOrFile: '$(Build.SourcesDirectory)/'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
replaceExistingArchive: true
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: '$(Build.BuildId)-build'
publishLocation: 'Container'
Release Pipeline
We will also add a destroy stage to destroy the resources once our demo is completed with a pre-deployment approval step.
Below is the structure of the Terraform stage of the Release pipeline:
Below is the structure of the destroy stage of the Release pipeline:
Conclusion:
In summary, Terraform empowers users to orchestrate infrastructure deployments efficiently through code, streamlining processes and enhancing collaboration. By integrating Terraform with Azure DevOps pipelines, teams can automate the provisioning of resources in Azure, enabling rapid, consistent, and scalable infrastructure deployment with ease.