Table of Contents

  1. Introduction
  2. Core Concepts
  3. Provider Comparison
  4. AWS EC2
  5. Azure Virtual Machines
  6. GCP Compute Engine
  7. Auto Scaling
  8. Pricing Models
  9. Best Practices
  10. Conclusion
Back to Technology

Cloud Compute Services Guide

January 25, 2026 Wasil Zafar 45 min read

Master cloud virtual machines across AWS EC2, Azure VMs, and Google Compute Engine with practical CLI examples, auto-scaling, and cost optimization strategies.

Introduction

Cloud compute services form the foundation of modern cloud infrastructure, providing on-demand virtual machines that can be provisioned in minutes and scaled to meet any workload. Understanding how to effectively use these services across providers is essential for any cloud practitioner.

Cloud compute services overview showing VM provisioning across AWS, Azure, and GCP
Figure 1: Cloud compute services provide on-demand virtual machines that can be provisioned in minutes across major providers.
What We'll Cover:
  • AWS EC2 - Elastic Compute Cloud instances
  • Azure VMs - Azure Virtual Machines
  • GCP Compute Engine - Google's VM instances
  • Instance types, families, and sizing
  • Auto-scaling and load balancing
  • Pricing models and cost optimization

Core Concepts

Virtual Machine Components

Every cloud VM consists of several key components:

Virtual machine components including vCPUs, memory, storage, and network interfaces
Figure 2: Core components of a cloud virtual machine — vCPUs, memory, storage, network, and machine image.
  • vCPUs - Virtual CPU cores (typically hyperthreaded)
  • Memory (RAM) - Allocated system memory
  • Storage - Root disk and additional data disks
  • Network - Virtual NICs, IP addresses, bandwidth
  • Machine Image - OS and pre-installed software template

Instance Families

All providers organize instance types into families optimized for different workloads:

Workload Type AWS Azure GCP
General Purpose M5, M6i, M7g, T3 D-series, B-series E2, N2, N2D
Compute Optimized C5, C6i, C7g F-series C2, C2D, H3
Memory Optimized R5, R6i, X2 E-series, M-series M2, M3
Storage Optimized I3, I4i, D3 L-series Z3
GPU/Accelerated P4, G5, Inf2 NC, ND, NV-series A2, G2

Provider Comparison

Feature AWS EC2 Azure VMs GCP Compute
CLI Tool aws ec2 az vm gcloud compute
Image Name AMI Image Image
Spot/Preemptible Spot Instances Spot VMs Spot VMs
Reserved Reserved Instances, Savings Plans Reserved VM Instances Committed Use Discounts
Auto Scaling Auto Scaling Groups VM Scale Sets Managed Instance Groups
Max vCPUs 448 (u-24tb1.metal) 416 (M-series) 416 (m3-megamem-128)

AWS EC2

AWS EC2 Key Features

  • Largest selection of instance types (500+)
  • Nitro System for enhanced security and performance
  • Graviton processors (ARM-based, cost-effective)
  • Placement groups for low-latency networking
  • Instance Store (ephemeral) and EBS (persistent) storage
AWS EC2 instance architecture with Nitro System and Graviton processors
Figure 3: AWS EC2 features the Nitro System for enhanced security and Graviton ARM-based processors for cost-effective computing.

Launching EC2 Instances

# List available AMIs (Amazon Linux 2023)
aws ec2 describe-images \
    --owners amazon \
    --filters "Name=name,Values=al2023-ami-*-x86_64" \
    --query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' \
    --output text

# Launch a basic instance
aws ec2 run-instances \
    --image-id ami-0abcdef1234567890 \
    --instance-type t3.micro \
    --key-name my-key-pair \
    --security-group-ids sg-0123456789abcdef0 \
    --subnet-id subnet-0123456789abcdef0 \
    --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=my-instance}]'

# Launch with user data script
aws ec2 run-instances \
    --image-id ami-0abcdef1234567890 \
    --instance-type t3.small \
    --key-name my-key-pair \
    --user-data file://startup-script.sh \
    --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=web-server}]'

