Terraform Deep Dive
Day 22: Terraform - Resources, Variables, State & Modules
Real Azure/AWS resources, variable types, outputs, locals, and remote state
โฑ 60 min
๐ Theory (35 min)
๐ง Lab (20 min)
โ Quiz (5 min)
Resources
Understand create/update/destroy/no-op behavior and lifecycle planning.
Inputs/Outputs
Use variables, locals, outputs, and data sources correctly.
State
Move from local state to remote state with locking for team safety.
Session Plan
Theory, Lab, and Quiz Breakdown
๐ Theory
Terraform Resource Lifecycle (create/update/destroy/no-op)
Variables, Locals, Outputs, and Data Sources
State Fundamentals and Remote State Backends
๐ง Lab
Provision Azure + GitHub resources and build a reusable module, then review `plan` vs `apply` behavior.
โ Quiz
5-minute knowledge check on lifecycle, locals, outputs, and remote state.
Core Concept
Terraform Resource Lifecycle
Terraform compares desired state (`.tf`) with current state (`.tfstate`).
create
Resource exists in config but not in state.
update
Resource exists in both, but configuration changed.
destroy
Resource exists in state but was removed from config.
no-op
Resource exists in both and is unchanged, so nothing happens.
Workflow
How Terraform Decides Actions
1) Read Config
Parse `.tf` files as desired state.
2) Read State
Load current state from backend.
3) Diff
Compute action graph for each resource.
4) Execute
`plan` previews, `apply` performs changes.
terraform init
terraform plan
terraform apply
Inputs and Outputs
Variables, Locals, Outputs, Data Sources
variable
Input values set via CLI, env vars, or `.tfvars`.
locals
Computed values inside the module (not external inputs).
output
Expose values to users or other modules.
data source
Read existing infrastructure not managed by this Terraform config.
Best Practice
Use Locals to Avoid Repetition
If an expression appears 3+ times, move it to `locals`.
variable "env" { type = string }
variable "project" { type = string }
locals {
common_tags = {
env = var.env
project = var.project
}
}
resource "azurerm_resource_group" "main" {
name = "${var.project}-${var.env}-rg"
location = "Central India"
tags = local.common_tags
}
State
State File Essentials
What state does
Maps configured resources to real infrastructure IDs and attributes.
Risk
State can include sensitive values. Never commit local state to Git.
Single source of truth
Terraform plans and applies depend on accurate, consistent state.
Team impact
Local state breaks collaboration and causes drift/conflicts.
Team Workflows
Remote State Backends + Locking
Azure
`azurerm` backend using Blob Storage.
AWS
`s3` backend (with locking setup for team safety).
Terraform Cloud
Managed state + locking, free tier available.
State Locking (Critical)
Prevents concurrent `terraform apply` from multiple users and avoids state corruption.
Hands-on Labs
Hands-on Labs: Azure + GitHub + Modules
Lab A - Provision Azure Resources
Step 1: Configure Azure provider and backend (if remote state is enabled).
Step 2: Create resource group + storage account using variables.
Step 3: Run `terraform init`, `terraform plan`, `terraform apply`.
resource "azurerm_resource_group" "rg" {
name = "${var.project}-${var.env}-rg"
location = var.location
tags = local.common_tags
}
resource "azurerm_storage_account" "st" {
name = "${var.project}${var.env}st01"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = "Standard"
account_replication_type = "LRS"
}
Lab B - Provision GitHub Repository
Step 1: Configure GitHub provider (`integrations/github`).
Step 2: Set `TF_VAR_github_token` securely in your shell.
Step 3: Run `terraform init`, `terraform plan`, `terraform apply`.
terraform {
required_providers {
github = {
source = "integrations/github"
version = "~> 6.0"
}
}
}
provider "github" {
token = var.github_token
}
resource "github_repository" "labs_repo" {
name = "terraform-day22-labs"
visibility = "private"
auto_init = true
}
Lab C - Build and Use a Module
Step 1: Create child module: `modules/resource_group`.
Step 2: Add `main.tf`, `variables.tf`, `outputs.tf` in that module.
Step 3: Call the module from root and pass inputs.
module "rg" {
source = "./modules/resource_group"
name = "${var.project}-${var.env}-rg"
location = var.location
tags = local.common_tags
}
output "resource_group_name" {
value = module.rg.name
}
Quiz
5-Minute Knowledge Check
1) What triggers `create` vs `update` in Terraform?
2) When should you use `locals` instead of `variables`?
3) What is the purpose of an `output` block?
4) Why is remote state locking important for teams?
5) What is the difference between a `resource` and a `data` source?
Recap
Day 22 Summary
Terraform lifecycle: create, update, destroy, no-op.
Variables are inputs, locals are computed values, outputs expose values.
Data sources read existing infrastructure without managing it.
Remote state + locking is mandatory for safe team workflows.
Next Practice
Extend the lab with a reusable module and compare plans across dev/staging workspaces.
Additional Session
Terraform Modules
Reusable modules, module registry, workspaces, and Terragrunt intro
โฑ 60 min
๐ Theory
๐ง Lab: Build and Use a Terraform Module
โ Quiz: 5 min
๐ Theory Topics
What is a Terraform Module? (root module vs child module)
Module structure + module registry usage
Workspaces, environment strategy, and Terragrunt intro
Modules Basics
What is a Terraform Module?
Module Definition
A module is a reusable package of Terraform resources. Every Terraform configuration is a module.
Root Module
The directory where you run Terraform commands (`init`, `plan`, `apply`).
Child Module
Invoked from root using a `module` block and input variables.
Module Sources
Public registry (`registry.terraform.io`) or private/internal module repos/registries.
Practical Advice
Do not build everything from scratch. Start with official battle-tested modules such as Azure AKS, AWS VPC, or GCP GKE.
Module Design
Recommended Module Structure
modules/network/
main.tf # resource definitions
variables.tf # input variable declarations
outputs.tf # output value declarations
README.md # usage docs and examples
main.tf
Contains the resources and data sources used by the module.
variables.tf
Declares typed inputs with defaults/validation where needed.
outputs.tf
Exposes IDs/attributes for root or downstream modules.
README.md
Document usage, examples, inputs, outputs, and constraints.
Automation Tip
Use `terraform-docs` to auto-generate README input/output documentation from your module code.
Environments
Workspaces and Terragrunt Intro
terraform workspace new staging
terraform workspace select production
Workspaces
Allow multiple environments with same config; each workspace has its own state file.
Large Team Strategy
Separate directories per environment is usually clearer and preferred for large teams.
Terragrunt Intro
Wrapper tool for DRY config, environment orchestration, and reusable module wiring.
When to Use
Useful when managing many stacks/accounts/regions with repeated backend/provider config.
Modules Lab + Quiz
Build and Use a Terraform Module
๐ง Lab Flow
Create a child module (`modules/resource_group`).
Define `variables.tf`, `main.tf`, `outputs.tf`.
Call module from root and pass env/project/location variables.
Run `terraform init`, `terraform plan`, `terraform apply`.
โ 5-Min Quiz Prompts
1) Root module vs child module difference?
2) Why split module files into main/variables/outputs?
3) Why can workspace strategy be risky for very large teams?
4) When should you adopt Terragrunt?