Use Terraform to manage infrastructure deployment

Azure Pipelines | Azure DevOps Server 2020 | Azure DevOps Server 2019 | TFS 2018

Azure Pipelines | Azure DevOps Server 2020 | Azure DevOps Server 2019 | TFS 2018

Terraform is an open-source infrastructure as code (IaC) tool to manage cloud services. Terraform can manage existing and popular cloud service providers as well as custom in-house solutions. Using Terraform you can define and provision your infrastructure components in config files using an easy to learn declarative language: HashiCorp Configuration Language (HCL).

In this tutorial, you will learn about:

  • The structure of a Terraform file
  • Building an application using an Azure CI pipeline
  • Deploying resources using Terraform and Azure CD pipeline

Prerequisites

  1. A Microsoft Azure account.
  2. An Azure DevOps account.
  3. Set up the demo project using the Azure DevOps Demo Generator.

Examine the Terraform config file

This tutorial uses the PartsUnlimited project, a sample eCommerce website developed using .NET Core. The Terraform config file defines the Azure resources required to deploy our web application.

  1. Select Repos then select the terraform branch.

    Selecting the terraform branch

  2. Find and select the webapp.tf configuration file in your repo and review its content. In this example, we define the Azure resources that will be used to deploy our web application. Some variables will be populated during run time.

      terraform {
       required_version = ">= 0.11" 
      backend "azurerm" {
       storage_account_name = "__terraformstorageaccount__"
         container_name       = "terraform"
         key                  = "terraform.tfstate"
     	access_key  ="__storagekey__"
       features{}
     	}
     	}
       provider "azurerm" {
         version = "=2.0.0"
     features {}
     }
     resource "azurerm_resource_group" "dev" {
       name     = "PULTerraform"
       location = "West Europe"
     }
    
     resource "azurerm_app_service_plan" "dev" {
       name                = "__appserviceplan__"
       location            = "${azurerm_resource_group.dev.location}"
       resource_group_name = "${azurerm_resource_group.dev.name}"
    
       sku {
         tier = "Free"
         size = "F1"
       }
     }
    
     resource "azurerm_app_service" "dev" {
       name                = "__appservicename__"
       location            = "${azurerm_resource_group.dev.location}"
       resource_group_name = "${azurerm_resource_group.dev.name}"
       app_service_plan_id = "${azurerm_app_service_plan.dev.id}"
    
     }
    

Azure build pipeline

This DevOps project includes two separate pipelines to build and deploy our web application. The build pipeline produces the artifacts that will be deployed by the release pipeline in the next section.

  1. Navigate to Pipelines and select the Terraform-CI pipeline.

    Select the build pipeline

  2. Select Edit to review the tasks included in the pipeline. The .NET Core tasks help restore dependencies, build, test, and publish the build output as a zip file to be deployed to an app service.

    Pipeline tasks

  3. The Copy files task copies the Terraform folder to the Artifact staging directory.

    Copy Terraform folder

  4. Select Queue then Run to queue and run your pipeline.

    Queue and run pipeline

Release pipeline