# Launch with IAM role
aws ec2 run-instances \
    --image-id ami-0abcdef1234567890 \
    --instance-type t3.medium \
    --iam-instance-profile Name=my-instance-profile \
    --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=app-server}]'

Managing EC2 Instances

# List all instances
aws ec2 describe-instances \
    --query 'Reservations[*].Instances[*].[InstanceId,State.Name,InstanceType,PublicIpAddress,Tags[?Key==`Name`].Value|[0]]' \
    --output table

# Get instance details
aws ec2 describe-instances --instance-ids i-0123456789abcdef0

# Start instance
aws ec2 start-instances --instance-ids i-0123456789abcdef0

# Stop instance
aws ec2 stop-instances --instance-ids i-0123456789abcdef0

# Reboot instance
aws ec2 reboot-instances --instance-ids i-0123456789abcdef0

# Terminate instance
aws ec2 terminate-instances --instance-ids i-0123456789abcdef0

# Modify instance type (must be stopped first)
aws ec2 stop-instances --instance-ids i-0123456789abcdef0
aws ec2 wait instance-stopped --instance-ids i-0123456789abcdef0
aws ec2 modify-instance-attribute \
    --instance-id i-0123456789abcdef0 \
    --instance-type "{\"Value\": \"t3.large\"}"
aws ec2 start-instances --instance-ids i-0123456789abcdef0

EC2 Key Pairs and Security Groups

# Create key pair
aws ec2 create-key-pair \
    --key-name my-key-pair \
    --query 'KeyMaterial' \
    --output text > my-key-pair.pem
chmod 400 my-key-pair.pem

# List key pairs
aws ec2 describe-key-pairs --output table

# Create security group
aws ec2 create-security-group \
    --group-name my-sg \
    --description "My security group" \
    --vpc-id vpc-0123456789abcdef0

# Add inbound rules
aws ec2 authorize-security-group-ingress \
    --group-id sg-0123456789abcdef0 \
    --protocol tcp \
    --port 22 \
    --cidr 0.0.0.0/0

aws ec2 authorize-security-group-ingress \
    --group-id sg-0123456789abcdef0 \
    --protocol tcp \
    --port 80 \
    --cidr 0.0.0.0/0

aws ec2 authorize-security-group-ingress \
    --group-id sg-0123456789abcdef0 \
    --protocol tcp \
    --port 443 \
    --cidr 0.0.0.0/0

# List security group rules
aws ec2 describe-security-groups --group-ids sg-0123456789abcdef0

EC2 Storage (EBS)

# Create EBS volume
aws ec2 create-volume \
    --availability-zone us-east-1a \
    --size 100 \
    --volume-type gp3 \
    --iops 3000 \
    --throughput 125 \
    --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=data-volume}]'

# Attach volume to instance
aws ec2 attach-volume \
    --volume-id vol-0123456789abcdef0 \
    --instance-id i-0123456789abcdef0 \
    --device /dev/sdf

# Detach volume
aws ec2 detach-volume --volume-id vol-0123456789abcdef0

# Create snapshot
aws ec2 create-snapshot \
    --volume-id vol-0123456789abcdef0 \
    --description "Daily backup" \
    --tag-specifications 'ResourceType=snapshot,Tags=[{Key=Name,Value=daily-backup}]'

# List volumes
aws ec2 describe-volumes \
    --query 'Volumes[*].[VolumeId,State,Size,VolumeType,Attachments[0].InstanceId]' \
    --output table

Azure Virtual Machines

Azure VMs Key Features

  • Hybrid cloud integration with Azure Arc
  • Confidential computing with secure enclaves
  • Azure Dedicated Host for compliance
  • Proximity placement groups
  • Ultra Disk storage for highest IOPS
Azure Virtual Machines with hybrid cloud integration via Azure Arc
Figure 4: Azure VMs offer hybrid cloud integration with Azure Arc and confidential computing with secure enclaves.

Azure VM Naming Convention & the D-Series Family

Azure VM sizes follow a structured naming pattern that can look confusing at first (e.g., Standard_D4s_v5), but once you understand the formula, you can instantly decode any Azure VM size:

