Store Terraform state in Azure Blob Storage

In this blog post I walk through the process of storing the Terraform state file within an Azure blob storage account.

Store Terraform state in Azure Blob Storage
Store Terraform state in Azure Blob Storage

In this blog post I want to walk you through the process of configuring Terraform to use an Azure storage account to store and protect your Terraform state file.

When you use Terraform as your Infrastructure as Code language it writes the status of your resources to a state file. By default this file is called “terraform.tfstate” and it is stored locally. This state file is written in JSON format.

The file is automatically created by Terraform the first time the Terraform plan command is run. It will subsequently use the file to compare the it’s state with the target infrastructure changes.

The main advantage of storing your Terraform state file in an Azure storage account is state locking. Terraform will create a file lock on the state file when running the Terraform apply operation. This prevents other Terraform executions against the state file.

Create Azure Storage account

There are a number of ways to create the storage account you need for the Terraform state. In this example I am going to use Azure CLI commands, but you can use PowerShell, the Azure Portal website or even Terraform.

Head over to https://shell.azure.com this will launch the Azure CloudShell environment allowing you to create the storage account via Azure CLI.

Below are the commands that will create a new resource group, storage account and blob container. If you customise the four variables at the top to meet your needs you can copy and paste this into your CloudShell environment directly.

# Declare inputs
RESOURCE_GROUP_NAME=terraform
STORAGE_ACCOUNT_NAME=terraform$RANDOM
CONTAINER_NAME=terraformstate
LOCATION=ukwest

# Create resource group
az group create --name $RESOURCE_GROUP_NAME --location $LOCATION

# 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

We need to configure an authentication method so we can read and write data to the storage account. I am going to use a storage account access key. But you could use a service principal, managed service identity, or storage account SAS token.

Be sure to choose the right one that works for your environment and follow any procedures you have within your organisation.

You can use more Azure CLI commands to reveal the storage account key.

Head over to https://shell.azure.com

Paste in the following commands:

# Query Account Key
ACCOUNT_KEY=$(az storage account keys list --resource-group $RESOURCE_GROUP_NAME --account-name $STORAGE_ACCOUNT_NAME --query '[0].value' -o tsv)

# Output Account key
echo $ACCOUNT_KEY

The output should reveal a long account key, take a copy of this. You will need it in the next step.

💡
If you wish to continue your Terraform learning journey check out my new booked "Terraform for Ops". You can find more information at https://www.terraformforops.com

Create a Terraform template

We are now ready to create a Terraform template to deploy resources. I am going to be using my favourite editor, VS Code to create the template.

Opening a new file I put in the following Terraform:

provider "azurerm" {
features {}
}

This section declares that I am using the Azure RM Terraform provider.

The next section of the template to write is:

terraform {
  backend "azurerm" {
    resource_group_name      = "terraform"
    storage_account_name     = "terraform25130"
    container_name           = "terraformstate"
    key                      = "<accesskey>"
  }
}

This section is defining where I want to store the Terraform state file. It is populated from the information relating to the storage account we populated in the previous step, resource group name, storage account name, container name and the access key.

💡
It’s important to note that in a production environment I wouldn’t recommend having your storage account access key populated in plain text in your Terraform template.

The next section in our template is:

resource "azurerm_resource_group" "rg"{
    name = "rg_test"
    location = "westeurope"
    tags = {
        enviroment = "www.techielass.com"
    }
}

This section of the template instructs Terraform to create a new Azure resource group.

Deploy the Terraform template

With the template written it’s time to deploy it and create the resources. Open up your terminal and type in the command:

terraform init

The next command you want to type is:

terraform plan

This command shows you what is going to happen if you were to deploy the Terraform file. Now that the Terraform plan command has been executed, the state file is created in the container that was defined in the configuration file.

You can see the contents of the state file by issuing the following command:

terraform state pull
Terraform state pull command
Terraform state pull command

You can now continue to complete the deployment by typing in the command:

terraform apply -auto-approve

This will initiate the deployment, the -auto-approve command will avoid us having to type in yes to proceed with the deployment. If you don’t append the -auto-approve command then you would have to type in “yes” to deploy the resource.

After a few minutes you will get a confirmation message that the resource group has been created.

You have now successfully created a new resource within Azure and the Terraform state is updated and stored within the Azure storage account.

If you want to continue learning more about Terraform and using it as your Infrastructure as Code language do check out my other blogs.