Terraform Remote State and Locking (Terraform Module)

As part of our migration to cloud, our team has been learning about DevOps tools and best practices.

We have picked Terraform as the tool to manage our Amazon AWS infrastructure, with a Collaborative IaC (Infrastructure as Code) workflow, which is well explained in the following page:
https://www.terraform.io/docs/enterprise/guides/recommended-practices/part1.html

A good practice is to leverage Terraform Remote State and Locking capabilities when working with large teams, this to improve efficiency and reduce the margin for errors and issues.

Terraform Remote State allows a team to store “state files” in a centralized remote location like Amazon S3. More about Terraform Remote State can be read here:
https://www.terraform.io/docs/state/remote.html

Additionally, Terraform Locking helps avoid situations where two team members attempt to deploy an infrastructure change at the same time, which could lead to conflicts and state corruption:
https://www.terraform.io/docs/state/locking.html

The following is a Terraform “template” module to create the required Amazon S3 bucket and DynamoDB table for this:


terraform {
  required_version = ">= 0.11.3"
}

###########
# S3 Bucket
###########
resource "aws_s3_bucket" "this" {
  acl    = "private"
  bucket = "${var.bucket}"
  region = "${var.region}"

  versioning {
    enabled = true
  }
}

########################
# DynamoDB Locking Table
########################
resource "aws_dynamodb_table" "this" {
  count = "${var.dynamodb_table != "" ? 1 : 0}"

  name            = "${var.dynamodb_table}"
  read_capacity   = 3
  write_capacity  = 3
  hash_key        = "LockID"

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

  tags {
    "Terraform" = true
  }
}

Following Terraform good practices, you could then create a new “live” module by extending the “template” module in the following way:


provider "aws" {
  region = "us-east-1"
}

module "s3statebucket" {
  source         = "[ path_to_your_template_module ]"
  region         = "us-east-1"

  bucket         = "[ your_s3_bucket_name ]"
  dynamodb_table = "[ your_dynamodb_table_name ]"
}

Please note DynamoDB locking is optional in the script, simply omit “dynamodb_table” if all you need is the S3 Bucket.

Leave a Reply

Your email address will not be published. Required fields are marked *