Skip to main content

Terraform: Your Guide to Infrastructure as Code

6 mins·

In the classical era of system administration, provisioning a server meant logging into a web console, clicking dozens of buttons, and hoping you remembered every setting. If you needed ten identical servers, you repeated that process ten times. This approach was slow, prone to human error, and impossible to scale.

Then came Infrastructure as Code (IaC), and Terraform emerged as the industry standard.


1. What’s Terraform and Why Terraform?
#

Terraform is an open-source tool created by HashiCorp. It is an Infrastructure as Code (IaC) tool that allows you to define, provision, and manage both cloud and on-premise resources using human-readable configuration files.

Why is Terraform the Go-To Tool?
#

The primary reason is that Terraform is Declarative. You don’t write scripts telling the cloud how to build a server (like standard Bash or Python scripts). Instead, you write a configuration defining what the final infrastructure must look like. Terraform figures out the execution steps to reach that desired state.

Other key benefits include:

  • Cloud-Agnostic: It works seamlessly with AWS, Azure, Google Cloud, Kubernetes, VMware, and hundreds of other providers using the same workflow.
  • Immutable Infrastructure: It favors replacing resources over modifying them, reducing configuration drift.
  • Idempotence: You can run the same Terraform plan multiple times, and it will only apply the changes necessary to reach the final state. Running an identical plan a second time changes nothing.

2. Terraform Components and Architecture
#

To understand Terraform, you have to understand its internal anatomy.

The Engine and Core
#

Terraform’s Core is the main executable binary (written in Go). It’s responsible for the overall logic. It parses your configuration files, manages the state, and creates the Resource Graph—a dependency map that determines the correct order to create or destroy resources (e.g., ensuring the Network is built before the Virtual Machine).

How Providers Work
#

Terraform Core doesn’t actually know how to talk to AWS or Azure API. It uses Providers, which are plugins. The core communicates with these plugins via RPC (Remote Procedure Calls).

When you run an apply, Terraform sends generic instructions to the AWS Provider, which translates them into specific AWS API calls (like ec2:RunInstances). This plugin architecture is what allows Terraform to manage almost any service with an API.

State Management: The Source of Truth
#

The most critical component is the State File ($terraform.tfstate$). This JSON file acts as Terraform’s memory. It maps the resources defined in your code to the actual, real-world resources currently existing in your cloud account.

When you run a plan, Terraform compares your code against this state file to determine what needs to be changed. Protect this file: if you lose it, Terraform will lose track of your managed infrastructure.


3. Terraform Workflow
#

The classic Terraform workflow is a simple, iterative three-step process:

  1. Write: You write your infrastructure definitions in .tf files.
  2. Plan (terraform plan): The engine compares your code to the state file and generates an execution plan. It tells you exactly which resources will be + Created, ~ Updated, or - Destroyed. This is your dry run.
  3. Apply (terraform apply): Upon confirmation, Terraform calls the required providers to execute the plan and update the state file.

4. Every Code Component with Examples
#

Let’s look at the foundational blocks of a Terraform project, using AWS for our examples.

The Providers Block
#

Configures the plugin.

# providers.tf
provider "aws" {
  region = "us-east-1"
}

Variables
#

Allows you to inject dynamic inputs and avoid hard-coding.

# variables.tf
variable "instance_type" {
  type        = string
  default     = "t2.micro"
  description = "The size of the server"
}

Locals
#

Internal, private variables used for cleanup or calculations. The user cannot override these.

# main.tf (locals block)
locals {
  # Logic to enforce standardized naming conventions
  project_prefix = "ecommerce-prod"
  server_name    = "${local.project_prefix}-webserver"
}

Data Sources
#

Queries existing infrastructure or dynamic information from the cloud provider (Read-Only).

# main.tf (data block)
data "aws_ami" "latest_ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical/Ubuntu

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
}

Resources
#

The most important part—this is what you are actually building.

# main.tf (resource block)
resource "aws_instance" "web" {
  # Referencing the DATA SOURCE result
  ami           = data.aws_ami.latest_ubuntu.id
  
  # Referencing the VARIABLE
  instance_type = var.instance_type

  # Referencing the LOCAL
  tags = {
    Name = local.server_name
  }
}

