"You've been asked to provision all infrastructure for your team's AKS platform. Resource groups, networking, clusters, monitoring, container registries... all of it. Let's learn Infrastructure as Code with Terraform."
The Manual Provisioning Problem
The Azure Portal Way
Click through dozens of screens
Remember every setting by heart
Hope your colleague clicks the same options
No audit trail of what changed
The Consequences
Configuration drift between environments
"Snowflake" servers nobody dares touch
Disaster recovery takes days
No code review for infrastructure
What is Infrastructure as Code?
Managing and provisioning infrastructure through machine-readable definition files rather than manual processes.
Key Principles
Declarative definitions
Version controlled
Idempotent operations
Self-documenting
Benefits
Repeatable deployments
Peer-reviewed changes
Automated provisioning
Consistent environments
What is Terraform?
Open-source IaC tool created by HashiCorp (2014)
Uses HCL (HashiCorp Configuration Language) - a declarative language
Works with providers - plugins for every major cloud and service
Manages the full lifecycle: create, update, destroy
Maintains a state file mapping config to real resources
Licensed under BSL 1.1 (since Aug 2023); OpenTofu is the open-source fork
Same language for Azure, Kubernetes, Helm, DNS, monitoring
Massive community - modules, examples, StackOverflow answers
Skills transfer to any cloud (AWS, GCP, etc.)
Azure-specific features: Blob backend for state, AD auth, managed identities
Knowledge Check 1
1. What language does Terraform use for configuration files?
2. What is the main problem with manual infrastructure provisioning?
3. Which of these tools is Azure-only?
The Core Terraform Workflow
1. Write
Define your infrastructure in .tf files
→
2. Init
Download providers & set up backend
→
3. Plan
Preview what will change
→
4. Apply
Create/update real resources
terraform init
Initializes the working directory. Downloads providers, sets up backend, installs modules.
$ terraform init
Initializing the backend...Initializing provider plugins...- Finding hashicorp/azurerm versions matching "~> 3.0"...- Installing hashicorp/azurerm v3.85.0...Terraform has been successfully initialized!
Run this once when starting, and again when providers or backend change.
terraform plan
Creates an execution plan showing what Terraform will do, without making any changes.
$ terraform plan
# azurerm_resource_group.main will be created
+ resource"azurerm_resource_group""main" {
+ name = "rg-aks-platform"
+ location = "uksouth"
}
Plan: 1 to add, 0 to change, 0 to destroy.
+ resource will be created
~ resource will be updated in-place
- resource will be destroyed
terraform apply
Executes the plan. Creates, updates, or destroys real infrastructure.
$ terraform apply
# Shows the plan, then prompts:
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yesazurerm_resource_group.main: Creating...azurerm_resource_group.main: Creation complete after 2sApply complete! Resources: 1 added, 0 changed, 0 destroyed.
terraform destroy
Removes all resources managed by the current configuration.
$ terraform destroy
# azurerm_resource_group.main will be destroyed
- resource"azurerm_resource_group""main" {
- name = "rg-aks-platform"
- location = "uksouth"
}
Plan: 0 to add, 0 to change, 1 to destroy.
Use with extreme caution in production. Always review the plan first.
HCL Basics: Resources
Resources are the most important element. They describe a single infrastructure object.
resource"azurerm_resource_group""main" {
name = "rg-${var.environment}"location = var.location
}
Set values via:
-var="env=dev"
terraform.tfvars file
TF_VAR_environment env var
HCL Basics: Outputs
Outputs expose values from your configuration - useful for passing data between modules or displaying results.
output"resource_group_id" {
description = "The ID of the resource group"value = azurerm_resource_group.main.id
}
output"resource_group_name" {
description = "The name of the resource group"value = azurerm_resource_group.main.name
}
For CI/CD, prefer environment variables (ARM_CLIENT_ID, etc.) over hardcoding credentials.
Terraform State
The state file (terraform.tfstate) is Terraform's record of what it manages.
What State Tracks
Resource IDs in Azure
Attribute values (names, IPs, etc.)
Dependencies between resources
Metadata for performance
Why It Matters
Maps config to real-world resources
Detects drift from desired state
Determines what to create/update/destroy
Must be shared in team environments
State File: Handle with Care
Critical Rules
1. Never commit terraform.tfstate to Git - it may contain secrets
2. Always use remote state for team projects (Azure Blob Storage)
3. Enable state locking to prevent concurrent modifications
4. Backup state before dangerous operations
# .gitignore
*.tfstate
*.tfstate.*
.terraform/
*.tfvars # may contain secrets