Azure VM Naming Convention
==========================

    Standard_D4s_v5
    │        │││ ││
    │        │││ └┴─ Version (v3, v4, v5 = newer hardware generations)
    │        │││
    │        ││└─── Capability: s = Premium SSD support
    │        ││            a = AMD processor
    │        ││            d = local temp disk
    │        ││            l = low memory
    │        ││            p = ARM-based (Ampere)
    │        ││
    │        │└──── vCPU count (2, 4, 8, 16, 32, 48, 64, 96)
    │        │
    │        └───── Family letter:
    │                D = General Purpose (balanced CPU/memory)
    │                B = Burstable (variable workloads)
    │                F = Compute Optimized (high CPU)
    │                E = Memory Optimized (high memory)
    │                L = Storage Optimized (high disk throughput)
    │                N = GPU Accelerated (ML/rendering)
    │                M = Memory Intensive (SAP, large DBs)
    │
    └───────── Pricing tier (always "Standard" for regular VMs)
Quick Decode Examples:
  • Standard_D8s_v5 → General purpose, 8 vCPUs, Premium SSD capable, version 5 (Intel)
  • Standard_D4as_v5 → General purpose, 4 vCPUs, AMD processor, Premium SSD, version 5
  • Standard_D16ds_v5 → General purpose, 16 vCPUs, local temp disk, Premium SSD, version 5
  • Standard_D2ps_v5 → General purpose, 2 vCPUs, ARM (Ampere), Premium SSD, version 5
  • Standard_B2sBurstable, 2 vCPUs, Premium SSD (ideal for dev/test)

The D-Series: Azure's Most Popular VM Family

The D-series is Azure's general-purpose workhorse — the most widely used VM family for production workloads. It offers a balanced ratio of CPU to memory (typically 1 vCPU : 4 GB RAM) and is suitable for the majority of workloads including web servers, application servers, small-to-medium databases, and development environments.

D-Series VariantProcessorvCPU : MemoryBest ForExample Sizes
Dv5 / Dsv5 Intel Ice Lake (3rd Gen Xeon) 1 : 4 GB General production workloads, enterprise apps D2s_v5 (2 vCPU, 8 GB) to D96s_v5 (96 vCPU, 384 GB)
Dasv5 AMD EPYC (3rd Gen Milan) 1 : 4 GB Cost-effective alternative to Intel D-series (~10% cheaper) D2as_v5, D4as_v5, D8as_v5…D96as_v5
Ddsv5 Intel Ice Lake 1 : 4 GB Workloads needing fast local temp disk (caching, temp files) D2ds_v5 — includes local NVMe SSD storage
Dpsv5 Ampere Altra (ARM64) 1 : 4 GB ARM-native Linux workloads, web servers, microservices D2ps_v5, D4ps_v5…D64ps_v5
Dlsv5 Intel Ice Lake 1 : 2 GB (low memory) CPU-heavy workloads that don't need much RAM D2ls_v5 (2 vCPU, 4 GB) to D96ls_v5
Dv4 / Dsv4 (previous gen) Intel Cascade Lake (2nd Gen Xeon) 1 : 4 GB Still supported; v5 recommended for new deployments D2s_v4 through D64s_v4

How to Choose the Right D-Series Variant

Decision Guide Azure VMs

Follow this decision path to pick the right D-series VM for your workload:

  1. Do you need the lowest cost? → Choose Dasv5 (AMD). AMD variants are typically 5–15% cheaper than Intel equivalents with comparable performance.
  2. Is your workload ARM-compatible (Linux with no x86 dependencies)? → Choose Dpsv5 (Ampere ARM). Up to 20% better price-performance for web servers and containerized apps.
  3. Do you need fast local temp storage? → Choose Ddsv5 (includes local NVMe SSD). Great for caching layers, ETL pipelines, or apps that write to temp files.
  4. Is your app CPU-bound with low memory needs? → Choose Dlsv5 (low memory). Half the RAM at a lower price — ideal for compute-heavy batch jobs.
  5. Standard production workload? → Choose Dsv5 (Intel). The safe, well-rounded default for most apps.

