ในบทความนี้
In this post
- ☁️ What Is Cloud Computing?
- 🏢 The 3 Major Cloud Providers
- 🏗️ Well-Architected Framework
- 🌐 VPC & Networking — Your Network on the Cloud
- ⚡ High Availability — The System Cannot Go Down!
- 🚀 Serverless Architecture
- 💰 Cost Optimization — Cutting the Cloud Bill
- 🔒 Cloud Security — Protecting the System
- 📊 Cloud Architecture Patterns
- Summary
จากซีรีส์ที่ผ่านมา เราเรียน Docker, Kubernetes, IaC, GitOps — แต่ทั้งหมดรันอยู่บน infrastructure ไม่ว่าจะเป็นเครื่องตัวเอง, VPS หรือ Cloud
วันนี้มาเรียนรู้ Cloud Architecture — วิธีออกแบบระบบบน Cloud ให้ แข็งแกร่ง, scale ได้, ปลอดภัย และคุ้มค่า ☁️🐕
☁️ Cloud Computing คืออะไร?
Cloud Computing คือการใช้ computing resources (servers, storage, databases, networking) ผ่าน internet แทนที่จะซื้อเครื่องเอง:
Cloud Service Models — IaaS / PaaS / SaaS
Cloud services แบ่งเป็น 3 ระดับตามว่า provider จัดการให้มากน้อยแค่ไหน — IaaS (Infrastructure as a Service) ให้ VM/storage มาเปล่าๆ คุณจัดการ OS ขึ้นไปเอง เหมือนเช่าห้องเปล่า, PaaS (Platform as a Service) จัดการ server ให้ คุณแค่ deploy code เหมือน co-working space, SaaS (Software as a Service) ใช้งานได้เลย เหมือนโรงแรม ยิ่ง managed เยอะ ยิ่งสะดวก แต่ flexibility น้อยลง:
| Model | คุณจัดการ | Cloud จัดการ | ตัวอย่าง |
|---|---|---|---|
| IaaS | OS, Runtime, App, Data | Server, Storage, Network | EC2, GCE, Azure VM |
| PaaS | App, Data | OS, Runtime, Server | Heroku, App Engine, Elastic Beanstalk |
| SaaS | แค่ใช้งาน | ทุกอย่าง | Gmail, Slack, Salesforce |
| FaaS | แค่ code (functions) | ทุกอย่าง + scaling | Lambda, Cloud Functions |
💡 จำง่ายๆ: IaaS = เช่าเครื่อง | PaaS = เช่า platform | SaaS = เช่า app | FaaS = เช่า function
🏢 3 Cloud Providers หลัก
ตลาด Cloud ถูกครอง 3 เจ้าใหญ่ — AWS (Amazon) มี market share มากที่สุด (~32%) มี services มากกว่า 200 ตัว, Azure (Microsoft) แข็งแกร่งด้าน enterprise และ hybrid cloud, GCP (Google) เด่นด้าน data/AI และ Kubernetes (Google สร้าง K8s) การเลือก provider ขึ้นอยู่กับ workload, ทีม, และ existing ecosystem มากกว่า "ใครดีกว่า":
- Compute: EC2, Lambda, ECS, EKS
- Storage: S3, EBS, EFS
- Database: RDS, DynamoDB, ElastiCache
- Network: VPC, ALB, CloudFront, Route53
- Monitor: CloudWatch, X-Ray
- Market share: ~31%
- Compute: VMs, Functions, AKS
- Storage: Blob, Disk, Files
- Database: SQL DB, Cosmos DB, Redis
- Network: VNet, App Gateway, Front Door
- Monitor: Monitor, App Insights
- Market share: ~25%
- Compute: GCE, Cloud Run, GKE
- Storage: Cloud Storage, Persistent Disk
- Database: Cloud SQL, Firestore, Bigtable
- Network: VPC, Cloud Load Balancing, CDN
- Monitor: Cloud Monitoring, Trace
- Market share: ~11%
Service Mapping — เปรียบเทียบ 3 Providers
แต่ละ provider เรียกชื่อ services ต่างกันแต่ทำหน้าที่เหมือนกัน — ตารางด้านล่างช่วยให้เปรียบเทียบได้เร็ว เช่น AWS EC2 = Azure VM = GCP Compute Engine, AWS S3 = Azure Blob = GCP Cloud Storage:
| Category | AWS | Azure | GCP |
|---|---|---|---|
| VM | EC2 | Virtual Machines | Compute Engine |
| Serverless | Lambda | Functions | Cloud Functions / Cloud Run |
| Kubernetes | EKS | AKS | GKE |
| Object Storage | S3 | Blob Storage | Cloud Storage |
| SQL Database | RDS / Aurora | SQL Database | Cloud SQL / Spanner |
| NoSQL | DynamoDB | Cosmos DB | Firestore / Bigtable |
| Cache | ElastiCache | Azure Redis | Memorystore |
| CDN | CloudFront | Front Door | Cloud CDN |
| DNS | Route 53 | Azure DNS | Cloud DNS |
| Message Queue | SQS / SNS | Service Bus | Pub/Sub |
| IaC | CloudFormation | ARM / Bicep | Deployment Manager |
🏗️ Well-Architected Framework
AWS, Azure และ GCP ต่างมี Well-Architected Framework — แนวทางออกแบบระบบบน cloud ที่ดี ประกอบด้วย 6 pillars:
🌐 VPC & Networking — เครือข่ายบน Cloud
VPC (Virtual Private Cloud) คือ "เครือข่ายส่วนตัว" ของคุณบน Cloud — เหมือนกั้นรั้วล้อมรอบ resources ทั้งหมดของคุณ ไม่ให้ใครเข้าถึงได้นอกจากที่อนุญาต การออกแบบ VPC ที่ดีคือรากฐานของ cloud security — แบ่ง subnets เป็น public (รับ traffic จาก internet) และ private (เข้าถึงได้เฉพาะภายใน) ใช้ Security Groups เป็น firewall ควบคุม traffic:
# Terraform — สร้าง VPC + Subnets
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = { Name = "production-vpc" }
}
# Public Subnet — internet access
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-southeast-1a"
map_public_ip_on_launch = true
tags = { Name = "public-subnet-1a" }
}
# Private Subnet — no direct internet
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.10.0/24"
availability_zone = "ap-southeast-1a"
tags = { Name = "private-subnet-1a" }
}
# Internet Gateway (public subnet access)
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main.id
}
# NAT Gateway (private subnet → internet)
resource "aws_nat_gateway" "nat" {
subnet_id = aws_subnet.public.id
allocation_id = aws_eip.nat.id
}
# Security Group
resource "aws_security_group" "web" {
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # HTTPS from anywhere
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # HTTP → redirect to HTTPS
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] # Allow all outbound
}
}
💡 กฎทอง: Web/App servers → Public Subnet | Database/Cache → Private Subnet (ไม่เปิด internet ตรง!)
⚡ High Availability — ระบบล่มไม่ได้!
High Availability (HA) คือการออกแบบให้ระบบทำงานได้ต่อเนื่องแม้ส่วนใดส่วนหนึ่งล่ม — หลักการสำคัญคือ "ไม่พึ่ง single point of failure" ทุก component ต้องมีอย่างน้อย 2 ตัว กระจายอยู่คนละ Availability Zone (AZ) หรือคนละ Region ถ้า AZ หนึ่งล่ม อีก AZ รับ traffic แทนได้ทันที Cloud providers ออกแบบ AZ ให้แยก power, cooling, networking จากกัน:
| Availability | Downtime/year | วิธีทำ |
|---|---|---|
| 99% | 3.65 วัน | Single server |
| 99.9% | 8.76 ชม. | Load balancer + multiple servers |
| 99.99% | 52.6 นาที | Multi-AZ + auto-failover |
| 99.999% | 5.26 นาที | Multi-region + active-active |
# Terraform — Auto Scaling Group
resource "aws_autoscaling_group" "app" {
name = "app-asg"
min_size = 2
max_size = 10
desired_capacity = 4
vpc_zone_identifier = [
aws_subnet.private_1a.id,
aws_subnet.private_1b.id,
aws_subnet.private_1c.id, # กระจาย 3 AZs
]
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
target_group_arns = [aws_lb_target_group.app.arn]
health_check_type = "ELB"
health_check_grace_period = 300
}
# Auto Scaling Policy — CPU > 70% → scale up
resource "aws_autoscaling_policy" "scale_up" {
name = "scale-up"
autoscaling_group_name = aws_autoscaling_group.app.name
policy_type = "TargetTrackingScaling"
target_tracking_configuration {
predefined_metric_specification {
predefined_metric_type = "ASGAverageCPUUtilization"
}
target_value = 70.0
}
}
🚀 Serverless Architecture
Serverless = ไม่ต้องจัดการ server เลย แค่เขียน code แล้ว deploy — cloud จัดการ scaling, patching, HA ให้หมด:
# AWS Lambda + API Gateway (Serverless Framework)
# serverless.yml
service: my-api
provider:
name: aws
runtime: nodejs20.x
region: ap-southeast-1
memorySize: 256
timeout: 30
environment:
TABLE_NAME: ${self:service}-${sls:stage}
functions:
getUser:
handler: src/handlers/getUser.handler
events:
- http:
path: /users/{id}
method: get
cors: true
createUser:
handler: src/handlers/createUser.handler
events:
- http:
path: /users
method: post
cors: true
processOrder:
handler: src/handlers/processOrder.handler
events:
- sqs: # Trigger จาก SQS queue
arn: !GetAtt OrderQueue.Arn
batchSize: 10
resources:
Resources:
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:service}-${sls:stage}
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
# Deploy
serverless deploy --stage production
# ได้ endpoint เช่น:
# https://abc123.execute-api.ap-southeast-1.amazonaws.com/production/users
Serverless: ข้อดี vs ข้อเสีย
Serverless ไม่ใช่ "silver bullet" — เหมาะกับ event-driven workloads ที่ traffic ไม่สม่ำเสมอ (APIs ที่ request มาเป็นช่วงๆ, image processing, scheduled jobs) แต่ไม่เหมาะกับ long-running tasks หรือ workloads ที่ต้องการ persistent connections ข้อดีคือ scale เป็น 0 ได้ (ไม่ใช้ไม่จ่าย) ข้อเสียคือ cold start delay และ vendor lock-in:
| ✅ ข้อดี | ⚠️ ข้อเสีย |
|---|---|
| ไม่ต้องจัดการ server | Cold start (ช้าตอน function ตื่น) |
| Scale อัตโนมัติ (0 → ∞) | Timeout limit (Lambda max 15 min) |
| จ่ายตามใช้งาน (pay-per-request) | Vendor lock-in |
| HA built-in | Debug ยากกว่า |
| เร็วในการ deploy | ไม่เหมาะกับ long-running tasks |
💰 Cost Optimization — ลดค่า Cloud
Cloud แพงได้ถ้าไม่ระวัง! นี่คือวิธีลดค่าใช้จ่าย:
1. Right-sizing — เลือก instance ให้เหมาะ
ข้อผิดพลาดที่พบบ่อยที่สุดคือเลือก instance ใหญ่เกินไป "เผื่อไว้" — ซึ่งเปลืองเงินมาก! ใช้ CloudWatch/Monitoring ดู CPU/Memory utilization จริง ถ้าใช้ไม่ถึง 40% ลดขนาดลงได้:
# ตรวจ CPU/Memory utilization
# ถ้า avg CPU < 20% → downsize!
# AWS Cost Explorer recommendation
aws ce get-rightsizing-recommendation \
--service EC2 \
--configuration '{"RecommendationTarget":"SAME_INSTANCE_FAMILY"}'
2. Reserved / Savings Plans
ถ้ารู้ว่าจะใช้ workload อะไรไปอีก 1-3 ปี Reserved Instances หรือ Savings Plans ประหยัดได้ 30-72% เทียบกับ on-demand — ยิ่งจ่ายล่วงหน้ามาก ยิ่งประหยัดมาก:
| Pricing Model | ส่วนลด | เหมาะกับ |
|---|---|---|
| On-Demand | 0% (ราคาเต็ม) | ทดสอบ, traffic ไม่แน่นอน |
| Reserved (1yr) | ~30-40% | Workload คงที่ |
| Reserved (3yr) | ~50-60% | Workload คงที่ระยะยาว |
| Spot Instances | ~60-90%! | Batch jobs, CI/CD, stateless |
| Savings Plans | ~30-50% | ยืดหยุ่นกว่า Reserved |
3. Auto-shutdown Dev/Staging
Dev/Staging environments ไม่จำเป็นต้องรัน 24/7 — ถ้าทีมทำงาน 9:00-18:00 ปิด instances นอกเวลาทำงานประหยัดได้ ~70%! ใช้ Lambda function + CloudWatch Events schedule ให้ start/stop อัตโนมัติ:
# Lambda function — ปิด dev instances ตอนกลางคืน
import boto3
def handler(event, context):
ec2 = boto3.client('ec2')
# หา instances ที่มี tag Environment=dev
instances = ec2.describe_instances(
Filters=[
{'Name': 'tag:Environment', 'Values': ['dev', 'staging']},
{'Name': 'instance-state-name', 'Values': ['running']}
]
)
ids = []
for r in instances['Reservations']:
for i in r['Instances']:
ids.append(i['InstanceId'])
if ids:
ec2.stop_instances(InstanceIds=ids)
print(f"Stopped {len(ids)} instances: {ids}")
# Schedule: ปิดทุก 20:00 เปิดทุก 08:00
# → ประหยัด ~50% ค่า dev/staging!
4. Storage Lifecycle
ข้อมูลที่เก่าแล้วไม่จำเป็นต้องอยู่ใน storage ราคาแพง — ใช้ Lifecycle Policies ย้ายข้อมูลอัตโนมัติจาก S3 Standard → S3 IA (Infrequent Access) → Glacier ตามอายุ ประหยัดได้ 60-90%:
# S3 Lifecycle — ย้ายข้อมูลเก่าไป storage ถูกกว่า
resource "aws_s3_bucket_lifecycle_configuration" "logs" {
bucket = aws_s3_bucket.logs.id
rule {
id = "archive-old-logs"
status = "Enabled"
transition {
days = 30
storage_class = "STANDARD_IA" # 30 วัน → Infrequent Access (-40%)
}
transition {
days = 90
storage_class = "GLACIER" # 90 วัน → Glacier (-80%)
}
expiration {
days = 365 # 1 ปี → ลบทิ้ง
}
}
}
🐕 สำคัญ! ตั้ง billing alerts เสมอ! ไม่งั้นตื่นมาเจอบิล $10,000 จะร้องไห้
# AWS Budget Alert — แจ้งเตือนเมื่อค่าใช้จ่ายเกิน
resource "aws_budgets_budget" "monthly" {
name = "monthly-budget"
budget_type = "COST"
limit_amount = "500"
limit_unit = "USD"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = 80 # แจ้งเมื่อถึง 80%
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = ["[email protected]"]
}
}
🔒 Cloud Security — ปกป้องระบบ
Cloud security ต่างจาก on-premise ตรงที่ใช้ Shared Responsibility Model — provider ดูแล security "ของ" cloud (physical, hypervisor, network) ส่วนคุณดูแล security "บน" cloud (data, access, config, OS patching) ข้อผิดพลาดที่พบบ่อยที่สุดคือ misconfiguration — S3 bucket เปิด public, IAM policy ให้สิทธิ์มากเกิน, Security Group เปิด port 0.0.0.0/0
IAM — Identity & Access Management
IAM คือระบบจัดการ "ใครมีสิทธิ์ทำอะไร" — หลักการสำคัญที่สุดคือ Least Privilege (ให้สิทธิ์เท่าที่จำเป็น) อย่าใช้ root account สำหรับงานประจำวัน สร้าง IAM users/roles ที่มี permissions เฉพาะงาน:
# Principle of Least Privilege — ให้สิทธิ์น้อยที่สุด
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/uploads/*"
}
]
}
# ❌ อย่าทำ!
# "Action": "*"
# "Resource": "*"
# → Full admin access ทุก service = อันตราย!
Security Checklist
Checklist ด้านล่างครอบคลุม security best practices ที่ทุก cloud deployment ต้องทำ — ตั้งแต่ MFA, encryption at rest/in transit, logging, ไปจนถึง vulnerability scanning:
- MFA — เปิด Multi-Factor Auth ทุก account โดยเฉพาะ root
- Least Privilege — ให้สิทธิ์น้อยที่สุดเท่าที่ต้องใช้
- Encrypt — encrypt data at rest (KMS) และ in transit (TLS)
- Private Subnets — DB/cache อยู่ใน private subnet เท่านั้น
- Security Groups — เปิด port เฉพาะที่ต้องใช้ (ไม่ 0.0.0.0/0 ทุก port!)
- Secrets Manager — อย่า hardcode credentials ใน code!
- CloudTrail — เปิด audit log ทุก API call
- GuardDuty — threat detection อัตโนมัติ
📊 Cloud Architecture Patterns
มาถึง patterns ที่ใช้จริงในการออกแบบระบบบน Cloud — แต่ละ pattern เหมาะกับ workload ต่างกัน ไม่มี "pattern ที่ดีที่สุด" มีแต่ "pattern ที่เหมาะสมที่สุด" กับ requirements ของคุณ เริ่มจาก simple แล้วค่อย evolve ตามความต้องการ:
1. Three-Tier Architecture (คลาสสิค)
Three-Tier แบ่งระบบเป็น 3 ชั้น — Presentation (frontend), Application (backend logic), Data (database) เป็น pattern คลาสสิคที่เข้าใจง่ายและเหมาะกับ web apps ส่วนใหญ่ เริ่มต้นด้วย pattern นี้ก่อน แล้วค่อยแยกเป็น microservices เมื่อ scale จนจำเป็น:
2. Event-Driven Architecture
Event-Driven Architecture คือการออกแบบให้ components สื่อสารกันผ่าน "events" แทนการเรียกตรง — เมื่อสิ่งหนึ่งเกิดขึ้น (เช่น user สั่งซื้อ) จะสร้าง event ส่งไปยัง message queue แล้ว services อื่นๆ รับไปทำงานต่อ ข้อดีคือ loose coupling — แต่ละ service ไม่ต้องรู้จักกัน:
Event-Driven pattern ทำให้ระบบมี resilience สูงเพราะหาก component หนึ่งล่ม events จะถูก queue ไว้และ process เมื่อ component กลับมา online ได้ การใช้ managed message queues อย่าง SQS, SNS หรือ EventBridge จะช่วยให้ระบบ scale ได้ดีและลด operational overhead
ข้อจำกัดของ pattern นี้คือการ debug และ monitoring ยากกว่าเพราะ flow ของข้อมูลไม่เป็นเส้นตรง และการ ensure eventual consistency ระหว่าง services ต้องใช้เทคนิคพิเศษ เช่น saga pattern หรือ event sourcing แต่สำหรับ use cases ที่เหมาะสม benefits ที่ได้จะมากกว่า complexity ที่เพิ่มขึ้น
3. Microservices on Kubernetes
Microservices บน Kubernetes เป็น pattern ที่ซับซ้อนที่สุดแต่ให้ benefits มากที่สุดสำหรับ large-scale applications การแยกแต่ละ business capability เป็น independent service ที่มี database ของตัวเองทำให้ทีมสามารถ develop, test และ deploy แยกกันได้ เหมาะกับองค์กรขนาดใหญ่ที่มีหลายทีม development
# แต่ละ service เป็น independent deployment
services:
├── user-service (EKS pod, own DynamoDB table)
├── order-service (EKS pod, own RDS database)
├── payment-service (EKS pod, connects Stripe)
├── notification-svc (Lambda, triggered by SQS)
└── api-gateway (Kong / AWS API Gateway)
# Communication:
sync → REST / gRPC (service-to-service)
async → SQS / SNS / EventBridge (event-driven)
Microservices architecture ตัวอย่างด้านบนแสดงการแยก services ตาม domain boundaries แทนที่จะแยกตาม technical layers แต่ละ service มี database ของตัวเองและสื่อสารกันผ่าน well-defined APIs การใช้ Kubernetes จะช่วยในการ orchestrate containers และ manage networking ระหว่าง services
ข้อดีของ pattern นี้คือ scalability และ development velocity ที่สูงมากสำหรับทีมขนาดใหญ่ แต่ cost และ complexity ก็สูงตามไปด้วย ไม่เหมาะกับ small teams หรือ simple applications การเลือกใช้ microservices ควรพิจารณาจาก organizational readiness มากกว่า technical requirements เพียงอย่างเดียว
สรุป
Cloud Architecture เป็นศาสตร์และศิลป์ที่ผสมผสานระหว่างความรู้ทางเทคนิคและความเข้าใจทางธุรกิจ การออกแบบระบบที่ดีไม่ใช่แค่การเลือก services ที่ล่าสุดหรือแพงที่สุด แต่เป็นการหาสมดุลระหว่าง technical requirements และ business constraints ให้เหมาะสมกับบริบทเฉพาะของแต่ละองค์กร
สิ่งสำคัญที่สุดคือการเริ่มต้นแบบ simple แล้วค่อย ๆ เพิ่ม complexity เมื่อจำเป็น การ over-engineer ตั้งแต่เริ่มต้นมักจะสร้างปัญหามากกว่าแก้ปัญหา การ monitor, measure และ iterate อย่างต่อเนื่องจะช่วยให้ระบบพัฒนาไปในทิศทางที่ถูกต้องและ sustainable ในระยะยาว
- Cloud Computing = เช่าใช้ resources จ่ายตามใช้งาน (IaaS / PaaS / SaaS / FaaS)
- 3 Providers = AWS (~31%), Azure (~25%), GCP (~11%) — services คล้ายกัน ชื่อต่าง
- Well-Architected = 6 pillars: Security, Reliability, Performance, Cost, Operations, Sustainability
- VPC = แยก public/private subnet, Security Groups จำกัด port
- High Availability = Multi-AZ, Auto Scaling, Load Balancer → 99.99% uptime
- Serverless = Lambda/Cloud Functions ไม่ต้องจัดการ server, scale อัตโนมัติ
- Cost = Right-size, Reserved/Spot instances, auto-shutdown dev, storage lifecycle
- Security = IAM least privilege, MFA, encrypt everything, private subnets ☁️🐕
Across this series we have learned Docker, Kubernetes, IaC and GitOps — but all of it runs on infrastructure, whether that is your own machine, a VPS or the cloud.
Today we learn Cloud Architecture — how to design systems on the cloud that are solid, scalable, secure and cost-effective ☁️🐕
☁️ What Is Cloud Computing?
Cloud computing means using computing resources (servers, storage, databases, networking) over the internet instead of buying the machines yourself:
Cloud Service Models — IaaS / PaaS / SaaS
Cloud services fall into three levels according to how much the provider manages for you — IaaS (Infrastructure as a Service) hands you a bare VM and storage and leaves everything from the OS upward to you, like renting an empty room; PaaS (Platform as a Service) manages the server so you only deploy code, like a co-working space; SaaS (Software as a Service) is ready to use, like a hotel. The more managed it is, the more convenient — and the less flexible:
| Model | You manage | Cloud manages | Examples |
|---|---|---|---|
| IaaS | OS, Runtime, App, Data | Server, Storage, Network | EC2, GCE, Azure VM |
| PaaS | App, Data | OS, Runtime, Server | Heroku, App Engine, Elastic Beanstalk |
| SaaS | Just use it | Everything | Gmail, Slack, Salesforce |
| FaaS | Just the code (functions) | Everything + scaling | Lambda, Cloud Functions |
💡 An easy way to remember: IaaS = rent a machine | PaaS = rent a platform | SaaS = rent an app | FaaS = rent a function
🏢 The 3 Major Cloud Providers
The cloud market is dominated by three giants — AWS (Amazon) holds the largest market share (~32%) and offers more than 200 services; Azure (Microsoft) is strong in enterprise and hybrid cloud; GCP (Google) leads on data/AI and Kubernetes (Google built K8s). Choosing a provider depends on your workload, your team and your existing ecosystem far more than on "who is better":
- Compute: EC2, Lambda, ECS, EKS
- Storage: S3, EBS, EFS
- Database: RDS, DynamoDB, ElastiCache
- Network: VPC, ALB, CloudFront, Route53
- Monitor: CloudWatch, X-Ray
- Market share: ~31%
- Compute: VMs, Functions, AKS
- Storage: Blob, Disk, Files
- Database: SQL DB, Cosmos DB, Redis
- Network: VNet, App Gateway, Front Door
- Monitor: Monitor, App Insights
- Market share: ~25%
- Compute: GCE, Cloud Run, GKE
- Storage: Cloud Storage, Persistent Disk
- Database: Cloud SQL, Firestore, Bigtable
- Network: VPC, Cloud Load Balancing, CDN
- Monitor: Cloud Monitoring, Trace
- Market share: ~11%
Service Mapping — Comparing the 3 Providers
Each provider names its services differently while doing the same job — the table below makes the comparison quick. AWS EC2 = Azure VM = GCP Compute Engine, AWS S3 = Azure Blob = GCP Cloud Storage:
| Category | AWS | Azure | GCP |
|---|---|---|---|
| VM | EC2 | Virtual Machines | Compute Engine |
| Serverless | Lambda | Functions | Cloud Functions / Cloud Run |
| Kubernetes | EKS | AKS | GKE |
| Object Storage | S3 | Blob Storage | Cloud Storage |
| SQL Database | RDS / Aurora | SQL Database | Cloud SQL / Spanner |
| NoSQL | DynamoDB | Cosmos DB | Firestore / Bigtable |
| Cache | ElastiCache | Azure Redis | Memorystore |
| CDN | CloudFront | Front Door | Cloud CDN |
| DNS | Route 53 | Azure DNS | Cloud DNS |
| Message Queue | SQS / SNS | Service Bus | Pub/Sub |
| IaC | CloudFormation | ARM / Bicep | Deployment Manager |
🏗️ Well-Architected Framework
AWS, Azure and GCP each publish a Well-Architected Framework — a guide to designing good systems on the cloud, built on 6 pillars:
🌐 VPC & Networking — Your Network on the Cloud
A VPC (Virtual Private Cloud) is your own "private network" on the cloud — a fence drawn around all of your resources so that nobody reaches them except the people you allow. A well-designed VPC is the foundation of cloud security: split the subnets into public (accepting traffic from the internet) and private (reachable only from inside), and use Security Groups as the firewall that controls traffic:
# Terraform — create the VPC + subnets
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = { Name = "production-vpc" }
}
# Public Subnet — internet access
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-southeast-1a"
map_public_ip_on_launch = true
tags = { Name = "public-subnet-1a" }
}
# Private Subnet — no direct internet
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.10.0/24"
availability_zone = "ap-southeast-1a"
tags = { Name = "private-subnet-1a" }
}
# Internet Gateway (public subnet access)
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main.id
}
# NAT Gateway (private subnet → internet)
resource "aws_nat_gateway" "nat" {
subnet_id = aws_subnet.public.id
allocation_id = aws_eip.nat.id
}
# Security Group
resource "aws_security_group" "web" {
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # HTTPS from anywhere
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # HTTP → redirect to HTTPS
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] # Allow all outbound
}
}
💡 The golden rule: Web/App servers → public subnet | Database/Cache → private subnet (never exposed directly to the internet!)
⚡ High Availability — The System Cannot Go Down!
High Availability (HA) means designing the system to keep working even when one part of it fails — the core principle being "depend on no single point of failure". Every component needs at least two instances, spread across different Availability Zones (AZs) or different regions, so that if one AZ goes down another can take the traffic immediately. Cloud providers build AZs with separate power, cooling and networking for exactly this reason:
| Availability | Downtime/year | How to get there |
|---|---|---|
| 99% | 3.65 days | Single server |
| 99.9% | 8.76 hours | Load balancer + multiple servers |
| 99.99% | 52.6 minutes | Multi-AZ + auto-failover |
| 99.999% | 5.26 minutes | Multi-region + active-active |
# Terraform — Auto Scaling Group
resource "aws_autoscaling_group" "app" {
name = "app-asg"
min_size = 2
max_size = 10
desired_capacity = 4
vpc_zone_identifier = [
aws_subnet.private_1a.id,
aws_subnet.private_1b.id,
aws_subnet.private_1c.id, # spread across 3 AZs
]
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
target_group_arns = [aws_lb_target_group.app.arn]
health_check_type = "ELB"
health_check_grace_period = 300
}
# Auto Scaling Policy — CPU > 70% → scale up
resource "aws_autoscaling_policy" "scale_up" {
name = "scale-up"
autoscaling_group_name = aws_autoscaling_group.app.name
policy_type = "TargetTrackingScaling"
target_tracking_configuration {
predefined_metric_specification {
predefined_metric_type = "ASGAverageCPUUtilization"
}
target_value = 70.0
}
}
🚀 Serverless Architecture
Serverless = no server management at all; you write the code and deploy it, and the cloud handles scaling, patching and HA for you:
# AWS Lambda + API Gateway (Serverless Framework)
# serverless.yml
service: my-api
provider:
name: aws
runtime: nodejs20.x
region: ap-southeast-1
memorySize: 256
timeout: 30
environment:
TABLE_NAME: ${self:service}-${sls:stage}
functions:
getUser:
handler: src/handlers/getUser.handler
events:
- http:
path: /users/{id}
method: get
cors: true
createUser:
handler: src/handlers/createUser.handler
events:
- http:
path: /users
method: post
cors: true
processOrder:
handler: src/handlers/processOrder.handler
events:
- sqs: # Triggered by an SQS queue
arn: !GetAtt OrderQueue.Arn
batchSize: 10
resources:
Resources:
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:service}-${sls:stage}
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
# Deploy
serverless deploy --stage production
# you get an endpoint such as:
# https://abc123.execute-api.ap-southeast-1.amazonaws.com/production/users
Serverless: Pros vs Cons
Serverless is no silver bullet — it suits event-driven workloads with uneven traffic (APIs that receive requests in bursts, image processing, scheduled jobs) but not long-running tasks or workloads that need persistent connections. The upside is that it scales to zero (no usage, no bill); the downsides are cold-start delay and vendor lock-in:
| ✅ Pros | ⚠️ Cons |
|---|---|
| No server management | Cold start (slow when the function wakes) |
| Automatic scaling (0 → ∞) | Timeout limit (Lambda maxes out at 15 min) |
| Pay for what you use (pay-per-request) | Vendor lock-in |
| HA built-in | Harder to debug |
| Fast to deploy | Unsuitable for long-running tasks |
💰 Cost Optimization — Cutting the Cloud Bill
The cloud gets expensive if you are not careful! Here is how to bring the spending down:
1. Right-sizing — pick the instance that fits
The most common mistake is picking an instance that is far too large "just in case" — which wastes a great deal of money. Use CloudWatch/Monitoring to look at real CPU/memory utilization; if you are not even reaching 40%, size it down:
# Check CPU/Memory utilization
# if avg CPU < 20% → downsize!
# AWS Cost Explorer recommendation
aws ce get-rightsizing-recommendation \
--service EC2 \
--configuration '{"RecommendationTarget":"SAME_INSTANCE_FAMILY"}'
2. Reserved / Savings Plans
If you know a workload will be around for the next 1-3 years, Reserved Instances or Savings Plans save 30-72% against on-demand — and the more you pay up front, the more you save:
| Pricing Model | Discount | Best for |
|---|---|---|
| On-Demand | 0% (full price) | Testing, unpredictable traffic |
| Reserved (1yr) | ~30-40% | Steady workloads |
| Reserved (3yr) | ~50-60% | Steady long-term workloads |
| Spot Instances | ~60-90%! | Batch jobs, CI/CD, stateless |
| Savings Plans | ~30-50% | More flexible than Reserved |
3. Auto-shutdown for Dev/Staging
Dev and staging environments do not need to run 24/7 — if the team works 9:00-18:00, shutting the instances down outside working hours saves around 70%! Use a Lambda function plus a CloudWatch Events schedule to start and stop them automatically:
# Lambda function — shut dev instances down overnight
import boto3
def handler(event, context):
ec2 = boto3.client('ec2')
# find instances tagged Environment=dev
instances = ec2.describe_instances(
Filters=[
{'Name': 'tag:Environment', 'Values': ['dev', 'staging']},
{'Name': 'instance-state-name', 'Values': ['running']}
]
)
ids = []
for r in instances['Reservations']:
for i in r['Instances']:
ids.append(i['InstanceId'])
if ids:
ec2.stop_instances(InstanceIds=ids)
print(f"Stopped {len(ids)} instances: {ids}")
# Schedule: stop every day at 20:00, start every day at 08:00
# → saves ~50% of the dev/staging bill!
4. Storage Lifecycle
Data that has aged does not need to sit in expensive storage — use Lifecycle Policies to move it automatically from S3 Standard → S3 IA (Infrequent Access) → Glacier as it ages, saving 60-90%:
# S3 Lifecycle — move old data to cheaper storage
resource "aws_s3_bucket_lifecycle_configuration" "logs" {
bucket = aws_s3_bucket.logs.id
rule {
id = "archive-old-logs"
status = "Enabled"
transition {
days = 30
storage_class = "STANDARD_IA" # 30 days → Infrequent Access (-40%)
}
transition {
days = 90
storage_class = "GLACIER" # 90 days → Glacier (-80%)
}
expiration {
days = 365 # 1 year → delete
}
}
}
🐕 Important! Always set billing alerts! Otherwise you wake up to a $10,000 bill and cry.
# AWS Budget Alert — warn when spending goes over
resource "aws_budgets_budget" "monthly" {
name = "monthly-budget"
budget_type = "COST"
limit_amount = "500"
limit_unit = "USD"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = 80 # alert at 80%
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = ["[email protected]"]
}
}
🔒 Cloud Security — Protecting the System
Cloud security differs from on-premise in that it runs on a Shared Responsibility Model — the provider secures the cloud itself (physical, hypervisor, network), while you secure what you put on it (data, access, configuration, OS patching). The most common failure by far is misconfiguration — an S3 bucket left public, an IAM policy that grants far too much, a Security Group open on 0.0.0.0/0.
IAM — Identity & Access Management
IAM is the system that governs "who is allowed to do what" — and its most important principle is Least Privilege (grant only what is needed). Do not use the root account for daily work; create IAM users and roles whose permissions match the job:
# Principle of Least Privilege — grant the minimum
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/uploads/*"
}
]
}
# ❌ Never do this!
# "Action": "*"
# "Resource": "*"
# → full admin access to every service = dangerous!
Security Checklist
The checklist below covers the security practices every cloud deployment needs — from MFA, encryption at rest and in transit, and logging, through to vulnerability scanning:
- MFA — turn on multi-factor auth for every account, root above all
- Least Privilege — grant the smallest set of permissions that works
- Encrypt — encrypt data at rest (KMS) and in transit (TLS)
- Private Subnets — DB and cache live in private subnets only
- Security Groups — open only the ports you use (not 0.0.0.0/0 on everything!)
- Secrets Manager — never hardcode credentials in code!
- CloudTrail — keep an audit log of every API call
- GuardDuty — automatic threat detection
📊 Cloud Architecture Patterns
Now to the patterns actually used when designing systems on the cloud — each one suits a different workload. There is no "best pattern", only the one that fits your requirements best. Start simple and let it evolve as the need appears:
1. Three-Tier Architecture (the classic)
Three-Tier splits the system into three layers — presentation (frontend), application (backend logic) and data (database). It is the classic pattern: easy to understand and a fit for most web apps. Start here, and only split into microservices once scale makes it necessary:
2. Event-Driven Architecture
Event-Driven Architecture has components talk to each other through "events" instead of direct calls — when something happens (a user places an order, say) an event is created and sent to a message queue, and other services pick it up and carry on the work. The benefit is loose coupling: no service needs to know about any other:
The event-driven pattern gives a system high resilience, because if one component goes down the events stay queued and are processed once it comes back online. Using managed message queues such as SQS, SNS or EventBridge helps the system scale well and cuts the operational overhead.
The limitation of this pattern is that debugging and monitoring are harder, because the flow of data is not a straight line, and ensuring eventual consistency between services calls for special techniques such as the saga pattern or event sourcing. For the right use cases, though, the benefits outweigh the added complexity.
3. Microservices on Kubernetes
Microservices on Kubernetes is the most complex pattern here, and the one that pays back most for large-scale applications. Splitting each business capability into an independent service with its own database lets teams develop, test and deploy separately — a fit for large organizations with several development teams.
# each service is an independent deployment
services:
├── user-service (EKS pod, own DynamoDB table)
├── order-service (EKS pod, own RDS database)
├── payment-service (EKS pod, connects Stripe)
├── notification-svc (Lambda, triggered by SQS)
└── api-gateway (Kong / AWS API Gateway)
# Communication:
sync → REST / gRPC (service-to-service)
async → SQS / SNS / EventBridge (event-driven)
The microservices architecture above splits services along domain boundaries rather than technical layers. Each service owns its database and communicates through well-defined APIs, with Kubernetes orchestrating the containers and managing the networking between services.
The advantage of this pattern is very high scalability and development velocity for large teams — but cost and complexity rise with it, which makes it a poor fit for small teams or simple applications. The decision to adopt microservices should weigh organizational readiness more heavily than technical requirements alone.
Summary
Cloud architecture is both a science and an art, blending technical knowledge with business understanding. Designing a good system is not a matter of choosing the newest or most expensive services; it is a matter of balancing technical requirements against business constraints in a way that suits the specific context of each organization.
The most important thing is to start simple and add complexity only when it is needed. Over-engineering from the outset usually creates more problems than it solves. Monitoring, measuring and iterating continuously is what keeps a system developing in the right direction and sustainable over the long run.
- Cloud Computing = rent your resources, pay for what you use (IaaS / PaaS / SaaS / FaaS)
- 3 Providers = AWS (~31%), Azure (~25%), GCP (~11%) — similar services, different names
- Well-Architected = 6 pillars: Security, Reliability, Performance, Cost, Operations, Sustainability
- VPC = separate public/private subnets, Security Groups limiting the ports
- High Availability = Multi-AZ, Auto Scaling, Load Balancer → 99.99% uptime
- Serverless = Lambda/Cloud Functions, no server management, automatic scaling
- Cost = right-size, Reserved/Spot instances, auto-shutdown for dev, storage lifecycle
- Security = IAM least privilege, MFA, encrypt everything, private subnets ☁️🐕