This note is in continuation to the previous one –Terraform Remote State -Part1: Using AWS, where I’ve covered the what and how of a terraform remote state. So that we are all on the same page, I’ll list down a few important points related to that:
-the current state of infrastructure as referred to by a terraform configuration is stored in a state file called terraform.tfstate
-the file gets created on command “terraform apply” and referred by each subsequent “terraform plan” command
-the default location of the terraform.tfstate file is the exact directory where the rest of the terraform configurations are stored
-terraform remote state refers to the storage of the terraform configuration state file in a location that assists automation, encourages collaboration, and enhances security
-configuring a remote-state is done by adding a backend block to the existing terraform configuration
In my previous post, I explored the idea of “terraform remote state” using AWS. In this post, I’ll list the steps to achieve the same using Azure.
As is standard, there are two pre-requisites to terraform remote state. Although it’s obvious, when I state pre-requisites, these are resources that should already exist before they are used in a particular Terraform configuration. In the case of Azure, they are – (i) a storage container to store the key (terraform.tfstate file) and (ii) access key to the storage container.
Step 1: Add the following block to existing terraform configuration file. I have seen repositories (on GitHub) where there is a separate file by the name of “backend.tf” where the backend configuration is stored. I believe storing backend configuration in a separate file keeps the configuration accessible and readable, rather than adding that block to an existing Terraform configuration.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
terraform { | |
backend "azurerm" { | |
resource_group_name = "$(ResourceGroupToStoreTerraformBackendResources)" | |
storage_account_name = "$(UniqueStorageAccountName)" | |
container_name = "$(StorageContainerName)" | |
key = "terraform.tfstate" | |
access_key = "$(StorageAccountAccessKey)" | |
} | |
} |
If you’ve worked on Azure, you know that every resource belongs to a resource group and that is what we set in $(ResourceGroupToStoreTerraformBackendResources). Terraform stores the key (terraform.tfstate) in a storage container $(StorageContainerName) that belongs to a storage account $(UniqueStorageAccountName) that belongs to a resource group $(ResourceGroupToStoreTerraformBackendResources). The $(StorageAccountAccessKey) is the storage account access key.
Note: If you recall, in AWS, we also stored a lock in a dynamoDB table to restrict concurrent access. In the case of Azure, that is not required since simultaneous access of the terraform.tfstate file is not allowed in a storage container.
Step 2: After the backend block is added to our Terraform configuration, we have to inform Terraform to initiate the backend. That is done with the “terraform init” command. Whether you already have an existing terraform.tfstate in your local workspace or initializing the configuration for the first time, we have to start with the “terraform init” command. Any subsequent changes made to the backend block should always be followed by a “terraform init”.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
– powershell: | | |
terraform init -backend-config="access_key=$(storage_access_key)" -no-color | |
workingDirectory: $(build.sourcesdirectory) | |
displayName: 'terraform init' | |
# where $(storage_access_key) is a secret variable stored in the Azure pipeline | |
# variable or a Library variable group. The value of the variable is the storage | |
# access key to the storage account where the terraform remote state file is stored |
Again, as is customary, I have a code repository (Terraform Azure RemoteBackend) where I demonstrate the backend configuration pointing to my Azure subscription. This repository has a backend.tf file with the details of an Azure backend. The skeleton code is to configure a Virtual network. The azure-pipelines.yaml file has all the Terraform steps in detail.
If you noticed, I did not mention service principal here. We do not require service principal credentials to store remote state in the storage container. We instead, use the storage account access key to do so. Terraform requires service principal credentials to interact with Azure cloud to provision resources. Particularly, service principal credentials are required at “terraform plan” step.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
– powershell: | | |
terraform plan -var client_id="$(client_id)" -var client_secret="$(client_secret)" -var subscription_id="$(subscription_id)" -var tenant_id="$(tenant_id)" -out application.tfplan -no-color | |
workingDirectory: $(build.sourcesdirectory) | |
displayName: 'terraform plan' | |
# where $(client_id) is the appID of the service principal, | |
# $(client_secret) is the password of the service princial, | |
# $(subscription_id) is the Azure subscription to which the service principal belongs, and | |
# $(tenant_id) is the tenant value of the service principal. | |
# These values can be stored in Azure pipeline variables or as a variable group in the Azure DevOps project. |
As I mentioned in my previous note -remote backend in Terraform is a crucial concept to understand as you move towards adopting an infrastructure-as-code mindset.
I hope you found this post helpful, and let me know if you have any questions or comments.
2 thoughts on “Terraform Remote State -Part 2: Using Azure”