Pro Tip: Always append s to your size name (e.g., D4s_v5 not D4_v5). The “s” enables Premium SSD support, which you almost always want for production.

Right-sizing Cost Optimization D-series
D-Series vs B-Series: The B-series (Burstable) is often confused with D-series. B-series VMs accumulate CPU credits during idle periods and "burst" to full CPU during spikes — similar to AWS T3 instances. They're ideal for dev/test, small websites, and microservices with intermittent traffic. Use D-series when you need consistent, predictable performance without credit mechanics.

Creating Azure VMs

# Create resource group
az group create --name myResourceGroup --location eastus

# List available VM sizes
az vm list-sizes --location eastus --output table

# List available images
az vm image list --output table
az vm image list --publisher Canonical --offer 0001-com-ubuntu-server-jammy --all --output table

# Create VM with defaults
az vm create \
    --resource-group myResourceGroup \
    --name myVM \
    --image Ubuntu2204 \
    --admin-username azureuser \
    --generate-ssh-keys

# Create VM with specific configuration
az vm create \
    --resource-group myResourceGroup \
    --name myVM \
    --image Ubuntu2204 \
    --size Standard_D2s_v3 \
    --admin-username azureuser \
    --ssh-key-values ~/.ssh/id_rsa.pub \
    --public-ip-sku Standard \
    --vnet-name myVNet \
    --subnet mySubnet \
    --nsg myNSG \
    --tags Environment=Dev Project=Demo

# Create VM with custom data (cloud-init)
az vm create \
    --resource-group myResourceGroup \
    --name webServer \
    --image Ubuntu2204 \
    --size Standard_B2s \
    --admin-username azureuser \
    --generate-ssh-keys \
    --custom-data cloud-init.yaml

Managing Azure VMs

# List all VMs
az vm list --output table

# List VMs with details
az vm list \
    --resource-group myResourceGroup \
    --show-details \
    --output table

# Get VM details
az vm show \
    --resource-group myResourceGroup \
    --name myVM

# Start VM
az vm start --resource-group myResourceGroup --name myVM

# Stop VM (deallocate - stops billing)
az vm deallocate --resource-group myResourceGroup --name myVM

# Stop VM (keep resources allocated)
az vm stop --resource-group myResourceGroup --name myVM

# Restart VM
az vm restart --resource-group myResourceGroup --name myVM

# Delete VM
az vm delete --resource-group myResourceGroup --name myVM --yes

# Resize VM
az vm resize \
    --resource-group myResourceGroup \
    --name myVM \
    --size Standard_D4s_v3

# List available sizes for resize
az vm list-vm-resize-options \
    --resource-group myResourceGroup \
    --name myVM \
    --output table

Azure VM Networking

# Create network security group
az network nsg create \
    --resource-group myResourceGroup \
    --name myNSG

# Add NSG rule for SSH
az network nsg rule create \
    --resource-group myResourceGroup \
    --nsg-name myNSG \
    --name AllowSSH \
    --protocol tcp \
    --priority 1000 \
    --destination-port-range 22 \
    --access allow

# Add NSG rule for HTTP/HTTPS
az network nsg rule create \
    --resource-group myResourceGroup \
    --nsg-name myNSG \
    --name AllowHTTP \
    --protocol tcp \
    --priority 1001 \
    --destination-port-range 80 443 \
    --access allow

# Get public IP
az vm list-ip-addresses \
    --resource-group myResourceGroup \
    --name myVM \
    --output table

# Open port on existing VM
az vm open-port \
    --resource-group myResourceGroup \
    --name myVM \
    --port 80 \
    --priority 1002

Azure VM Disks

# Create managed disk
az disk create \
    --resource-group myResourceGroup \
    --name myDataDisk \
    --size-gb 128 \
    --sku Premium_LRS

# Attach disk to VM
az vm disk attach \
    --resource-group myResourceGroup \
    --vm-name myVM \
    --name myDataDisk

# Detach disk
az vm disk detach \
    --resource-group myResourceGroup \
    --vm-name myVM \
    --name myDataDisk