Outputs
#

Prints specific information to your terminal after an apply.

# outputs.tf
output "web_server_public_ip" {
  value       = aws_instance.web.public_ip
  description = "Connect to the server at this IP"
}

More about Terraform providers
#

In Terraform, a provider is a plugin that interacts with an external system’s API to manage resources.

It implements CRUD operations:

  • Create
  • Read
  • Update
  • Delete

Types of Terraform Providers
#

Terraform providers are not officially classified this way, but in practice they fall into four functional categories:


1. Infrastructure Providers
#

Definition
#

Providers that manage core infrastructure resources such as compute, networking, and storage.

Examples
#

  • Amazon Web Services via AWS provider
  • Microsoft Azure
  • Google Cloud Platform
  • Docker

Example
#

resource "aws_instance" "web" {
  ami           = "ami-123"
  instance_type = "t2.micro"
}

Characteristics
#

  • Directly create infrastructure
  • Strong state mapping
  • High reliability
  • Widely used

Use cases
#

  • VMs, VPCs, load balancers
  • Storage systems
  • Base infrastructure setup

2 Platform Providers
#

Definition
#

Providers that manage platforms which themselves orchestrate infrastructure or workloads.

Examples
#

  • Kubernetes
  • OpenShift

Example
#

resource "kubernetes_deployment" "app" {
  metadata {
    name = "nginx"
  }
}

Characteristics
#

  • Operate on top of infrastructure
  • Interact with platform APIs
  • Manage workloads, not raw infra

Use cases
#

  • Deploying applications
  • Managing cluster resources
  • Service definitions

3 Orchestration / Packaging Providers
#

Definition
#

Providers that manage deployment tools or packaging systems, not raw infrastructure.

Examples
#

  • Helm
  • (conceptually similar tools: ArgoCD, though not always used via Terraform)

Example
#

resource "helm_release" "nginx" {
  name  = "nginx"
  chart = "nginx"
}

Characteristics
#

  • Wrap another system
  • Often depend on another provider (e.g., Kubernetes)
  • Manage packaged applications

Use cases
#

  • Installing applications via charts
  • Managing versions of deployed apps

4 Application / Service Providers
#

Definition
#

Providers that manage configuration inside SaaS tools or applications.

Examples
#

  • Grafana
  • Datadog
  • GitHub

Example
#

resource "grafana_dashboard" "example" {
  config_json = file("dashboard.json")
}

Characteristics
#

  • Manage logical configuration, not infrastructure
  • API-driven
  • Often sensitive to drift (manual UI changes)

Use cases
#

  • Dashboards, alerts
  • Repositories, permissions
  • Monitoring configuration

5 Utility / Bridge Providers
#

Definition
#

Providers that bridge gaps or provide utility functionality, often mimicking CLI behavior.

Examples
#

  • Community kubectl provider (wraps kubectl behavior)
  • Random provider (generates random values)
  • Null provider (executes scripts)

Example
#

resource "kubectl_manifest" "example" {
  yaml_body = file("manifest.yaml")
}

Characteristics
#

  • Often community-built
  • May be imperative in nature
  • Weaker state guarantees

Use cases
#

  • Applying raw YAML
  • Running scripts
  • Handling unsupported resources

Provider Ownership Types
#

Another important classification is who maintains the provider:

Official Providers
#

Maintained by HashiCorp

Examples:

  • hashicorp/aws
  • hashicorp/kubernetes
  • hashicorp/helm

Vendor Providers
#

Maintained by the platform company

Examples:

  • grafana/grafana
  • datadog/datadog

Community Providers
#

Maintained by individuals or small groups

Examples:

  • kreuzwerker/docker
  • gavinbunney/kubectl

Key Differences Across Types
#

TypeManagesState ComplexityExample
InfrastructurePhysical/cloud resourcesLowAWS
PlatformWorkloads/platform objectsMediumKubernetes
OrchestrationPackaged deploymentsMedium–HighHelm
ApplicationApp-level configMediumGrafana
UtilityHelpers/bridgesHighkubectl

By mastering these fundamental building blocks, you have the key to defining and managing entire data centers in simple, version-controlled text files. Happy provisioning!

Author
Suriya Shanmugam