top of page

Your First Deployment: The Essential Terraform Lifecycle

Now that we have covered the overview of Terraform, including how it works, tracks your infrastructure, and state files, we are going to transition from theory to practice moving forward with hands-on, step-by-step guide. Before we move any further, there are some prerequisites that we need to do. If you are already familiar and have set these up, please do skip the below section. Let me explain!


Prerequisites

You will need the following:

  1. Terraform installed as an executable Command Line Interface (CLI) on supported operating systems (OS), including macOS, Windows, and several Linux distributions. You can either install it manually or by using a Package Manager like Homebrew.

  2. An Amazon Web Services (AWS) account as I will be using Terraform to provision resources in AWS. For the purposes of these blogs, I am using AWS, but know that you can use other cloud providers to provision resources in. There will be costs associated with provisioning some of the resources within AWS. As best practice for these hands-on exercises, make sure you terminate provisioned resources at the end of each exercise to prevent unexpected charges. If you are interested, you might want to read this document and set up a budget to alert you when you are near the threshold ($$) you have set and/or when you have gone over.

  3. Install the AWS CLI as it would come in handy when accessing your AWS account programmatically.

  4. Credentials to access the AWS account including Terraform authentication and deploying resources. Make sure to follow AWS Security best practices when managing authentication, and access controls. Make sure to authenticate first before accessing the AWS account programmatically or when deploying resources.

  5. An Integrated Development Environment (IDE) that you are familiar and comfortable with. I am using VS Code.

  6. An Amazon Simple Storage Service (S3) bucket to be used as our remote backend. It will also be used for state locking as it can now be enabled via S3.


Create Infrastructure

Assuming that you have all of the above completed, let's dive right in:

  1. Create a new directory for your Terraform configurations and change into that directory. You can name it anything you want:

mkdir first-terraform-project && cd first-terraform-project
  1. We are going to keep things simple for now. Create a new file called providers.tf and this is where we are going to define our Terraform block including the required version, provider, and our S3 backend.

# providers.tf

# Terraform block
terraform {
    required_version = ">=1.2"

    required_providers {
       aws = {
        source = "hashicorp/aws"
        version = "~> 6.0"
       }
    }

    backend "s3" {
        bucket         = "<YOUR_UNIQUE_BUCKET_NAME"
        key            = "terraform/state"
        region         = "us-east-1"
        use_lockfile  = true
    }
}

# Provider configuration
provider "aws" {
    region = var.aws_region
}
  1. Run the terraform init command to initialise Terraform and install the plugins. Make sure you are in the project root directory and authenticated to AWS before running the command. You should see something like this as the output:

Fig1.1: Output from running terraform init command
Fig1.1: Output from running terraform init command

  1. In the project root directory, let's create our:

    - main.tf - will contain resource blocks which define the components of your infrastructure. It can also contain data blocks which are used to query your cloud provider for information about other resources. This keeps your configuration dynamic and avoid hardcoded values that can become stale.

    - outputs.tf - These are output values about your infrastructure that can expose information for other Terraform configurations to use. Similar to return values in programming languages.

    - variables.tf - contains the input variables which are like placeholders for values that you want to use in your configuration files. This allows for code reusability instead of hardcoding every value. They are defined in a variable block and then referenced elsewhere in your code.

  1. Let's work on our main.tf file. We will keep it simple by creating an S3 bucket using Terraform. An input variable has been referenced for the bucket name:

# Create an S3 bucket
resource "aws_s3_bucket" "first_bucket" {
  bucket = var.bucket_name
  force_destroy = true

  tags = {
    Name        = "First Terraform Project Bucket"
    Environment = "Development"
    ManagedBy  = "Terraform"
  }
}

# Create S3 bucket versioning
resource "aws_s3_bucket_versioning" "first_bucket_versioning" {
  bucket = aws_s3_bucket.first_bucket.id

  versioning_configuration {
    status = "Enabled"
  }
}

# Block public access to the S3 bucket
resource "aws_s3_bucket_public_access_block" "first_bucket_public_access_block" {
  bucket = aws_s3_bucket.first_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
  1. Now, let's create the variable block for our aws_region and bucket_name variables:

# Variables for Terraform Project
variable "aws_region" {
  type        = string
  description = "AWS Region"
  default     = "us-east-1"
}

variable "bucket_name" {
  type        = string
  description = "Name of the S3 bucket"
  default     = "first-terraform-project-s3bucket"
}
  1. Lastly, we would like to output the value of the S3 bucket name which can then be used by other configurations:

# Outputs for the Terraform project
output "bucket_name" {
  value       = aws_s3_bucket.first_bucket.bucket
  description = "The name of the S3 bucket created by this Terraform project."
}
  1. Now that our code has been authored, we will re-initialise Terraform and the run the plan command to see our execution plan. This shows what Terraform is going to create. We wil also introduce the terraform fmt command which formats our code:

terraform fmt

terraform init

terraform plan

You should have something similar to this as output. As you can see, 3 resources will be provisioned and our bucket name as the output:

Fig1.2: Output for terraform plan
Fig1.2: Output for terraform plan
  1. Once you are happy with what Terraform is going to execute, you can run the next command and approve for Terraform to provision the resources in your AWS account:

terraform apply 

# Need to approve
yes

You should see something similar in the terminal:

Fig1.3: Output from running terraform apply
Fig1.3: Output from running terraform apply

And in the AWS Management console, you should see the S3 bucket created:

Fig1.4: S3 bucket created in the AWS Management console
Fig1.4: S3 bucket created in the AWS Management console
  1. Yey Congratulations!!! You have created your first Terraform project. We will introduce more Terraform commands as we proceed so you understand when and where you can use them. I will add one now - terraform output command which will display all outputs if no output NAME is mentioned.

terraform output
  1. Now that we have completed our first Terraform project, lets delete everything so that we don't have to worry about costs. Run the destroy command to destroy the resources.

terraform destroy

# Need to approve
yes

You should see something similar in the terminal:

Fig1.5: Outputs from running terraform destroy command
Fig1.5: Outputs from running terraform destroy command

Summary

That brings us to the end of our first Terraform project where we authored our code, initialised and installed the plugins, ran the execution plan and then provisioned our resources in our AWS account. At the end, we made sure we deleted all created resources via the destroy command.


As a look forward, we will be building on this knowledge and look at modules. Until then, if you have any questions, feel free to ask in the comments or if you have any feedbacks, let me know.

Comments


bottom of page