Terraform: Create S3 bucket and DynamoDB table

Reading Time: 2 minutes

Let’s say you have a Template file (.yaml) that provisions resources to support Terraform Remote state backed by S3 and DynamoDB for consistency locking as below

AWSTemplateFormatVersion: "2010-09-09"
Description: Description is here
Parameters, Metadata, REsources are defined here
    Type: AWS::S3::Bucket
      BucketName: !Ref TerraformRemoteStateS3BucketName
      AccessControl: Private
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: 'aws:kms'
              KMSMasterKeyID: !Ref TerraformRemoteStateKMSKey
        Status: Enabled
          Key: Name
          Value: terrraform-remote-state-s3-bucket 

    Type: AWS::DynamoDB::Table
      TableName: !Ref TerraformRemoteStateTableName
          AttributeName: LockID
          AttributeType: S
         AttributeName: LockID
         KeyType: HASH
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
        SSEEnabled: true 
          Key: Name
          Value: terrraform-remote-state-lock-table

You can create AWS S3 bucket and DynamoDB table using Designer Template in AWS CloudFormation. Go to AWS Cloud Formation page and click Design template.

Copy and paste the content of the yaml file to the template section and create stack.

This image has an empty alt attribute; its file name is image-2-1024x465.png

After stack creation is done, go to the Resources section to check the status. The Physical Id section is the name of the resources that we are going to specify in the terraform commands section.

Check DynamoDB table

Assuming that you are in eu-west-2 zone, go to your AWS account and search the table. Table details looks like that.

DynamoDB table in Cloud Formation Stack

Check S3 bucket

You can check the bucket in your AWS zone.

Terraform commands

terraform init

The terraform init command is used to initialize a working directory containing Terraform configuration files. This is the first command that should be run after writing a new Terraform configuration or cloning an existing one from version control. It is safe to run this command multiple times.

We will use the config file, config.tfvars, to run terraform init command.

encrypt = true
bucket = "my-terraform-remote-state"
key = "state/state.tfstate"
dynamodb_table = "my-terraform-remote-state-lock-table"
region = "eu-west-2"
access_key = "your_access_key"
secret_key = "your_secret_key"
kms_key_id = "your_kms_id"  --> Go to Resources and copy the Physical ID of AWS::KMS::KEY in your stack

If you don’t specify kms_key_id correctly, you will get following error:

Initializing the backend…  Error loading state: failed to upload state: KMS.KMSInvalidStateException: arn:aws:kms:eu-west-2:XXXXXXXX:key/unique_number is pending deletion. status code: 400, request id: F52E6A6E33081A8E, host id: caUBtZC/yasdaddfgsafgasgsg=45674e67ehdgdsgh=

Initialize terraform using config.tfvars

tterraform init -backend-config=C:\DWP\homecare-terraform-aws\config.tfvars

You might have following error if terraform cannot create state/state.tfstate file in S3 bucket.

Terraform acquires a state lock to protect the state from being written by multiple users at the same time. Please resolve the issue above and try again. For most commands, you can disable locking with the "-lock=false" flag, but this is not recommended. 

Using -reconfigure option helped me to get rid of the error

terraform init -input=false -reconfigure -backend-config=C:\DWP\homecare-terraform-aws\config.tfvars

terraform plan

The terraform plan command is used to create an execution plan. Terraform performs a refresh, unless explicitly disabled, and then determines what actions are necessary to achieve the desired state specified in the configuration files. The result of the commond is as follows

terraform apply

The terraform apply command is used to apply the changes required to reach the desired state of the configuration, or the pre-determined set of actions generated by a terraform plan execution plan.

Leave a Reply

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