Skip to main content

backend and lock

create S3 bucket and DynamoDB table

At first make tf file to build S3 bucket for backend to store state file and DynamoDB table for lock control

resource "aws_s3_bucket" "terraform_state" {
  bucket = "mybucketname"
  versioning {
    enabled = true
  }

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }

  # lifecycle {
  #   prevent_destroy = true
  # }

  tags = {
    Name = "terraform_backend"
  }
}

resource "aws_s3_bucket_public_access_block" "terraform_state" {
  bucket = aws_s3_bucket.terraform_state.bucket

  block_public_acls = true
  block_public_policy = true
  ignore_public_acls = true
  restrict_public_buckets = true
}

resource "aws_dynamodb_table" "terraform_state_lock" {
  name = "terraform_state_lock"
  read_capacity = 1
  write_capacity = 1
  hash_key = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}
variable "region" {
  default = "ap-northeast-1"
}

provider "aws" {
  region = var.region
  version = "~> 2.61.0"
}

terraform {
  required_version = ">= 0.12.26"
#  backend "s3" {
#    bucket = "mybucketname"
#    key    = "network/terraform.tfstate"
#    region = "ap-northeast-1"
#    dynamodb_table = "terraform_state_lock"
#  }
}

then initialize

terraform init 
terraform show

at last create bucket and table

terraform plan -out terraform.plan -no-color 
terraform apply "terraform.plan" -no-color 
terraform show

change backend to S3

at first edit tf file to enable S3 backend

terraform {
  required_version = ">= 0.12.26"
  backend "s3" {
    bucket = "mybucketname"
    key    = "network/terraform.tfstate"
    region = "ap-northeast-1"
    dynamodb_table = "terraform_state_lock"
  }
}

then initialize

terraform init -no-color 
aws s3api list-object-versions  --bucket mybucketname --prefix network/terraform.tfstate --query 'Versions[].{VersionId:VersionId, LastModified:LastModified}'

then you can use S3 backend

add tf file content to build aws resource

variable "cidr_block" {
  default = "10.0.0.0/16"
}

resource "aws_vpc" "terraform_test_vpc" {
  cidr_block           = var.cidr_block
  instance_tenancy     = "default"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "terraform_test"
  }
}

plan and apply as usual

terraform plan -no-color -out terraform.plan 
terraform apply "terraform.plan" 
terraform show

aws s3api list-object-versions  --bucket mybucketname --prefix network/terraform.tfstate --query 'Versions[].{VersionId:VersionId, LastModified:LastModified}'

remove all reosources other than S3 bucket and DynamoDB table

before change backend from S3 to local again, remove all other resources.

at first remove all aws resources from tf file other than S3 bucket for backend and DynamoDB table for lock control. then plan and apply

terraform plan -no-color -out terraform.plan 
terraform apply "terraform.plan" 
terraform show

change backend from S3 to local

comment out or remove backend from tf file

    terraform {
      required_version = ">= 0.12.26"
    #  backend "s3" {
    #    bucket = "mybucketname"
    #    key    = "network/terraform.tfstate"
    #    region = "ap-northeast-1"
    #    dynamodb_table = "terraform_state_lock"
    #  }
    }

then initialize.

terraform init -no-color 
ls -l terraform.tfstate

remove S3 tables and DynamoDB table

before remove them, make sure S3 bucket empty

aws s3api list-object-versions  --bucket mybucketname --prefix network/terraform.tfstate --query 'Versions[].{VersionId:VersionId, LastModified:LastModified}'
delete_objects=$(aws s3api list-object-versions --bucket mybucketname --prefix network/terraform.tfstate \
--query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}')
aws s3api delete-objects --bucket mybucketname --delete "${delete_objects}"

terraform destroy 
terraform show

Sample yaml file for stack of CloudFormation to build backend S3 bucket and DynamoDB table

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  BucketName:
    Type: String
  TableName:
    Type: String
Resources:
  BackendBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      BucketName: !Ref BucketName
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: AES256
      VersioningConfiguration:
        Status: "Enabled"
      Tags:
        - "Key": "Name"
          "Value": "test"
  LockctrlTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: !Ref TableName
      AttributeDefinitions:
        - AttributeName: "LockID"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "LockID"
          KeyType: "HASH"
      BillingMode: "PROVISIONED"
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1
      Tags:
        - Key: "Name"
          Value: "test"