Terraform Remote Backend Configuration with S3 (Without DynamoDB)
Before diving into the main purpose, it’s essential to cover the fundamentals to build a solid foundation.
What’s Terraform ?
What is Terraform Backend ?
The Usual Practice:
Example of remote configuration block.
terraform {
backend "s3" {
bucket = "example-bucket"
key = "path/to/state"
region = "us-east-1"
dynamodb_table = "example-table"
}
}
Here, the backend is configured to use S3 for storing the Terraform state file.
While this approach works well to prevent overwrites and ensures state locking, it also introduces additional costs and creates a dependency on DynamoDB. For teams or projects aiming to minimize costs or simplify infrastructure, avoiding DynamoDB might be a more practical choice, though it requires extra caution to avoid state conflicts.
The New Approach:
Recent update from AWS. Amazon S3 now supports conditional writes (Link). Which means, that allows users to specify conditions under which certain write operations (like PUT, COPY, or DELETE) can be performed. This feature provides an extra layer of control and helps prevent accidental overwrites or deletions by ensuring that an operation only occurs if specific conditions are met.
领英推荐
Terraform now supports S3 native state locking
The latest release of Terraform v1.10.0 supports S3 native state locking.
“backend/s3: The s3 backend now supports S3 native state locking. When used with DynamoDB-based locking, locks will be acquired from both sources. In a future minor release of Terraform the DynamoDB locking mechanism and associated arguments will be deprecated.”
How does S3 native state locking works ? Refer this PR for more information (link)
Acquiring a Lock To acquire a lock, a .tflock file is uploaded to an S3 bucket to establish a lock on the state file. If the lock file does not already exist, the upload succeeds, thereby acquiring the lock. If the file already exists, the upload fails due to a conditional write, indicating that the lock is already held by another Terraform client.
Releasing a Lock To release a lock, the corresponding lock file is deleted from the S3 bucket. This action removes the file, thereby releasing the lock and making it available for other Terraform clients.
Now that we know it's possible to eliminate the use of DynamoDB by utilizing S3's native state locking functionality, let's proceed to create an S3 bucket to store the state file.
resource "aws_s3_bucket" "backend-24-test" {
bucket = "backend-24-test"
object_lock_enabled = true
tags = {
Name = "backend-24-test"
}
}
resource "aws_s3_bucket_versioning" "backend-24-test" {
bucket = "backend-24-test"
versioning_configuration {
status = "Enabled"
}
}
Follow the standard process: add the provider information, run terraform init, then terraform plan, and finally execute terraform apply.
After the bucket is created with object_lock_enabled, it can be used to store the state file.
Below is a sample snippet for configuring the remote backend to use S3:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.80.0"
}
}
backend "s3" {
bucket = "backend-24-test"
key = "backend/terraform.tfstate"
use_lockfile = true
encrypt = true
}
}
provider "aws" {
# Configuration options
region = "eu-west-1"
}
With this approach, we successfully eliminated the additional cost and dependency of DynamoDB in our Infrastructure as Code (IaC) setup.