# List disks
az disk list \
    --resource-group myResourceGroup \
    --output table

# Create snapshot
az snapshot create \
    --resource-group myResourceGroup \
    --name mySnapshot \
    --source myDataDisk

# Resize OS disk
az vm deallocate --resource-group myResourceGroup --name myVM
az disk update \
    --resource-group myResourceGroup \
    --name myVM_OsDisk \
    --size-gb 256
az vm start --resource-group myResourceGroup --name myVM

GCP Compute Engine

GCP Compute Engine Key Features

  • Custom machine types (configure exact vCPU/memory)
  • Live migration during maintenance
  • Sole-tenant nodes for compliance
  • Local SSD for high-performance storage
  • Per-second billing (minimum 1 minute)

GCP Machine Families & Types

Unlike Azure and AWS where you choose from a fixed catalogue of named sizes, Google Compute Engine uniquely lets you create custom machine types with any vCPU/memory combination. But GCP also provides predefined machine families optimized for specific workloads:

FamilySeriesProcessorvCPU : MemoryBest For
General Purpose E2 Intel / AMD (shared-core available) 1 : 4 GB (flexible) Cost-effective — dev/test, small web apps, microservices. GCP's equivalent of Azure B-series.
N2 Intel Cascade Lake / Ice Lake 1 : 4 GB Balanced production workloads. GCP's equivalent of Azure D-series (Dsv5).
N2D AMD EPYC Milan 1 : 4 GB Cost-effective AMD alternative. Equivalent to Azure Dasv5.
Compute Optimized C2 Intel Cascade Lake (3.1 GHz sustained) 1 : 4 GB Gaming, HPC, single-threaded apps, ad serving
C2D AMD EPYC Milan (3rd Gen) 1 : 4 GB High-core count compute, data analytics, scientific computing
Memory Optimized M2 Intel Cascade Lake 1 : 14–28 GB SAP HANA, large in-memory databases, real-time analytics
M3 Intel Ice Lake 1 : 16 GB Next-gen memory-intensive workloads, up to 30 TB RAM
Accelerator A2 / G2 Intel + NVIDIA A100 / L4 GPUs Varies ML training, inference, video transcoding, rendering
GCP's Unique Advantage — Custom Machine Types: If no predefined size fits, you can specify exact vCPU and memory. For example, --custom-cpu=6 --custom-memory=20GB creates a VM with 6 vCPUs and 20 GB RAM. You pay only for what you allocate. This flexibility doesn't exist on AWS or Azure (where you must pick from a fixed catalogue). Custom types work within any general-purpose family (N2, N2D, E2).

Cross-Provider Equivalents — Quick Reference

AWS Azure GCP

When migrating or comparing costs, use this mapping to find equivalent VM sizes across providers:

WorkloadAWS EC2Azure VMGCP Compute EngineApprox. Specs
Dev/test, burstablet3.mediumStandard_B2se2-medium2 vCPU, 4 GB
General productionm5.xlargeStandard_D4s_v5n2-standard-44 vCPU, 16 GB
General AMDm5a.xlargeStandard_D4as_v5n2d-standard-44 vCPU, 16 GB
Compute optimizedc5.2xlargeStandard_F8s_v2c2-standard-88 vCPU, 16–32 GB
Memory optimizedr5.2xlargeStandard_E8s_v5n2-highmem-88 vCPU, 64 GB
GPU (ML training)p4d.24xlargeStandard_NC24ads_A100_v4a2-highgpu-1gNVIDIA A100

Key insight: Azure D-series maps directly to AWS M5/M6i (Intel) or M5a/M6a (AMD), and to GCP N2 (Intel) or N2D (AMD). They all offer the same 1:4 vCPU-to-memory ratio for balanced production workloads.

Multi-cloud Migration Right-sizing
GCP Sustained Use Discounts (SUD): Unlike AWS and Azure which require upfront commitments (Reserved Instances) for discounts, GCP automatically applies sustained use discounts when you run instances for more than 25% of a month. At full month usage (730 hours), you receive up to 30% off the on-demand price — with zero commitment, no prepayment, and nothing to configure. This makes GCP uniquely beginner-friendly for cost optimization.

