Cloud Computing Tutorial: Learn Cloud from Scratch (2026)
Cloud computing delivers on-demand computing resources over the internet, shifting infrastructure from capital expenditure to operational expenditure. Having migrated multiple production systems to the cloud and optimized their cost and performance, I have firsthand experience with the trade-offs between IaaS, PaaS, and FaaS, and the operational discipline required to run workloads reliably at scale. This tutorial covers cloud service models, deployment patterns, virtualization, containerization, and the major cloud providers' offerings.
We will explore practical scenarios: designing a multi-region architecture for high availability, setting up auto-scaling groups to handle traffic spikes, implementing infrastructure as code with Terraform, and building a CI/CD pipeline that deploys to Kubernetes. Each section balances conceptual depth with actionable guidance.
Cloud Service Models: IaaS, PaaS, SaaS, FaaS
Infrastructure as a Service (IaaS) provides virtualized compute, storage, and networking — you manage the OS, middleware, and applications. Platform as a Service (PaaS) manages the runtime environment; you deploy code only. Software as a Service (SaaS) delivers fully managed applications to end users. Function as a Service (FaaS) — serverless computing — runs stateless functions triggered by events, scaling to zero when idle. The shared responsibility model defines security boundaries: the provider secures the cloud, you secure what is in the cloud.
# AWS CDK: Defining an IaaS stack
from aws_cdk import Stack
from aws_cdk.aws_ec2 import Instance, InstanceType, MachineImage, Vpc
from constructs import Construct
class WebServerStack(Stack):
def __init__(self, scope: Construct, id: str):
super().__init__(scope, id)
vpc = Vpc(self, "VPC", max_azs=2)
Instance(self, "WebServer",
vpc=vpc,
instance_type=InstanceType("t3.micro"),
machine_image=MachineImage.latest_amazon_linux2()
)
Virtualization and Hypervisors
Virtualization abstracts physical hardware so multiple virtual machines (VMs) can share the same host. Type 1 hypervisors (VMware ESXi, KVM, Hyper-V) run directly on hardware, providing better performance and isolation. Type 2 hypervisors (VirtualBox, VMware Workstation) run on top of a host OS. Each VM includes a full guest OS, consuming gigabytes of disk and seconds to boot. Paravirtualization modifies the guest OS to issue hypercalls directly, reducing virtualization overhead for I/O operations.
# Virtualization management conceptual
def create_vm(hypervisor, name, cpu_cores, ram_mb, disk_gb):
vm = {
"name": name,
"vcpus": cpu_cores,
"memory": ram_mb,
"disk": disk_gb,
"state": "stopped",
"hypervisor": hypervisor
}
hypervisor.vms.append(vm)
return vm
def migrate_vm(vm, target_host):
print(f"Migrating {vm['name']} to {target_host}")
vm['hypervisor'] = target_host
print("Migration complete, < 50ms downtime")
Containerization and Docker
Containers provide OS-level virtualization — they share the host kernel but isolate processes, filesystem, and networking. Docker packages an application with its dependencies into a lightweight, portable image. Images are built from Dockerfiles using layers, each instruction adding a read-only layer. Containers start in milliseconds and use far less memory than VMs. Kubernetes (K8s) orchestrates containers across a cluster, handling scaling, service discovery, rolling updates, and self-healing.
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /usr/local /usr/local
COPY app.py .
EXPOSE 8080
CMD ["python", "app.py"]
# docker build -t myapp .
# docker run -p 8080:8080 myapp
Auto Scaling and Load Balancing
Auto Scaling adjusts compute capacity based on demand, adding instances during traffic spikes and removing them during lulls. Launch templates specify the AMI, instance type, security groups, and user data script. Scaling policies can be target tracking (e.g., maintain CPU at 50%), step scaling, or scheduled scaling. A load balancer (ALB for HTTP, NLB for TCP) distributes traffic across healthy instances, performing health checks and routing around failures. The combination ensures applications remain responsive under varying load.
# Auto Scaling configuration (AWS CLI conceptual)
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name web-asg \
--launch-template LaunchTemplateName=web-template \
--min-size 2 --max-size 10 --desired-capacity 2 \
--vpc-zone-identifier subnet-abc,subnet-def \
--target-group-arns arn:aws:elasticloadbalancing:...
# Scale-out policy: add 2 instances when CPU > 70% for 5 min
aws autoscaling put-scaling-policy \
--policy-name cpu-scale-out \
--auto-scaling-group-name web-asg \
--scaling-adjustment 2 \
--cooldown 300
Infrastructure as Code with Terraform
Infrastructure as Code (IaC) manages cloud resources through declarative configuration files, enabling version control, code review, and automated provisioning. Terraform defines resources in HCL (HashiCorp Configuration Language) and maintains state — a JSON file mapping configuration to real-world resources. The plan/apply workflow shows changes before applying. Modules encapsulate reusable infrastructure patterns (e.g., a VPC module with public/private subnets, NAT gateways, and route tables).
provider "aws" {
region = "us-west-2"
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = { Name = "main-vpc" }
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
}
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
subnet_id = aws_subnet.public.id
user_data = <<-EOF
#!/bin/bash
yum install -y httpd
systemctl start httpd
EOF
}
Serverless Computing and Event-Driven Architecture
Serverless computing (AWS Lambda, Azure Functions, Cloud Functions) lets you run code without provisioning or managing servers. Functions are stateless, event-driven, and scale automatically. Each invocation runs in a sandboxed container with a configurable memory (128 MB to 10 GB) and timeout (up to 15 minutes for Lambda). Cold starts introduce latency when a new sandbox is created; provisioned concurrency keeps instances warm. Common patterns include processing S3 uploads, handling API Gateway requests, and transforming data in streaming pipelines.
import json
import boto3
def lambda_handler(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
print(f"Processing s3://{bucket}/{key}")
s3 = boto3.client('s3')
response = s3.get_object(Bucket=bucket, Key=key)
image_data = response['Body'].read()
return {"statusCode": 200, "body": json.dumps(f"Processed {key}")}
Frequently Asked Questions
What is the difference between vertical and horizontal scaling?
Vertical scaling adds more resources (CPU, RAM) to a single instance. It has limits and creates a single point of failure. Horizontal scaling adds more instances behind a load balancer, providing better fault tolerance and near-infinite scalability.
How do you estimate cloud costs?
Use provider cost calculators. Major cost drivers: compute (instance hours), storage (GB/month + I/O operations), data transfer (egress is expensive), and managed services. Reserved instances and spot instances reduce costs by 40-90% compared to on-demand.
What is vendor lock-in and how do you avoid it?
Vendor lock-in occurs when migrating away from a provider is prohibitively expensive due to proprietary services. Mitigate by using open-source technologies (Kubernetes, Terraform), abstracting cloud-specific APIs behind interfaces, and designing for multi-cloud portability.
How does cloud security differ from on-premises security?
The shared responsibility model applies: the cloud provider secures the physical infrastructure, hypervisor, and network. You secure data, access management (IAM), encryption keys, OS patches, and application code. Identity and access management becomes the primary security perimeter.
Originally published on Ayodhyyya. Last updated June 1, 2026.