- Introduction to Cloud Computing
- Cloud Providers
- AWS Global Infrastructure
- Infrastructure as Code (IaC)
- What is Terraform and Why Terraform
- Terraform Installation
- AWS CLI Installation and Access Configuration
- Terraform Commands
- Terraform Keywords
- Data Types
- Functions
- Terraform Providers
Cloud computing is the delivery of computing services — servers, storage, databases, networking, software, analytics, and intelligence — over the internet ("the cloud") to offer faster innovation, flexible resources, and economies of scale.
Instead of owning and maintaining physical data centers and servers, you access technology services on an as-needed basis from a cloud provider.
In the traditional model, companies had to:
- Buy physical servers and hardware upfront (capital expense)
- Set up and maintain their own data centers
- Hire staff to manage hardware, cooling, power, and networking
- Over-provision capacity to handle peak loads (wasted resources)
- Wait weeks or months to provision new infrastructure
| Traditional (On-Premises) | Cloud Computing |
|---|---|
| Buy hardware upfront | Pay-as-you-go (OpEx) |
| Months to provision | Minutes to provision |
| Fixed, limited capacity | Scale up/down instantly |
| You manage everything | Provider manages hardware |
| Single physical location | Available globally |
| High upfront cost | Low starting cost |
| Idle resources waste money | Pay only for what you use |
| Model | Full Name | What You Manage | Examples |
|---|---|---|---|
| IaaS | Infrastructure as a Service | OS, runtime, apps, data | AWS EC2, Azure VMs, GCP Compute |
| PaaS | Platform as a Service | Apps and data only | AWS Elastic Beanstalk, Heroku |
| SaaS | Software as a Service | Nothing (just use it) | Gmail, Salesforce, Zoom |
- Public Cloud — Infrastructure owned by a provider (AWS, Azure, GCP), shared across customers
- Private Cloud — Infrastructure dedicated to one organization, on-premises or hosted
- Hybrid Cloud — Mix of public and private cloud, connected together
- Multi-Cloud — Using multiple public cloud providers simultaneously
- Elasticity — Scale resources up or down based on demand automatically
- Global reach — Deploy applications close to users anywhere in the world
- High availability — Built-in redundancy and fault tolerance
- Security — Enterprise-grade security managed by the provider
- Speed — Go from idea to running infrastructure in minutes
- Cost efficiency — No upfront hardware investment, pay only for usage
Several major companies offer cloud computing platforms. Each has strengths, global presence, and a broad catalog of services.
| Provider | Full Name | Market Share | Strengths |
|---|---|---|---|
| AWS | Amazon Web Services | ~32% | Largest service catalog, most mature, widest global reach |
| Azure | Microsoft Azure | ~23% | Best for enterprises using Microsoft products (Windows, Active Directory, Office 365) |
| GCP | Google Cloud Platform | ~12% | Best for data analytics, machine learning, and Kubernetes (Google invented it) |
| Provider | Strengths |
|---|---|
| IBM Cloud | Enterprise workloads, hybrid cloud, mainframe integration |
| Oracle Cloud | Oracle databases, enterprise applications |
| Alibaba Cloud | Dominant in China and Southeast Asia |
| DigitalOcean | Simple, developer-friendly, affordable for small projects |
| Linode (Akamai) | Affordable Linux-based cloud for developers |
| Category | AWS | Azure | GCP |
|---|---|---|---|
| Compute | EC2 | Virtual Machines | Compute Engine |
| Serverless | Lambda | Azure Functions | Cloud Functions |
| Containers | EKS, ECS | AKS | GKE |
| Object Storage | S3 | Blob Storage | Cloud Storage |
| Managed Database | RDS | Azure SQL | Cloud SQL |
| DNS | Route 53 | Azure DNS | Cloud DNS |
| CDN | CloudFront | Azure CDN | Cloud CDN |
| IAM | IAM | Azure AD | Cloud IAM |
- Launched in 2006 — over 15 years of maturity
- 200+ services covering virtually every use case
- 30+ geographic regions worldwide
- Largest ecosystem of partners, tools, and community resources
- Most job postings and certifications in the industry
- Used by Netflix, Airbnb, NASA, the CIA, and millions of businesses
AWS infrastructure is built around three core concepts: Regions, Availability Zones, and Edge Locations.
┌─────────────────────────────────────────────────────────────────────────┐
│ AWS GLOBAL INFRASTRUCTURE │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ REGION (e.g., us-east-1) │ │
│ │ A geographic area │ │
│ │ │ │
│ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │
│ │ │ AZ-1 │ │ AZ-2 │ │ AZ-3 │ │ │
│ │ │ us-east-1a │ │ us-east-1b │ │ us-east-1c │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ │
│ │ │ │Data Center│ │ │ │Data Center│ │ │ │Data Center│ │ │ │
│ │ │ └───────────┘ │ │ └───────────┘ │ │ └───────────┘ │ │ │
│ │ └───────────────┘ └───────────────┘ └───────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ Edge Locations (400+): CloudFront CDN endpoints close to end users │
└─────────────────────────────────────────────────────────────────────────┘
A Region is a physical geographic area that contains multiple, isolated data centers. AWS has 30+ regions worldwide and each region is completely independent from others.
How to choose a region:
- Compliance — Data residency laws (e.g., EU data must stay in EU under GDPR)
- Latency — Pick the region closest to your users
- Service availability — Not all services are available in every region
- Cost — Pricing varies by region (
us-east-1is typically the cheapest)
Common regions:
| Region Code | Location | Notes |
|---|---|---|
us-east-1 |
N. Virginia | Default, cheapest, most services available |
us-west-2 |
Oregon | West coast US |
eu-west-1 |
Ireland | Europe |
eu-central-1 |
Frankfurt | Europe, GDPR-friendly |
ap-southeast-1 |
Singapore | Asia Pacific |
ap-northeast-1 |
Tokyo | Japan |
sa-east-1 |
São Paulo | South America |
Each region contains 2–6 Availability Zones. An AZ is one or more discrete data centers with redundant power, networking, and connectivity.
- Physically separate from each other (different buildings, different power grids)
- Connected via low-latency private fiber links
- Isolated from failures in other AZs
- Deploying across multiple AZs gives you high availability
Example: If us-east-1a suffers a power outage, your application running in us-east-1b continues without interruption.
AWS has 400+ Edge Locations worldwide used by CloudFront (CDN) and Route 53 (DNS). They cache content close to end users to reduce latency — separate from Regions and AZs.
| Concept | Definition | Example |
|---|---|---|
| Region | Geographic area with multiple data centers | us-east-1 (N. Virginia) |
| Availability Zone | Isolated data center(s) within a region | us-east-1a, us-east-1b |
| Edge Location | CDN/DNS endpoint close to users | CloudFront PoPs worldwide |
| Local Zone | AWS infrastructure closer to large cities | Los Angeles, Chicago |
| Wavelength Zone | Ultra-low latency for 5G networks | Verizon, T-Mobile 5G zones |
| Service | Category | What It Does |
|---|---|---|
| EC2 | Compute | Virtual servers |
| VPC | Networking | Private network in the cloud |
| S3 | Storage | Object storage (files, backups, static sites) |
| RDS | Database | Managed relational databases |
| EKS | Containers | Managed Kubernetes |
| IAM | Security | Users, roles, and permissions |
| ELB | Networking | Load balancers |
| Route 53 | DNS | Domain name management |
| CloudFront | CDN | Content delivery network |
| Lambda | Serverless | Run code without managing servers |
Before IaC, infrastructure was managed manually:
- Engineers would click through web consoles to create servers
- Steps were documented in wikis or runbooks (often outdated)
- Environments were inconsistent — "works on staging, breaks in prod"
- No version history — impossible to know who changed what and when
- Disaster recovery was slow and error-prone
- Scaling required manual repetition of the same steps
Infrastructure as Code is the practice of managing and provisioning infrastructure through machine-readable configuration files rather than manual processes or interactive tools.
With IaC, your infrastructure is defined in code files that can be:
- Versioned in Git like application code
- Reviewed via pull requests before applying
- Tested in CI/CD pipelines
- Reused across environments (dev, staging, prod)
- Shared across teams
| Benefit | Description |
|---|---|
| Consistency | Same code = same infrastructure every time, no manual drift |
| Speed | Provision entire environments in minutes |
| Version control | Full history of every infrastructure change in Git |
| Collaboration | Teams review infra changes like code via pull requests |
| Disaster recovery | Rebuild entire infrastructure from code in minutes |
| Documentation | The code itself documents what infrastructure exists |
| Cost control | Easily destroy and recreate environments to save money |
| Auditability | Know exactly who changed what and when |
| Approach | Description | Tools |
|---|---|---|
| Declarative | You describe the desired end state; the tool figures out how to get there | Terraform, CloudFormation, Pulumi |
| Imperative | You write step-by-step instructions for how to build the infrastructure | Ansible, shell scripts, AWS CDK |
Declarative is generally preferred for infrastructure because it handles drift detection and idempotency automatically.
| Tool | Provider | Language | Approach |
|---|---|---|---|
| Terraform | HashiCorp | HCL | Declarative, multi-cloud |
| CloudFormation | AWS | JSON/YAML | Declarative, AWS only |
| Pulumi | Pulumi | Python/TypeScript/Go | Declarative, multi-cloud |
| Ansible | Red Hat | YAML | Imperative, multi-purpose |
| AWS CDK | AWS | TypeScript/Python | Imperative → CloudFormation |
| OpenTofu | Community | HCL | Declarative, Terraform fork |
Terraform is an open-source Infrastructure as Code tool created by HashiCorp in 2014. It lets you define cloud and on-premises infrastructure in human-readable configuration files using HCL (HashiCorp Configuration Language), then provision and manage that infrastructure through a consistent workflow.
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ WRITE │────────▶│ PLAN │────────▶│ APPLY │
│ │ │ │ │ │
│ Define .tf │ │ Preview │ │ Create/Update│
│ config files │ │ changes │ │ infrastructure│
└──────────────┘ └──────────────┘ └──────────────┘
Key characteristics:
- Declarative — describe the desired state; Terraform figures out how to reach it
- Cloud-agnostic — works with AWS, Azure, GCP, Kubernetes, and 3,000+ providers
- State-based — tracks what it created so it can update or destroy resources accurately
- Idempotent — running the same config multiple times always produces the same result
Terraform works with virtually every cloud and service through providers. You use the same workflow and language whether you're provisioning AWS, Azure, GCP, Kubernetes, GitHub, Datadog, or PagerDuty.
HCL is readable and concise. You describe what you want, not how to build it:
resource "aws_instance" "web" {
ami = "ami-09e6f87a47903347c"
instance_type = "t3.micro"
tags = {
Name = "web-server"
}
}Before making any changes, Terraform shows you exactly what it will create, modify, or destroy. No surprises.
Plan: 3 to add, 1 to change, 0 to destroy.
Terraform maintains a state file that maps your config to real infrastructure. This allows it to detect drift, calculate diffs, and make only the necessary changes.
Terraform modules let you package infrastructure into reusable components. Write once, use across dev, staging, and prod environments.
- 3,000+ providers on the Terraform Registry
- Huge community with thousands of open-source modules
- Most widely adopted IaC tool in the industry
- Most in-demand IaC skill in DevOps job postings
| Tool | Type | Comparison |
|---|---|---|
| AWS CloudFormation | IaC (AWS only) | AWS-native, no state file, verbose JSON/YAML, slower |
| Pulumi | IaC (multi-cloud) | Uses real programming languages (Python, Go, TypeScript) |
| OpenTofu | IaC (multi-cloud) | Open-source Terraform fork, identical syntax |
| Ansible | Config Management | Procedural, better for OS config, not ideal for cloud infra |
| AWS CDK | IaC (AWS only) | Write infra in TypeScript/Python, compiles to CloudFormation |
| Year | Event |
|---|---|
| 2014 | HashiCorp releases Terraform 0.1 |
| 2019 | Terraform 0.12 — major HCL2 syntax upgrade |
| 2021 | Terraform 1.0 — stability guarantee, production-ready |
| 2023 | HashiCorp changes license to BSL (Business Source License) |
| 2023 | OpenTofu forked as open-source alternative under Linux Foundation |
| 2024 | Terraform 1.7+ — testing framework improvements |
Option 1: Chocolatey (recommended)
choco install terraformOption 2: Manual
- Download the zip from https://developer.hashicorp.com/terraform/install
- Extract the zip — you get a single
terraform.exefile - Move it to
C:\terraform\ - Add
C:\terraformto your System PATH:- Search "Environment Variables" in Start
- System Properties → Environment Variables
- Under System variables, select
Path→ Edit → New →C:\terraform
- Open a new terminal and verify:
terraform -version# Homebrew (recommended)
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Verify
terraform -versionwget -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 -y
terraform -versionsudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
sudo yum install terraform -y
terraform -versionTerraform uses the AWS CLI credentials to authenticate with AWS. You need to install the AWS CLI and configure your access keys.
Windows
# Download and run the MSI installer
msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi
# Verify
aws --versionmacOS
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
aws --versionLinux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws --versionBefore configuring the CLI, you need AWS credentials. Here is how to get them:
- Log in to the AWS Console at https://console.aws.amazon.com
- Go to IAM → Users → Create user
- Give the user a name (e.g.,
terraform-user) - Attach the policy AdministratorAccess (or a least-privilege policy for production)
- Go to the user → Security credentials tab → Create access key
- Choose CLI as the use case
- Download or copy the Access Key ID and Secret Access Key — you only see the secret once
Run the configure command and enter your credentials:
aws configureYou will be prompted for:
AWS Access Key ID [None]: AKIAXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Default region name [None]: us-east-1
Default output format [None]: json
This creates two files:
~/.aws/credentials— stores your access key and secret key~/.aws/config— stores your default region and output format
# Check your identity
aws sts get-caller-identity
# List S3 buckets (simple connectivity test)
aws s3 lsExpected output from get-caller-identity:
{
"UserId": "AIDAXXXXXXXXXXXXXXXX",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/terraform-user"
}Create a provider.tf file in your Terraform project:
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}Terraform automatically picks up credentials from ~/.aws/credentials. No need to hardcode them.
If you work with multiple AWS accounts, use named profiles:
# Configure a named profile
aws configure --profile dev
aws configure --profile prodReference a profile in Terraform:
provider "aws" {
region = "us-east-1"
profile = "dev"
}Or set it via environment variable:
export AWS_PROFILE=devYou can also authenticate Terraform using environment variables (useful in CI/CD):
export AWS_ACCESS_KEY_ID="AKIAXXXXXXXXXXXXXXXX"
export AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export AWS_DEFAULT_REGION="us-east-1"Terraform checks for AWS credentials in this order:
- Static credentials in the provider block (not recommended)
- Environment variables (
AWS_ACCESS_KEY_ID, etc.) - AWS CLI credentials file (
~/.aws/credentials) - IAM Instance Profile (when running on EC2)
- IAM Role for ECS tasks or Lambda functions
Never hardcode credentials in
.tffiles or commit them to Git. Useaws configure, environment variables, or IAM roles.
| Command | Purpose |
|---|---|
terraform init |
Initialize working directory, download providers |
terraform plan |
Preview what will be created/changed/destroyed |
terraform apply |
Apply changes to create/update infrastructure |
terraform destroy |
Destroy all managed infrastructure |
terraform validate |
Check syntax and configuration for errors |
terraform fmt |
Format .tf files to canonical style |
terraform show |
Show current state or a saved plan |
terraform state list |
List all resources tracked in state |
terraform state show <resource> |
Show details of a specific resource |
terraform output |
Show output values |
terraform import <resource> <id> |
Import existing infrastructure into state |
terraform refresh |
Update state to match real infrastructure |
terraform workspace list |
List workspaces |
terraform workspace new <name> |
Create a new workspace |
terraform init # First time, or when providers change
terraform fmt # Format code
terraform validate # Check for errors
terraform plan # Review changes
terraform apply # Deploy (type 'yes' to confirm)
terraform destroy # Tear down (type 'yes' to confirm)terraform apply -auto-approve
terraform destroy -auto-approve| Keyword | Purpose | Example |
|---|---|---|
resource |
Define infrastructure to create | resource "aws_instance" "web" {} |
provider |
Configure cloud provider | provider "aws" { region = "us-east-1" } |
variable |
Declare input parameters | variable "region" { default = "us-east-1" } |
output |
Expose values after apply | output "ip" { value = aws_instance.web.public_ip } |
data |
Query existing resources | data "aws_ami" "latest" {} |
module |
Reuse grouped resources | module "vpc" { source = "./modules/vpc" } |
locals |
Define local computed values | locals { name = "${var.env}-app" } |
terraform |
Configure Terraform settings | terraform { required_version = ">= 1.0" } |
backend |
Configure remote state storage | backend "s3" { bucket = "my-state" } |
dynamic |
Generate repeated nested blocks | dynamic "ingress" { ... } |
for_each |
Create multiple resources from a map/set | for_each = var.instances |
count |
Create multiple resources by number | count = 3 |
depends_on |
Explicit dependency declaration | depends_on = [aws_vpc.main] |
lifecycle |
Control resource behavior | lifecycle { prevent_destroy = true } |
| Type | Description | Example |
|---|---|---|
string |
Text | "us-east-1" |
number |
Integer or float | 8080 |
bool |
True or false | true |
list |
Ordered collection | ["us-east-1a", "us-east-1b"] |
map |
Key-value pairs | { name = "web", env = "prod" } |
set |
Unordered unique values | toset(["a", "b", "c"]) |
object |
Structured type with named attributes | { name = string, port = number } |
tuple |
Fixed-length typed list | [string, number, bool] |
| Function | Purpose | Example |
|---|---|---|
format |
Format a string | format("Hello %s", var.name) |
join |
Join list into string | join(",", var.list) |
split |
Split string into list | split(",", "a,b,c") |
length |
Length of list/map/string | length(var.subnets) |
lookup |
Get value from map | lookup(var.amis, "us-east-1") |
element |
Get item by index | element(var.azs, 0) |
file |
Read file contents | file("scripts/init.sh") |
templatefile |
Render template with variables | templatefile("user_data.tpl", { port = 8080 }) |
cidrsubnet |
Calculate subnet CIDR | cidrsubnet("10.0.0.0/16", 8, 1) |
merge |
Merge two maps | merge(var.defaults, var.overrides) |
flatten |
Flatten nested lists | flatten([["a"], ["b", "c"]]) |
tolist / toset / tomap |
Type conversion | tolist(var.items) |
try |
Return first non-error value | try(var.optional, "default") |
keys / values |
Get map keys or values | keys(var.tags) |
Providers are plugins that allow Terraform to interact with cloud APIs and services. There are 3,000+ providers on the Terraform Registry.
| Provider | Purpose |
|---|---|
hashicorp/aws |
Amazon Web Services |
hashicorp/azurerm |
Microsoft Azure |
hashicorp/google |
Google Cloud Platform |
hashicorp/kubernetes |
Kubernetes resources |
hashicorp/helm |
Helm chart deployments |
integrations/github |
GitHub repos and teams |
hashicorp/random |
Generate random values |
hashicorp/null |
Null resources for triggers |
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
}