Skip to main content

Command Palette

Search for a command to run...

DevOps Week 4 : Infrasturcture as Code and Terraform

Updated
6 min read
DevOps Week 4 : Infrasturcture as Code and Terraform
M

I'm experienced in designing scalable software architecture on a higher level and lower level implementation. Ensures the smooth functioning of technical operations by monitoring and evaluating staff progress. Involved in the training and recruitment process, works for company goals, and ensures overall client satisfaction.

In today’s cloud-centric world, managing infrastructure efficiently is crucial. Cloud providers like AWS, Azure, and Google Cloud offer APIs for automation, but working with these APIs directly can become complex, especially if you’re juggling multiple providers or transitioning between them. Enter Terraform by HashiCorp—a powerful tool designed to simplify infrastructure management through Infrastructure as Code (IaC).

Understanding Cloud Provider APIs and Automation

Cloud providers offer APIs for automating resource management—think provisioning, scaling, and configuring resources. Traditionally, scripts tailored to a specific provider's API (e.g., AWS CLI or Azure CLI) are used. However, if your organization changes its cloud provider or adopts a multi-cloud strategy, you'll face the challenge of rewriting these scripts to match the new provider’s API. This can lead to a tangled web of scripts and configurations, making management cumbersome.

Introduction to Terraform

Terraform is an open-source IaC tool that abstracts away the complexity of cloud provider APIs. Developed by HashiCorp, Terraform uses a high-level configuration language known as HashiCorp Configuration Language (HCL), written in .tf files. This approach allows you to define your infrastructure in a provider-agnostic manner, making it easier to switch providers or manage hybrid environments.

How Terraform Works

  1. Providers: Terraform uses "providers" to communicate with different cloud platforms. For example, when working with AWS, you configure the AWS provider in your .tf script. Switching to Azure requires configuring the Azure provider. Terraform manages the translation between your configuration and the provider-specific APIs.

  2. Plan and Apply: Terraform generates an execution plan based on your configuration. This plan outlines what changes will be made to your infrastructure. You review and approve this plan before Terraform applies it. The tool then translates your configuration into the necessary API calls, managing the lifecycle of resources effectively.

  3. State Management: Terraform maintains a state file that tracks the current state of your infrastructure. This state file helps Terraform understand what changes are necessary when you update your configuration, ensuring that your infrastructure aligns with your defined state.

Advantages of Terraform

  • Consistency: Provides a unified workflow for managing infrastructure across various cloud providers.

  • Modularity: Supports reusable code modules, simplifying complex setups.

  • Scalability: Suitable for both small and large-scale infrastructures.

  • Multi-Cloud and Hybrid: Facilitates the management of multi-cloud or hybrid environments with a single configuration file.

Drawbacks of Terraform

  • State Management: Requires careful handling of state files to prevent issues with resource drift and deployment inconsistencies.

  • Complexity with Large Setups: Managing extensive infrastructures and multiple modules can become intricate.

  • Learning Curve: New users may face a steep learning curve with Terraform’s advanced features.

  • Limited Support for Some Providers: Some cloud providers might have less mature Terraform support, leading to potential limitations.

Ideal Terraform Setup

To maximize Terraform’s benefits, consider these best practices:

  1. State Management: Use a remote state store like an S3 bucket with DynamoDB for state locking to ensure state file integrity.

  2. Modularity: Organize and reuse code with Terraform modules.

  3. Version Control: Store your Terraform code in a version control system such as Git.

  4. CI/CD Integration: Automate deployment by integrating Terraform with CI/CD pipelines.

  5. Secret Management: Manage sensitive data with tools like AWS Secrets Manager or HashiCorp Vault.

  6. Testing: Validate your infrastructure code using tools like terratest.

Terraform Hands-On: Setting Up Remote State and Creating an EC2 Instance

Let's walk through a practical example of using Terraform to set up a remote backend for storing state and provisioning an EC2 instance.

Prerequisites:

  • Install the latest version of Terraform.

  • Configure AWS CLI on your terminal.

To install Terraform on Ubuntu, add the HashiCorp GPG key to your system:

curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -

Next, add the official HashiCorp Terraform Linux repository to apt:

sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"

Then update apt and install Terraform:

sudo apt-get update && sudo apt-get install terraform

Once installed, verify the installation:

terraform -v

The command returns Terraform’s version information:

Terraform v1.6.4