Creating GCP Instances

# List available machine types
gcloud compute machine-types list --filter="zone:us-central1-a" | head -20

# List available images
gcloud compute images list --filter="family:ubuntu"

# Create basic instance
gcloud compute instances create my-instance \
    --zone=us-central1-a \
    --machine-type=e2-medium \
    --image-family=ubuntu-2204-lts \
    --image-project=ubuntu-os-cloud

# Create instance with custom configuration
gcloud compute instances create web-server \
    --zone=us-central1-a \
    --machine-type=n2-standard-2 \
    --image-family=ubuntu-2204-lts \
    --image-project=ubuntu-os-cloud \
    --boot-disk-size=50GB \
    --boot-disk-type=pd-ssd \
    --tags=http-server,https-server \
    --metadata-from-file=startup-script=startup.sh

# Create custom machine type
gcloud compute instances create custom-vm \
    --zone=us-central1-a \
    --custom-cpu=4 \
    --custom-memory=8GB \
    --image-family=debian-12 \
    --image-project=debian-cloud

# Create with service account
gcloud compute instances create app-server \
    --zone=us-central1-a \
    --machine-type=e2-standard-2 \
    --service-account=my-sa@project.iam.gserviceaccount.com \
    --scopes=cloud-platform \
    --image-family=ubuntu-2204-lts \
    --image-project=ubuntu-os-cloud

Managing GCP Instances

# List instances
gcloud compute instances list

# List instances in specific zone
gcloud compute instances list --filter="zone:us-central1-a"

# Describe instance
gcloud compute instances describe my-instance --zone=us-central1-a

# Start instance
gcloud compute instances start my-instance --zone=us-central1-a

# Stop instance
gcloud compute instances stop my-instance --zone=us-central1-a

# Reset instance (hard restart)
gcloud compute instances reset my-instance --zone=us-central1-a

# Delete instance
gcloud compute instances delete my-instance --zone=us-central1-a

# Change machine type (requires stop)
gcloud compute instances stop my-instance --zone=us-central1-a
gcloud compute instances set-machine-type my-instance \
    --zone=us-central1-a \
    --machine-type=e2-standard-4
gcloud compute instances start my-instance --zone=us-central1-a

# SSH into instance
gcloud compute ssh my-instance --zone=us-central1-a

# SSH with specific user
gcloud compute ssh myuser@my-instance --zone=us-central1-a

GCP Firewall Rules

# Create firewall rule for SSH
gcloud compute firewall-rules create allow-ssh \
    --direction=INGRESS \
    --priority=1000 \
    --network=default \
    --action=ALLOW \
    --rules=tcp:22 \
    --source-ranges=0.0.0.0/0

# Create firewall rule for HTTP/HTTPS
gcloud compute firewall-rules create allow-http \
    --direction=INGRESS \
    --priority=1000 \
    --network=default \
    --action=ALLOW \
    --rules=tcp:80,tcp:443 \
    --target-tags=http-server,https-server \
    --source-ranges=0.0.0.0/0

# List firewall rules
gcloud compute firewall-rules list

# Delete firewall rule
gcloud compute firewall-rules delete allow-ssh

# Update firewall rule
gcloud compute firewall-rules update allow-http \
    --source-ranges=10.0.0.0/8,192.168.0.0/16

GCP Persistent Disks

# Create persistent disk
gcloud compute disks create my-data-disk \
    --zone=us-central1-a \
    --size=100GB \
    --type=pd-ssd

# Attach disk to instance
gcloud compute instances attach-disk my-instance \
    --zone=us-central1-a \
    --disk=my-data-disk

# Detach disk
gcloud compute instances detach-disk my-instance \
    --zone=us-central1-a \
    --disk=my-data-disk

# List disks
gcloud compute disks list

# Create snapshot
gcloud compute disks snapshot my-data-disk \
    --zone=us-central1-a \
    --snapshot-names=my-snapshot

# List snapshots
gcloud compute snapshots list

