Sai Umesh

Getting Started with Terraform Part - 1

11 min read

Terraform is an open-source Infrastructure as code software that helps you to create/update/delete Infrastructure.

You will be learning how to create Infrastructure using Terraform and some of its key features. We will be using AWS as our cloud provider and assuming you are already familiar with it.

This article towards beginners and expects no previous experience of Terraform. By the end of this book, you will be able to use Terraform to create Infrastructure.

Prerequisites

  1. An account with AWS cloud
  2. Experience in working with AWS cloud

Installation

  1. We will be using Terraform CLI to create infrastructure.
  2. If you are having multiple projects which require different versions, you can use tfswitch
  3. We will be using VSCode as our code editor with Terraform extension or This
  4. We will be using AWS as our cloud provider for creating Infrastructure using Terraform. You can create an AWS free tier account. Click here for more information.
  5. Configure AWS Account using its CLI.
    1. Installation -https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
    2. Configuring AWS - https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html#cli-configure-files-methods
    3. Test configuration - To test your AWS configuration run the following command and it should return your account id.
aws sts get-caller-identity

Output as follows

{
    "UserId": "XXXXXXXXX",
    "Account": "XXXXXXX",
    "Arn": "arn:aws:iam::XXXXXX:user/XXXXXXX"
}

More on Terraform

Language

Terraform uses HCL configuration language and every Terraform file ends with a .tf extension.

State

when you create infrastructure using Terraform, it creates a file terraform.tfstate. Terraform tracks changes made in code with state file. either it creates or destroys Infrastructure based on changes that were made.

Create S3 Bucket Using Terraform

Now let’s see how to create an S3 bucket using Terraform

let’s create a folder with the name terraform-S3 and add following content in main.tf

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "3.72.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "bucket" {
  bucket = "terraform-remote-state-test-bucket-example"
  tags = {
    Environment = "Development"
  }
}

now let’s break down the code

Terraform Block

Terraform supports multiple providers (AWS, Azure, GCP …) These providers are an abstraction of API to create infrastructure. for more information check here. We will be using AWS providers to create our infrastructure.

terraform {
  required_providers {
    AWS = {
      source = "hashicorp/aws"
      version = "3.72.0"
    }
  }
}

Provider Block

This block helps us to configure AWS Keys, regions, etc… when you are not defining keys explicitly, it will be reading default credentials from path ~/.aws/credentials.

# Configure the AWS Provider
provider "aws" {
  region = "us-east-1"
}

Resource Block

This defines one or more resources to create Infrastructure for a given provider. This is probably the most used Terraform feature. Terraform has tons of AWS prebuilt resources which can be found here.

resource "aws_s3_bucket" "bucket" {
  bucket = "terraform-remote-state-test-bucket-example"
  tags = {
    Environment = "Development"
  }
}

Commands

Init

Init: The following command will initialize Terraform project by Installing listed providers like AWS and its resources. It also creates a few of the folders like .terraform and .terraform.lock.hcl. For more information check here.

terraform init

The output should be as follow

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Installing hashicorp/aws v3.72.0...
- Installed hashicorp/aws v3.72.0 (signed by HashiCorp)

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Plan

Plan: The following command will give you the list of resources that will be created/updated/destroyed if you apply your configuration.

terraform plan

The output should be as follow

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_s3_bucket.b will be created
  + resource "aws_s3_bucket" "b" {
      + acceleration_status         = (known after apply)
      + acl                         = "private"
      + arn                         = (known after apply)
      + bucket                      = "terraform-remote-state-test-bucket-example"
      + bucket_domain_name          = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags                        = {
          + "Environment" = "Development"
        }
      + tags_all                    = {
          + "Environment" = "Development"
        }
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + versioning {
          + enabled    = (known after apply)
          + mfa_delete = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform
apply" now.

Apply

Apply: Following command will create infrastructure as configured and planned in earlier steps.

terraform apply

When you run the above command, it will plan and ask for confirmation.

terraform-S3 git:(master) ✗ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_s3_bucket.b will be created
  + resource "aws_s3_bucket" "b" {
      + acceleration_status         = (known after apply)
      + acl                         = "private"
      + arn                         = (known after apply)
      + bucket                      = "terraform-remote-state-test-bucket-example"
      + bucket_domain_name          = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags                        = {
          + "Environment" = "Development"
        }
      + tags_all                    = {
          + "Environment" = "Development"
        }
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + versioning {
          + enabled    = (known after apply)
          + mfa_delete = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:

Now enter yes to create Bucket and output should be as follow

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_s3_bucket.b: Creating...
aws_s3_bucket.b: Still creating... [10s elapsed]
aws_s3_bucket.b: Still creating... [20s elapsed]
aws_s3_bucket.b: Creation complete after 23s [id=terraform-remote-state-test-bucket-example]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Lets goto AWS console to confirm if S3 bucket has been created

Untitled

Destroy: Once we confirm with S3 bucket on console, run the following command to destroy it.

terraform destroy

The Output should be as follows

terraform-S3 git:(master) ✗ terraform destroy
aws_s3_bucket.b: Refreshing state... [id=terraform-remote-state-test-bucket-example]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # aws_s3_bucket.b will be destroyed
  - resource "aws_s3_bucket" "b" {
      - acl                         = "private" -> null
      - arn                         = "arn:aws:s3:::terraform-remote-state-test-bucket-example" -> null
      - bucket                      = "terraform-remote-state-test-bucket-example" -> null
      - bucket_domain_name          = "terraform-remote-state-test-bucket-example.s3.amazonaws.com" -> null
      - bucket_regional_domain_name = "terraform-remote-state-test-bucket-example.s3.amazonaws.com" -> null
      - force_destroy               = false -> null
      - hosted_zone_id              = "Z3AQBSTGFYJSTF" -> null
      - id                          = "terraform-remote-state-test-bucket-example" -> null
      - region                      = "us-east-1" -> null
      - request_payer               = "BucketOwner" -> null
      - tags                        = {
          - "Environment" = "Development"
        } -> null
      - tags_all                    = {
          - "Environment" = "Development"
        } -> null

      - versioning {
          - enabled    = false -> null
          - mfa_delete = false -> null
        }
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value:

Now enter yes to destroy Bucket and output should be as follows

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_s3_bucket.b: Destroying... [id=terraform-remote-state-test-bucket-example]
aws_s3_bucket.b: Destruction complete after 2s

Destroy complete! Resources: 1 destroyed.

Go to the AWS console to confirm if the S3 bucket has been deleted or you can run the following command to verify the same.

aws s3 ls

Sai Umesh

I’m Sai Umesh, a software engineer based in India. Working as a DevOps engineer.