How to: Terraform Locking State in S3

tl;dr Terraform, as of v0.9, offers locking remote state management. To get it up and running in AWS create a terraform s3 backend, an s3 bucket and a dynamDB table.

Intro

Terragrunt first provided a great way to lock remote terraform state files in AWS with an S3 bucket and a dyanmoDB table. Then in v0.9, Terraform added this functionality as well, so in this blog I will be showing how to set up remote state management with locking using Terraform not Terragrunt.

Whats in the state file?

Here is an example of creating a DNS zone with Terraform along with its state file:

# example.tf# create a DNS zone called example.com
resource "aws_route53_zone" "example_dns_zone" {
name = "example.com"
}
# terraform.tfstate# in the state file, the DNS zone ID along with its name is stored
"aws_route53_zone.example_dns_zone": {
"type": "aws_route53_zone",
"primary": {
"id": "Z2D3OUXZHH4NUA",
"attributes": {
"name": "example.com"
}
}
},

Store State Remotely in S3

You can create an s3 bucket in a terraform config like so:

# example.tfprovider "aws" {
region = "us-west-2"
}
# terraform state file setup
# create an S3 bucket to store the state file in
resource "aws_s3_bucket" "terraform-state-storage-s3" {
bucket = "terraform-remote-state-storage-s3"

versioning {
enabled = true
}

lifecycle {
prevent_destroy = true
}

tags {
Name = "S3 Remote Terraform State Store"
}
}

Then create the s3 backend resource like so:

# terraform.tfterraform {
backend “s3” {
encrypt = true
bucket = "terraform-remote-state-storage-s3"
region = us-west-2
key = path/to/state/file
}
}

What is locking and why do we need it?

Create the dynamoDB table like this:

# example.tf# create a dynamodb table for locking the state file
resource "aws_dynamodb_table" "dynamodb-terraform-state-lock" {
name = "terraform-state-lock-dynamo"
hash_key = "LockID"
read_capacity = 20
write_capacity = 20

attribute {
name = "LockID"
type = "S"
}

tags {
Name = "DynamoDB Terraform State Lock Table"
}
}

You will need to modify the Terraform S3 backend resource and add in the dynamoDB table:

# terraform.tfterraform {
backend “s3” {
encrypt = true
bucket = "terraform-remote-state-storage-s3"
dynamodb_table = "terraform-state-lock-dynamo"
region = us-west-2
key = path/to/state/file
}
}

Putting pieces together:

Jessica$ cat .terraform/terraform.tfstate
{
"version": 3,
"backend": {
"type": "s3",
"config": {
"bucket": "terraform-remote-state-storage-s3",
"dynamodb_table": "terraform-state-lock-dynamo",
"encrypt": true,
"key": "example/terraform.tfstate",
"region": "us-west-2"
}
}
}

Helpful Resources:

Terragrunt blog about Terraform

--

--

Live simply. Program stuff.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store