# Resize disk (online resize supported)
gcloud compute disks resize my-data-disk \
    --zone=us-central1-a \
    --size=200GB

Auto Scaling

Auto scaling automatically adjusts the number of instances based on demand, ensuring performance during traffic spikes while minimizing costs during low usage.

Auto scaling diagram showing instances adjusting based on traffic demand
Figure 5: Auto scaling automatically adjusts instance count based on demand — scaling out during traffic spikes and scaling in during low usage.

AWS Auto Scaling

# Create launch template
aws ec2 create-launch-template \
    --launch-template-name my-template \
    --version-description "v1" \
    --launch-template-data '{
        "ImageId": "ami-0abcdef1234567890",
        "InstanceType": "t3.micro",
        "KeyName": "my-key-pair",
        "SecurityGroupIds": ["sg-0123456789abcdef0"],
        "UserData": "IyEvYmluL2Jhc2gKZWNobyAiSGVsbG8gV29ybGQi"
    }'

# Create Auto Scaling group
aws autoscaling create-auto-scaling-group \
    --auto-scaling-group-name my-asg \
    --launch-template LaunchTemplateName=my-template,Version='$Latest' \
    --min-size 1 \
    --max-size 5 \
    --desired-capacity 2 \
    --vpc-zone-identifier "subnet-0123456789abcdef0,subnet-0fedcba9876543210" \
    --target-group-arns "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/my-tg/1234567890123456" \
    --health-check-type ELB \
    --health-check-grace-period 300

# Create scaling policy (target tracking)
aws autoscaling put-scaling-policy \
    --auto-scaling-group-name my-asg \
    --policy-name cpu-target-tracking \
    --policy-type TargetTrackingScaling \
    --target-tracking-configuration '{
        "PredefinedMetricSpecification": {
            "PredefinedMetricType": "ASGAverageCPUUtilization"
        },
        "TargetValue": 70.0
    }'

# Describe Auto Scaling group
aws autoscaling describe-auto-scaling-groups \
    --auto-scaling-group-names my-asg

# Update desired capacity
aws autoscaling set-desired-capacity \
    --auto-scaling-group-name my-asg \
    --desired-capacity 3

Azure VM Scale Sets

# Create VM Scale Set
az vmss create \
    --resource-group myResourceGroup \
    --name myScaleSet \
    --image Ubuntu2204 \
    --upgrade-policy-mode automatic \
    --admin-username azureuser \
    --generate-ssh-keys \
    --instance-count 2 \
    --vm-sku Standard_B2s \
    --lb-sku Standard

# Enable autoscale
az monitor autoscale create \
    --resource-group myResourceGroup \
    --resource myScaleSet \
    --resource-type Microsoft.Compute/virtualMachineScaleSets \
    --name autoscale-config \
    --min-count 1 \
    --max-count 10 \
    --count 2

# Add autoscale rule (scale out on CPU > 70%)
az monitor autoscale rule create \
    --resource-group myResourceGroup \
    --autoscale-name autoscale-config \
    --condition "Percentage CPU > 70 avg 5m" \
    --scale out 1

# Add autoscale rule (scale in on CPU < 30%)
az monitor autoscale rule create \
    --resource-group myResourceGroup \
    --autoscale-name autoscale-config \
    --condition "Percentage CPU < 30 avg 5m" \
    --scale in 1

# List scale set instances
az vmss list-instances \
    --resource-group myResourceGroup \
    --name myScaleSet \
    --output table

# Scale manually
az vmss scale \
    --resource-group myResourceGroup \
    --name myScaleSet \
    --new-capacity 5

GCP Managed Instance Groups

# Create instance template
gcloud compute instance-templates create my-template \
    --machine-type=e2-medium \
    --image-family=ubuntu-2204-lts \
    --image-project=ubuntu-os-cloud \
    --boot-disk-size=20GB \
    --tags=http-server \
    --metadata-from-file=startup-script=startup.sh

# Create managed instance group
gcloud compute instance-groups managed create my-mig \
    --zone=us-central1-a \
    --template=my-template \
    --size=2