Now that we built our application, it's time to deploy it. However, no deployment infrastructure has been created yet. This is where Terraform comes in. By following the definition file reviewed earlier, Terraform determines what actions are necessary to achieve the state outlined in the config file.

  1. Navigate to Releases and select the Terraform-CD pipeline. Select Edit to review or edit the pipeline.

    Select release pipeline

  2. The release pipeline has been configured to consume the build artifact. Select the Dev stage to review or edit its tasks.

    Artifacts and stages

  3. There are eight tasks defined in the release stage. Most of them require some configuration to work with your Azure account. Select each task and enter your Azure subscription in the appropriate field.

    Dev stage tasks

  4. Select Agent job and set up the Agent pool and Agent specification.

    Set up agent pool and specification

  5. Select the Azure CLI task and add your Azure subscription.

    Set up the Azure CLI task

    This task executes a series of Azure CLI commands to set up some basic infrastructure required to use Terraform.

     # this will create Azure resource group
     az group create --location westus --name $(terraformstoragerg)
    
     az storage account create --name $(terraformstorageaccount) --resource-group $(terraformstoragerg) --location westus --sku Standard_LRS
    
     az storage container create --name terraform --account-name $(terraformstorageaccount)
    
     az storage account keys list -g $(terraformstoragerg) -n $(terraformstorageaccount)
    

    By default, Terraform stores state locally in terraform.tfstate. When working in a team environment, using a local file makes Terraform implementation more complicated. With remote state, Terraform writes the state data to a remote data store. In our example, the Azure CLI task creates an Azure storage account and a storage container to store the Terraform state. For more information on Terraform remote state, see Remote State.

  6. Select the Azure PowerShell task and set up the Azure Resource Manager and Azure subscription fields.

    Configure Azure PowerShell task

    This task uses a PowerShell script to retrieve the storage account key needed for the Terraform provisioning.

     # Using this script we will fetch storage key which is required in terraform file to authenticate backend storage account
    
     $key=(Get-AzStorageAccountKey -ResourceGroupName $(terraformstoragerg) -AccountName $(terraformstorageaccount)).Value[0]
    
     Write-Host "##vso[task.setvariable variable=storagekey]$key"
    
  7. Select the Replace tokens in terraform file task. If you recall the file reviewed earlier, there were several resources that were unknown at the time and marked with token placeholders, such as terraformstorageaccount. This task assigns values during run-time to some of the variables in the webapp.tf config file including those from the pipeline's Variables section.

    Replace tokens task

  8. The Install Terraform task installs and configures the specified version of Terraform on the agent for the remaining tasks.

    When running Terraform in automation, the focus is usually on the core plan/apply cycle. The next three tasks follow these stages.

    Terraform workflow

  9. The Terraform init task runs the init command to look through all of the *.tf files in the current working directory and automatically downloads any of the required providers. In this example, it will download Azure provider as it is going to deploy Azure resources.

    Set up the Azure subscription, container, and Key fields.

    Set up Terraform init task

  10. The Terraform plan task runs the plan command to create an execution plan by determining what actions are necessary to achieve the desired state specified in the configuration files. This is just a dry run and shows which actions will be performed.

    Enter your Azure subscription in the appropriate field.

    Set up Terraform plan task

  11. The Terraform apply task runs the apply command to deploy the resources. By default, it will also prompt for confirmation before applying. Since this is an automated deployment, the auto-approve argument is included.

    Enter your Azure subscription in the appropriate field.

    Set up Terraform apply task

  12. Select the Azure App Service Deploy task and enter your Azure subscription. By the time this task runs, Terraform has already ensured that the deployment environment has been configured to meet the app's requirements. It will use the $(appservicename) from the Variables section.

    Set up the app service deployment task

  13. Select Save then confirm.

  14. Select Create release and specify the recent build's Artifact then select Create.

    Create a release

  15. Select the new release to view the pipeline's execution.

    View release pipeline execution

  16. Once the release is completed, select the Azure App Service Deploy task.

    Select the Azure App Service Deploy task

  17. Copy the name of the app service from the task title.

    Copy the name of the app service

  18. Open a new browser tab and navigate to your deployed website. The domain format is [app service name].azurewebsites.net:

    https://pulterraformweb99ac17bf.azurewebsites.net.
    

    Navigate to the deployed website

Clean up resources

In this tutorial, we created a Azure DevOps project and few resources in Azure. If you're not going to continue to use these resources, you can follow these steps to delete them:

  1. Delete the Azure DevOps project created by the Azure DevOps Demo Generator.

  2. All Azure resources created during this tutorial were assigned to either the PULTerraform or terraformrg resource groups. Deleting those two groups will delete the resources they contain.

    az group delete --name PULTerraform
    az group delete --name terraformrg