Kahibaro
Discord Login Register

Terraform fundamentals

What Terraform Is and When to Use It

Terraform is a declarative Infrastructure as Code (IaC) tool. You describe what infrastructure you want (servers, networks, databases, etc.) in configuration files, and Terraform figures out how to create, change, or destroy it.

Key characteristics:

Typical use cases:

Core Concepts

Configuration Files

Terraform configurations are plain text files (usually with .tf extension) written in HashiCorp Configuration Language (HCL).

A minimal layout:

Terraform reads all .tf files in a directory as a single configuration.

Providers

A provider is a plugin that knows how to talk to an API (e.g. AWS, Azure, GCP).

Basic provider block:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  required_version = ">= 1.5.0"
}
provider "aws" {
  region = "us-east-1"
}

Important points:

Resources

A resource is a real piece of infrastructure Terraform manages, like a VM, database, or bucket.

Structure:

resource "<PROVIDER>_<TYPE>" "<NAME>" {
  # arguments
}

Example:

resource "aws_instance" "web" {
  ami           = "ami-0123456789abcdef0"
  instance_type = "t3.micro"
}

Data Sources

A data source reads information from external systems without managing it.

Example:

data "aws_ami" "ubuntu" {
  most_recent = true
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
  owners = ["099720109477"] # Canonical
}
resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"
}

Data sources:

Inputs: Variables

Variables allow you to parameterize configurations.

Definition (usually in variables.tf):

variable "instance_type" {
  description = "EC2 instance type for web servers"
  type        = string
  default     = "t3.micro"
}

Usage:

resource "aws_instance" "web" {
  ami           = "ami-0123456789abcdef0"
  instance_type = var.instance_type
}

Ways to set variable values:

Outputs

Outputs expose values after apply finishes, useful for human consumption or for other tools.

Example:

output "web_public_ip" {
  description = "Public IP of the web instance"
  value       = aws_instance.web.public_ip
}

After terraform apply, Terraform prints the output values.

Outputs are also important when combining modules (passing information between them).

Expressions and References

Terraform uses expressions to wire resources together.

Common patterns:

Example:

resource "aws_security_group" "web_sg" {
  name = "web-sg"
}
resource "aws_instance" "web" {
  ami                    = "ami-0123456789abcdef0"
  instance_type          = "t3.micro"
  vpc_security_group_ids = [aws_security_group.web_sg.id]
}

The reference aws_security_group.web_sg.id creates a dependency: Terraform ensures the security group exists before creating the instance.

Terraform CLI Workflow

Initialization: `terraform init`

terraform init:

Run it whenever:

Example:

$ terraform init

Planning Changes: `terraform plan`

terraform plan shows what Terraform will do without making changes.

It:

Example:

$ terraform plan

Typical uses:

Applying Changes: `terraform apply`

terraform apply:

Example:

$ terraform apply

For automation (CI/CD):

$ terraform apply -auto-approve

Destroying Infrastructure: `terraform destroy`

terraform destroy removes all resources managed in the current state.

Example:

$ terraform destroy

You can selectively destroy resources with targeting (covered below), but be careful: deletions can be irreversible (data loss, downtime).

State: How Terraform Tracks Resources

Terraform uses a state file (default terraform.tfstate) to track which real resources correspond to which configuration blocks.

Key points:

Local vs Remote State

By default, state is stored locally:

Remote state stores the state in a shared backend (e.g. S3, GCS, Azure Blob, Terraform Cloud), often with locking.

Example S3 backend:

terraform {
  backend "s3" {
    bucket = "my-tf-state-bucket"
    key    = "envs/prod/terraform.tfstate"
    region = "us-east-1"
  }
}

For multi‑person or production usage:

State Locking and Concurrency

To avoid conflicts:

Team practice:

Basic Language Features

HCL Syntax

HCL basics:

Example:

resource "aws_instance" "web" {
  ami           = "ami-0123456789abcdef0"
  instance_type = var.instance_type
  tags = {
    Name = "web-${var.environment}"
  }
}

Basic Types

Terraform has simple types:

And complex types (briefly):

You usually start with simple types, then use complex types as configurations grow.

Built‑in Functions (Overview)

Terraform provides standard library functions, such as:

Example:

tags = {
  Name = upper("web-${var.environment}")
}

Resource Graph and Dependencies

Terraform builds a dependency graph between resources based on references.

Example:

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "web" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
}

Here, aws_subnet.web depends on aws_vpc.main because of vpc_id = aws_vpc.main.id.

You can also use explicit depends_on when references are not enough, but for fundamentals, implicit dependencies via references cover most cases.

Targeting and Lifecycle Basics

Resource Targeting

-target allows you to focus plan or apply on specific resources.

Example:

$ terraform apply -target=aws_instance.web

Usage:

Lifecycle Options (Overview)

The lifecycle block controls some aspects of how Terraform manages resources.

Example:

resource "aws_instance" "web" {
  ami           = "ami-0123456789abcdef0"
  instance_type = "t3.micro"
  lifecycle {
    prevent_destroy = true
  }
}

Common lifecycle attributes you will encounter:

A Minimal End‑to‑End Example

This example shows a simple flow using a single provider and one resource.

main.tf:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  required_version = ">= 1.5.0"
}
provider "aws" {
  region = "us-east-1"
}
resource "aws_instance" "web" {
  ami           = "ami-0123456789abcdef0"
  instance_type = "t3.micro"
}
output "web_instance_id" {
  value = aws_instance.web.id
}

Workflow:

  1. Initialize:
   $ terraform init
  1. Preview:
   $ terraform plan
  1. Apply:
   $ terraform apply
  1. Destroy when done:
   $ terraform destroy

This pipeline—init → plan → apply → (destroy)—is the foundation on which more advanced Terraform features (modules, workspaces, complex backends) are built and will be elaborated in subsequent chapters.

Views: 20

Comments

Please login to add a comment.

Don't have an account? Register now!