# Enable autoscaling
gcloud compute instance-groups managed set-autoscaling my-mig \
    --zone=us-central1-a \
    --min-num-replicas=1 \
    --max-num-replicas=10 \
    --target-cpu-utilization=0.7 \
    --cool-down-period=60

# List instances in group
gcloud compute instance-groups managed list-instances my-mig \
    --zone=us-central1-a

# Resize group manually
gcloud compute instance-groups managed resize my-mig \
    --zone=us-central1-a \
    --size=5

# Update template (rolling update)
gcloud compute instance-groups managed rolling-action start-update my-mig \
    --zone=us-central1-a \
    --version=template=my-template-v2 \
    --max-surge=1 \
    --max-unavailable=0

Pricing Models

Model AWS Azure GCP Savings
On-Demand On-Demand Pay-as-you-go On-Demand 0% (baseline)
Spot/Preemptible Spot Instances Spot VMs Spot VMs 60-90%
Reserved (1 year) Reserved Instances Reserved VMs Committed Use 30-40%
Reserved (3 year) Reserved Instances Reserved VMs Committed Use 50-60%
Sustained Use N/A N/A Automatic Up to 30%

Using Spot/Preemptible Instances

# AWS Spot Instance
aws ec2 run-instances \
    --image-id ami-0abcdef1234567890 \
    --instance-type t3.large \
    --instance-market-options 'MarketType=spot,SpotOptions={MaxPrice=0.05,SpotInstanceType=persistent}'

# Azure Spot VM
az vm create \
    --resource-group myResourceGroup \
    --name mySpotVM \
    --image Ubuntu2204 \
    --size Standard_D2s_v3 \
    --priority Spot \
    --eviction-policy Deallocate \
    --max-price 0.05

# GCP Spot VM
gcloud compute instances create spot-instance \
    --zone=us-central1-a \
    --machine-type=n2-standard-2 \
    --provisioning-model=SPOT \
    --instance-termination-action=STOP \
    --image-family=ubuntu-2204-lts \
    --image-project=ubuntu-os-cloud

Best Practices

Security Best Practices:
  • Use IAM roles instead of access keys on instances
  • Keep security groups/NSGs restrictive (principle of least privilege)
  • Encrypt EBS/managed disks at rest
  • Use private subnets for backend services
  • Enable VPC flow logs / NSG flow logs
  • Patch instances regularly (use Systems Manager, Update Management)

Cost Optimization

  1. Right-size instances - Monitor utilization and adjust
  2. Use auto scaling - Scale down during low demand
  3. Leverage spot instances - For fault-tolerant workloads
  4. Reserved instances - For predictable, steady-state workloads
  5. Schedule start/stop - Turn off dev/test instances after hours
  6. Use savings plans - Flexible commitments across instance families

Scheduled Start/Stop

# AWS: Use EventBridge + Lambda or Instance Scheduler
# Simple example with AWS CLI (for automation scripts)
aws ec2 stop-instances --instance-ids i-0123456789abcdef0
aws ec2 start-instances --instance-ids i-0123456789abcdef0

# Azure: Auto-shutdown configuration
az vm auto-shutdown \
    --resource-group myResourceGroup \
    --name myVM \
    --time 1900

# GCP: Use instance schedules
gcloud compute resource-policies create instance-schedule my-schedule \
    --region=us-central1 \
    --vm-start-schedule="0 9 * * 1-5" \
    --vm-stop-schedule="0 18 * * 1-5" \
    --timezone="America/New_York"

gcloud compute instances add-resource-policies my-instance \
    --zone=us-central1-a \
    --resource-policies=my-schedule

Conclusion

Cloud compute services provide the flexibility to run any workload at any scale. While AWS EC2, Azure VMs, and GCP Compute Engine share core concepts, each offers unique features:

Choose AWS EC2 If... Choose Azure VMs If... Choose GCP Compute If...
You need widest instance selection You have Microsoft/Windows workloads You want custom machine types
You want ARM-based Graviton You need hybrid cloud with Azure Arc You value automatic sustained use discounts
You need mature ecosystem You require confidential computing You want live migration during maintenance
Technology