Terraform Unlock: A Step-by-Step Guide

·

4 min read

Terraform is a powerful tool for managing infrastructure as code. It can be used to create, update, and destroy infrastructure resources in a variety of cloud providers. One of the features of Terraform is state locking. State locking ensures that only one process can be modifying the state at a time. This prevents race conditions and ensures that the state is always consistent.

So now the story time,

I recently had the opportunity to create a Redis instance using Terraform. The Terraform script worked fine locally, but when I ran it in an Azure pipeline, it failed with the following error message:

/opt/hostedtoolcache/terraform/1.1.8/x64/terraform plan -var-file=input.live.tfvar -out 142747.1.live.tfplan -detailed-exitcode

│ Error: Error acquiring the state lock

│ Error message: state blob is already locked

│ Lock Info:

│ ID: 07afbff1-d414-e1ad-e326-0d9af3fa0133

│ Path: terraform/patientinfo.live.tfstate

│ Operation: OperationTypePlan

│ Who: vsts@fv-az633-616

│ Version: 1.1.8

│ Created: 2023-04-11 06:12:10.635685982 +0000 UTC

I was puzzled by the issue, but after searching the internet, I was able to find a solution. In this blog post, we will look at the Terraform state and how to resolve this error in the pipeline.

So now the basics,

The Terraform state is a file that stores information about the resources that have been created by Terraform. This information includes the resource names, types, and configurations. The state file is used by Terraform to track changes to the infrastructure and to ensure that resources are created and updated in a consistent manner

The lock is implemented using a state file stored in a backend storage system such as Amazon S3 / HashiCorp Consul / Azure storage explorer.

The Terraform state file is not stored in the repository because it is sensitive and could be changed by anyone who has access to the repository. The state file contains information about the resources that have been created by Terraform, and it could be used to make changes to the infrastructure without authorization.

The state file is typically stored in a remote location, such as an S3 bucket or a Azure storage account. This ensures that it is only accessible to authorized users, and it prevents it from being accidentally or maliciously modified.

Terraform checks the state file to ensure that no other user is currently modifying the same resource. This is done to prevent conflicts and ensure that the infrastructure is in a consistent state.

In the case of Azure Storage Explorer, the state file is stored in the Azure Storage account. Terraform checks the state file before making any changes to the resources in the account. If another user is currently modifying the same resource, Terraform will wait until the other user is finished before making its changes. This ensures that the changes made by Terraform are not overwritten by the changes made by the other user

However, in some cases, the lock may become stuck due to a previous failure (This is what happened to me) or a terminated process. This can prevent other users from making changes, even if the previous process is no longer running. In such cases, Terraform provides the terraform force-unlock command to release the lock and allow other users to proceed with changes.

So in these case we needed to unlock the state manually.

It is important to note that using terraform force-unlock should only be done as a last resort, as it can lead to data loss or corruption if used improperly. Before using this command, it is important to ensure that the previous process is no longer running and that no other user is currently making changes.

To use terraform force-unlock, simply run the following command:

terraform force-unlock LOCK_ID

Where LOCK_ID is the unique identifier of the lock to be released. This can be obtained by running the terraform state list command or from the error message in my case, I got the lock Id from the error message.

The above can be easily achieved while testing locally, but in the case of Azure Pipelines, we need to configure the Terraform task in the Azure Pipelines project.

- task: charleszipp.azure-pipelines-tasks-terraform.azure-pipelines-tasks-terraform-cli.TerraformCLI@0
    displayName: 'terraform unlock'
    inputs:
       workingDirectory: '$(Pipeline.Workspace)/terraform/'
       environmentServiceName: ${{ parameters.azureSubscription }}
       command: 'forceunlock'
       allowTelemetryCollection: true
       lockID: '***Give your LockId***'

Always remember to unlock the Terraform state file after initializing Terraform.

In conclusion, Terraform's locking mechanism is an important feature that ensures safe modifications to infrastructure. While rare, stuck locks can occur, and the terraform force-unlock command can be used to release them. However, this command should only be used as a last resort and with caution to avoid data loss or corruption