Chapter 1: Introduction to Infrastructure as Code & Terraform#
π― Learning Objectives#
- Understand what Infrastructure as Code (IaC) is and why it matters
- Compare Terraform with other IaC tools (CloudFormation, Pulumi, Ansible)
- Learn Terraform’s architecture and how it works
- Install Terraform and set up AWS credentials
- Write your first Terraform configuration
- Understand HCL vs JSON configuration formats
1.1 What is Infrastructure as Code?#
Infrastructure as Code (IaC) is the practice of managing and provisioning infrastructure (servers, networks, databases, etc.) through machine-readable definition files, rather than manual processes or interactive configuration tools.
The Problem IaC Solves#
Before IaC, infrastructure was managed manually:
- Clicking through AWS Console to create resources
- SSH’ing into servers to install software
- Documenting setup steps in wikis (that quickly go out of date)
- Snowflake servers β each server is unique and irreproducible
Benefits of IaC#
| Benefit | Description |
|---|---|
| Reproducibility | Spin up identical environments every time |
| Version Control | Infrastructure changes are tracked in Git |
| Review & Collaboration | Pull requests for infra changes (code review) |
| Consistency | No snowflake servers β every environment is identical |
| Speed | Provision infrastructure in minutes, not days |
| Self-Documenting | The code IS the documentation |
| Disaster Recovery | Rebuild entire infrastructure from scratch quickly |
IaC Approaches#
| Approach | Description | Examples |
|---|---|---|
| Declarative (Functional) | Define the desired state, tool figures out how to reach it | Terraform, CloudFormation, Pulumi |
| Imperative (Procedural) | Define the steps to reach the desired state | Ansible, Chef, Puppet |
Terraform is declarative β you describe what you want, and Terraform figures out how to make it happen.
1.2 Terraform vs Other Tools#
| Feature | Terraform | AWS CloudFormation | Pulumi | Ansible |
|---|---|---|---|---|
| Cloud | Multi-cloud | AWS-only | Multi-cloud | Multi-cloud |
| Language | HCL (HashiCorp Config Language) | JSON/YAML | General-purpose (TS, Python, Go) | YAML |
| State Management | Built-in state tracking | Stack-based | State managed | Stateless (push/pull) |
| Execution Model | Declarative | Declarative | Declarative | Imperative |
| Maturity | Mature (10+ years) | Mature | Growing | Mature |
| Community Providers | 2000+ | AWS-only | Growing | Extensive |
| Learning Curve | Moderate | Moderate (JSON/YAML) | Steeper (needs programming) | Gentle |
Why Terraform for AWS?#
- Multi-cloud flexibility β Even if you’re AWS-only now, skills transfer to GCP/Azure
- HCL β Designed specifically for infrastructure, human-readable
- Rich ecosystem β 2000+ providers, huge community, modules, registry
- Plan/Apply workflow β See changes before applying them
- State management β Tracks what’s deployed vs what’s defined
- Battle-tested β Used by Netflix, Uber, Slack, Coinbase, and thousands of enterprises
1.3 Terraform Architecture#
βββββββββββββββββββββββββββββββββββββββ
β Terraform Core β
β (HashiCorp, written in Go) β
β β
β βββββββββββββ βββββββββββββββββ β
β β Parser β β Dependency β β
β β (HCL) β β Graph Builder β β
β βββββββ¬ββββββ βββββββββ¬ββββββββ β
β β β β
β βββββββΌβββββββββββββββββββΌββββββββ β
β β Terraform State β β
β β (terraform.tfstate) β β
β ββββββββββββββββββββββββββββββββββββ β
β β β
ββββββββββββββββββββββΌββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ
β β β
βββββββΌβββββββ βββββββββΌββββββββ βββββββββΌββββββββ
β AWS Provider β β GCP Provider β β Azure Providerβ
β (aws) β β (google) β β (azurerm) β
ββββββββ¬ββββββββ βββββββββ¬ββββββββ βββββββββ¬ββββββββ
β β β
ββββββββΌβββββββ βββββββββΌββββββββ βββββββββΌββββββββ
β AWS API β β GCP API β β Azure API β
βββββββββββββββ βββββββββββββββββ βββββββββββββββββKey Components#
| Component | Role |
|---|---|
| Terraform Core | Parses HCL, builds dependency graph, manages state |
| Providers | Plugins that understand API interactions with specific platforms (AWS, GCP, etc.) |
| State | Mapping between your config and actual deployed resources |
| Configuration | Your .tf files defining the desired infrastructure |
1.4 Terraform Workflow#
The Terraform workflow consists of three core commands executed in sequence:
Write Config β terraform init β terraform plan β terraform apply β terraform destroyBasic Workflow#
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Terraform Workflow β
β β
β 1. INIT Install providers and modules β
β βββ $ terraform init β
β β
β 2. PLAN Preview what will be created/changed/destroyed β
β βββ $ terraform plan β
β β
β 3. APPLY Execute the changes (create/update/delete) β
β βββ $ terraform apply β
β β
β 4. DESTROY Tear down all managed resources β
β βββ $ terraform destroy β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββThe Plan/Apply Loop (Exam Critical)#
This is the most important concept for the exam:
- Write your configuration in
.tffiles - Run
terraform initβ Initialize the working directory (download providers) - Run
terraform planβ Creates an execution plan (does NOT apply it) - Review the plan β See what resources will be added/changed/destroyed
- Run
terraform applyβ Apply the changes (Terraform asks for confirmation by default)
The plan shows:
+Resources to be created-Resources to be destroyed~Resources to be modified in-place+/-Resources to be replaced (destroyed and recreated)
1.5 Installing Terraform#
Option 1: Package Manager (Recommended)#
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Linux (Ubuntu/Debian)
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
# Linux (Amazon Linux / RHEL / CentOS)
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
sudo yum -y install terraform
# Windows (Chocolatey)
choco install terraformOption 2: Manual Install#
# Download the binary for your OS
wget https://releases.hashicorp.com/terraform/1.9.0/terraform_1.9.0_linux_amd64.zip
# Unzip
unzip terraform_1.9.0_linux_amd64.zip
# Move to PATH
sudo mv terraform /usr/local/bin/
# Verify
terraform --versionInstall Terraform with tfenv (Version Management)#
# Install tfenv
git clone https://github.com/tfutils/tfenv.git ~/.tfenv
echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bashrc
# Install and use specific version
tfenv install 1.9.0
tfenv use 1.9.0
# Switch versions easily
tfenv listSetting Up AWS Credentials#
# Install AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# Configure credentials
aws configure
# AWS Access Key ID: [your access key]
# AWS Secret Access Key: [your secret key]
# Default region: us-east-1
# Default output format: json
# Verify
aws sts get-caller-identityBest Practice: Never hardcode AWS credentials in Terraform files! Use environment variables or AWS CLI profiles.
# Option A: Environment variables
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_DEFAULT_REGION="us-east-1"
# Option B: AWS profile
export AWS_PROFILE="my-dev-profile"1.6 Your First Terraform Configuration#
Let’s create a simple configuration that deploys an S3 bucket.
Step 1: Create the configuration file#
# main.tf
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-first-terraform-bucket-2024-unique-name"
tags = {
Name = "MyBucket"
Environment = "Learning"
}
}Step 2: Initialize#
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.40.0...
- Installed hashicorp/aws v5.40.0 (signed by HashiCorp)
Terraform has been successfully initialized!Step 3: Plan#
$ terraform plan
Terraform will perform the following actions:
# aws_s3_bucket.my_bucket will be created
+ resource "aws_s3_bucket" "my_bucket" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = "my-first-terraform-bucket-2024"
+ bucket_domain_name = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ region = (known after apply)
+ tags = {
+ "Environment" = "Learning"
+ "Name" = "MyBucket"
}
+ tags_all = {
+ "Environment" = "Learning"
+ "Name" = "MyBucket"
}
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.Step 4: Apply#
$ terraform apply
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_s3_bucket.my_bucket: Creating...
aws_s3_bucket.my_bucket: Creation complete after 2s [id=my-first-terraform-bucket-2024]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.Step 5: Verify in AWS Console#
Go to S3 in AWS Console β you’ll see your new bucket!
Step 6: Destroy#
$ terraform destroy
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_s3_bucket.my_bucket: Destroying... [id=my-first-terraform-bucket-2024]
aws_s3_bucket.my_bucket: Destruction complete after 1s
Destroy complete! Resources: 1 destroyed.1.7 HCL vs JSON Configuration#
Terraform supports two syntaxes:
HCL (HashiCorp Configuration Language) β Preferred .tf#
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "WebServer"
}
}JSON Syntax .tf.json β Machine-generated#
{
"resource": {
"aws_instance": {
"web": {
"ami": "ami-0c55b159cbfafe1f0",
"instance_type": "t2.micro",
"tags": {
"Name": "WebServer"
}
}
}
}
}Always use HCL (.tf) for human-written configurations. JSON is useful for:
- Machine-generated configurations
- Programmatic creation of Terraform configs
- Integration with other tools
1.8 Key Terraform Commands#
| Command | Purpose | When to Use |
|---|---|---|
terraform init |
Initialize working directory, download providers | First time, after adding new providers |
terraform plan |
Show execution plan without applying | Before any apply |
terraform apply |
Apply changes to reach desired state | To deploy/update infrastructure |
terraform destroy |
Destroy all managed resources | To tear down infrastructure |
terraform fmt |
Format code according to HCL standards | Before committing |
terraform validate |
Validate configuration syntax | During development |
terraform state list |
List resources in state | Troubleshooting |
terraform output |
Show output values | Getting generated values |
terraform show |
Show current state or plan | Inspection |
1.9 Understanding terraform init Deep Dive#
The init command is the first command to run after writing a new configuration. It:
- Creates the
.terraformdirectory (stores providers, modules) - Downloads provider plugins specified in
required_providers - Downloads modules referenced in the configuration
- Initializes the backend (local or remote state storage)
- Creates/updates
.terraform.lock.hclβ provider version lock file
# Basic init
terraform init
# Init with specific backend config
terraform init -backend-config="bucket=my-terraform-state"
# Upgrade providers and modules
terraform init -upgrade
# Re-initialize in a non-interactive way
terraform init -input=false
# Init only specific modules
terraform init -get=falseπ Exam Tips#
- Know the Terraform workflow: init β plan β apply (in that order)
- Understand
terraform initβ it downloads providers and modules, initializes backends - Understand
terraform planβ read-only operation, does NOT modify infrastructure - Know the difference between HCL (.tf) and JSON (.tf.json) syntaxes
- Remember
terraform fmtformats code,terraform validatechecks syntax - Be aware that
terraform destroyis the reverse ofterraform apply
β Chapter 1 Quiz#
-
What is the first command you should run after writing a Terraform configuration?
- a)
terraform apply - b)
terraform plan - c)
terraform init - d)
terraform validate
- a)
-
Which Terraform command creates an execution plan but does NOT apply changes?
- a)
terraform plan - b)
terraform apply - c)
terraform show - d)
terraform init
- a)
-
True or False: Terraform uses an imperative approach to infrastructure management.
-
Which file extension is used for HCL Terraform configurations?
- a)
.json - b)
.yaml - c)
.tf - d)
.hcl
- a)
-
What does
terraform destroydo?- a) Destroys the local state file
- b) Destroys all resources managed by the configuration
- c) Destroys the Terraform binary
- d) Only destroys resources marked for deletion
π Answers
- c β
terraform initmust be run first to initialize the backend and download providers - a β
terraform planshows what changes will be made without applying them - False β Terraform uses a declarative approach (you define the desired state)
- c β
.tffiles contain HCL syntax - b β
terraform destroydestroys all resources managed by the configuration
π Additional Resources#
- Terraform Installation Guide
- AWS CLI Installation Guide
- Terraform AWS Provider Docs
- HCL Specification
Example Projects to Explore#
Now that you understand the basics, explore these real-world examples:
- π₯οΈ Basic EC2 β Simple EC2 instance with variables and outputs
- ποΈ VPC Module β Reusable VPC with public/private subnets
- π¦ Multi-Tier App β VPC + ALB + ASG + RDS architecture
- β‘ Serverless API β Lambda + API Gateway + DynamoDB (serverless pattern)
- π³ ECS Fargate β Containerized app on ECS with auto-scaling
- βΈοΈ EKS Cluster β Managed Kubernetes cluster with node groups
- π S3 + CloudFront Website β Static site hosting with CDN and WAF
- π Production-Ready β Full production-grade infrastructure pattern
Continue to β Chapter 2: Terraform Core Concepts