Setup Steps:

  1. Create Directories:

     mkdir remote_state_setup remote_state_example
    
  2. Configure Remote Backend:

  • Navigate to remote_state_setup and create main.tf to define S3 and DynamoDB resources for state management:

  • Initialize and apply Terraform to create the S3 bucket and DynamoDB table:

# ------------------------------------------------------------------------------
# Main
# ------------------------------------------------------------------------------

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

  required_version = ">= 1.2.0"
}

provider "aws" {
  region = "ap-south-1"
}

# ------------------------------------------------------------------------------
# CREATE THE S3 BUCKET
# ------------------------------------------------------------------------------

data "aws_caller_identity" "current" {}

locals {
  account_id    = data.aws_caller_identity.current.account_id
}

resource "aws_s3_bucket" "terraform_state" {
  # With account id, this S3 bucket names can be *globally* unique.
  bucket = "${local.account_id}-terraform-states"

  # Enable versioning so we can see the full revision history of our
  # state files
  versioning {
    enabled = true
  }

  # Enable server-side encryption by default
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}


# ------------------------------------------------------------------------------
# CREATE THE DYNAMODB TABLE
# ------------------------------------------------------------------------------

resource "aws_dynamodb_table" "terraform_lock" {
  name         = "terraform-lock"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

# ------------------------------------------------------------------------------
# OUTPUT
# ------------------------------------------------------------------------------

output "s3_bucket_name" {
  value       = aws_s3_bucket.terraform_state.id
  description = "The NAME of the S3 bucket"
}

output "s3_bucket_arn" {
  value       = aws_s3_bucket.terraform_state.arn
  description = "The ARN of the S3 bucket"
}

output "s3_bucket_region" {
  value       = aws_s3_bucket.terraform_state.region
  description = "The REGION of the S3 bucket"
}

output "dynamodb_table_name" {
  value       = aws_dynamodb_table.terraform_lock.name
  description = "The ARN of the DynamoDB table"
}

output "dynamodb_table_arn" {
  value       = aws_dynamodb_table.terraform_lock.arn
  description = "The ARN of the DynamoDB table"
}
  •   cd remote_state_setup
      terraform init
      terraform plan
      terraform apply
    
  • Note the S3 bucket name for later use.

  1. Setup EC2 Instance with Remote State:

    • Navigate to remote_state_example and create main.tf for the EC2 instance:

        # ------------------------------------------------------------------------------
        # Main
        # ------------------------------------------------------------------------------
      
        terraform {
          required_providers {
            aws = {
              source  = "hashicorp/aws"
              version = "~> 4.16"
            }
          }
      
          required_version = ">= 1.2.0"
      
          backend "s3" {
            bucket  = "Your-s3-bucket-name"
            key     = "development/service-name.tfstate"
            encrypt = true
            region = "ap-south-1"
            dynamodb_table = "terraform-lock"
          }
      
        }
      
        provider "aws" {
          region = "ap-south-1"
        }
      
        # ------------------------------------------------------------------------------
        # CREATE THE EC2 instance
        # ------------------------------------------------------------------------------
      
        resource "aws_instance" "app_server" {
          ami           = "ami-0ad21ae1d0696ad58"
          instance_type = "t2.micro"
      
          tags = {
            Name = "Terraform_Demo"
          }
        }
      
        # ------------------------------------------------------------------------------
        # OUTPUT
        # ------------------------------------------------------------------------------
      
        output "aws_instance" {
          value       = aws_instance.app_server.id
          description = "the EC2 instance ID"
        }
      
    • Initialize and apply Terraform to create the EC2 instance:

        cd remote_state_example
        terraform init
        terraform plan
        terraform apply
      

It will create ec2 instance and will store the statefile remotely on s3 and will lock the file using dynamoDB

For more details look into my GitHub Repo: https://github.com/manjot-baj/DevOps/tree/main/Terraform

Conclusion

Terraform significantly simplifies managing infrastructure across various cloud providers or within a hybrid environment. By defining your infrastructure in a provider-agnostic way, Terraform handles the intricacies of API interactions, letting you focus on building and managing your infrastructure efficiently. Embracing best practices like remote state management, modularity, and CI/CD integration will ensure a scalable, secure, and manageable Terraform setup.

If you found this guide helpful, please give it a thumbs up and share it with your colleagues! Your feedback and support help me create more content like this. Feel free to leave a comment or reach out if you have any questions or need further assistance!