Home DevOps Microsoft Azure — Virtual Machines
Intermediate 8 min · July 12, 2026

Microsoft Azure — Virtual Machines

Azure VMs, VM sizes, availability sets, availability zones, disks, and provisioning..

N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Written from production experience, not tutorials.

Follow
Verified
production tested
July 19, 2026
last updated
2,466
articles · all by Naren
Before you start⏱ 25 min
  • Azure subscription with Contributor access, Azure CLI 2.50+ installed, PowerShell 7+ with Az module 10.0+, basic knowledge of VNet/subnet concepts, familiarity with JSON/YAML, and a GitHub account for IaC version control.
✦ Definition~90s read
What is Virtual Machines?

Microsoft Azure — Virtual Machines is a core Azure service that handles virtual machines in the Microsoft cloud ecosystem.

Virtual Machines is like having a specialized tool that handles virtual machines in the Microsoft cloud — you manage the configuration, Azure handles the infrastructure.
Plain-English First

Virtual Machines is like having a specialized tool that handles virtual machines in the Microsoft cloud — you manage the configuration, Azure handles the infrastructure.

Azure is Microsoft's cloud computing platform offering over 200 services. This article covers virtual machines with production-ready configurations, best practices, and hands-on examples.

Azure VMs: The Foundation of IaaS

Azure Virtual Machines are the bread and butter of Infrastructure as a Service (IaaS) on Microsoft's cloud. They give you full control over the operating system, installed software, and networking. Unlike PaaS services, VMs require you to manage patching, scaling, and high availability yourself. This is both a blessing and a curse: you get flexibility, but you also inherit operational overhead. In production, the most common mistake is treating VMs like on-premises servers—spinning them up, installing everything manually, and hoping they never fail. That approach leads to configuration drift, security gaps, and painful recovery. Instead, treat VMs as cattle, not pets. Use infrastructure as code (IaC) to define every aspect: size, disk, network, and extensions. Start with a clear naming convention and tagging strategy. For example, use env:prod, app:payment, role:web to filter and manage resources at scale. Without tags, you'll drown in a sea of unnamed VMs.

create-vm.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
# Create a production VM with tags and managed disk
az vm create \
  --resource-group prod-rg \
  --name prod-web-001 \
  --image UbuntuLTS \
  --size Standard_D2s_v3 \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_rsa.pub \
  --storage-sku Premium_LRS \
  --os-disk-size-gb 128 \
  --tags env=prod app=web role=app
Output
{
"fqdns": "",
"id": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/prod-web-001",
"location": "eastus",
"macAddress": "00-0D-3A-...",
"powerState": "VM running",
"privateIpAddress": "10.0.1.4",
"publicIpAddress": "52.168.1.100",
"resourceGroup": "prod-rg"
}
⚠ Don't Skip Tags
Without tags, you can't track costs, enforce policies, or automate lifecycle management. Tag every resource from day one.
📊 Production Insight
We once had a customer who forgot to tag VMs and ended up with 200 orphaned instances costing $15k/month. Tags saved them after a cleanup script.
🎯 Key Takeaway
Azure VMs give full control but demand strict IaC and tagging to avoid operational chaos.
azure-virtual-machines THECODEFORGE.IO Azure VM Provisioning Workflow Step-by-step from image selection to deployment Choose VM Image Select OS or custom image from Azure Marketplace Select VM Size Pick series like Dv3, Ev3 based on workload Configure Networking Define VNet, subnet, and NSG rules Attach Storage Add managed disks with caching and backup Set High Availability Choose availability set or zone Deploy and Monitor Enable Azure Monitor and diagnostics ⚠ Skipping NSG rules can expose VMs to threats Always restrict inbound traffic to least privilege THECODEFORGE.IO
thecodeforge.io
Azure Virtual Machines

Choosing the Right VM Size and Series

Azure offers dozens of VM series: general-purpose (D-series), compute-optimized (F-series), memory-optimized (E-series), and more. Picking the wrong size leads to either overspending or performance bottlenecks. For production, never use the B-series burstable VMs for steady-state workloads—they rely on CPU credits and will throttle under sustained load. Instead, start with D-series for most web apps and APIs. Use E-series for in-memory caches or databases. For GPU workloads, NC or ND series. Always benchmark with your actual workload. A common trap is choosing a VM with too little memory, causing the OS to swap and kill performance. Use Azure Monitor to track memory pressure. Also consider the new generation: Dv5 and Ev5 offer better price-performance than older Dv3. For disk, always use Premium SSD for OS disks in production—Standard HDD is only for dev/test. For data disks, consider Ultra Disk for high IOPS workloads like databases.

Get-VMSizes.ps1POWERSHELL
1
2
# List available VM sizes in a region with vCPU and memory
Get-AzVMSize -Location eastus | Where-Object {$_.Name -like "Standard_D*"} | Select-Object Name, NumberOfCores, MemoryInMB | Format-Table -AutoSize
Output
Name NumberOfCores MemoryInMB
---- ------------- ----------
Standard_D2s_v3 2 8192
Standard_D4s_v3 4 16384
Standard_D8s_v3 8 32768
Standard_D16s_v3 16 65536
Standard_D32s_v3 32 131072
💡Use Reserved Instances for Steady Load
If your VM runs 24/7, buy Reserved Instances (1 or 3 years) to save up to 72% compared to pay-as-you-go.
📊 Production Insight
A client used B2s for a production API. Under peak load, CPU credits exhausted, requests timed out, and they lost revenue. Switched to D2s_v3 and solved it.
🎯 Key Takeaway
Match VM series to workload type; avoid burstable for production; benchmark before committing.

Networking: VNet, Subnets, and NSGs Done Right

Every Azure VM lives inside a Virtual Network (VNet). You must plan your IP address space carefully—don't use /16 for everything. Use /24 subnets per tier: web, app, data. Network Security Groups (NSGs) are your first line of defense. Default-deny inbound, allow only necessary ports. For production, never open SSH (22) or RDP (3389) to the internet. Use Azure Bastion or a jumpbox. Also, enable NSG flow logs to detect anomalies. Another common mistake: placing all VMs in the same subnet. If one VM is compromised, lateral movement is trivial. Use Application Security Groups (ASGs) to group VMs by role and define NSG rules based on ASGs, not IPs. This decouples security from IP addresses. For high availability, deploy VMs in an Availability Set or Availability Zone. Availability Sets protect against rack failures; Zones protect against datacenter failures. For critical workloads, use Zones.

create-vnet-nsg.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash
# Create VNet with subnets and NSG
az network vnet create \
  --resource-group prod-rg \
  --name prod-vnet \
  --address-prefix 10.0.0.0/16 \
  --subnet-name web-subnet \
  --subnet-prefix 10.0.1.0/24

az network nsg create \
  --resource-group prod-rg \
  --name web-nsg

az network nsg rule create \
  --resource-group prod-rg \
  --nsg-name web-nsg \
  --name AllowHTTPS \
  --protocol tcp \
  --priority 100 \
  --destination-port-ranges 443 \
  --access allow \
  --direction inbound \
  --source-address-prefixes Internet \
  --destination-address-prefixes VirtualNetwork
Output
{
"newNSG": {
"defaultSecurityRules": [...],
"id": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.Network/networkSecurityGroups/web-nsg",
"location": "eastus",
"name": "web-nsg",
"securityRules": [
{
"access": "Allow",
"destinationAddressPrefix": "VirtualNetwork",
"destinationPortRange": "443",
"direction": "Inbound",
"name": "AllowHTTPS",
"priority": 100,
"protocol": "Tcp",
"sourceAddressPrefix": "Internet"
}
]
}
}
⚠ Never Expose Management Ports
SSH/RDP open to the internet is the #1 cause of VM compromise. Use Azure Bastion or a VPN.
📊 Production Insight
A startup had SSH open on all VMs. A brute-force attack succeeded, and the attacker mined cryptocurrency for a week before detection. Cost: $10k in compute and data exfiltration.
🎯 Key Takeaway
Segment VNets by tier, use NSGs with ASGs, and never expose management ports.
azure-virtual-machines THECODEFORGE.IO Azure VM Architecture Stack Layered view of IaaS components from compute to monitoring Compute Layer VM Instances | Scale Sets | Availability Sets/Zones Networking Layer Virtual Network | Subnets | NSGs Storage Layer Managed Disks | Disk Caching | Backup Vault Configuration Layer Extensions | Desired State Config | Custom Scripts Monitoring Layer Azure Monitor | Log Analytics | Diagnostics THECODEFORGE.IO
thecodeforge.io
Azure Virtual Machines

Storage: Managed Disks, Caching, and Backup

Azure Managed Disks are the default and should always be used over unmanaged disks (storage accounts). They offer better reliability, availability, and integration with availability sets. For OS disks, Premium SSD is the minimum for production. For data disks, choose based on IOPS needs: Standard SSD for general purpose, Premium SSD for high performance, Ultra Disk for extreme latency-sensitive workloads. Disk caching can significantly improve read performance: set OS disk caching to ReadWrite, data disks to ReadOnly for read-heavy workloads. But be careful—write-heavy databases should disable caching on data disks to avoid data corruption. Always enable Azure Backup for VMs. It provides application-consistent backups for Windows and file-consistent for Linux. Set a retention policy that meets your RPO/RTO. For critical data, also use Azure Site Recovery for cross-region replication. A common mistake is forgetting to back up data disks attached to a VM—backup only covers the VM by default, but you can include data disks.

Configure-Backup.ps1POWERSHELL
1
2
3
4
5
6
7
8
9
# Enable Azure Backup for a VM
$vault = Get-AzRecoveryServicesVault -ResourceGroupName prod-rg -Name prod-vault
Set-AzRecoveryServicesVaultContext -Vault $vault

$policy = Get-AzRecoveryServicesBackupProtectionPolicy -Name "DailyPolicy"
Enable-AzRecoveryServicesBackupProtection `
  -ResourceGroupName prod-rg `
  -Name prod-web-001 `
  -Policy $policy
Output
WorkloadName Operation Status StartTime EndTime
-------------- ---------------- ------------- ------------------- -------------------
prod-web-001 ConfigureBackup Completed 7/12/2026 10:00:00 AM 7/12/2026 10:01:23 AM
🔥Disk Caching Pitfall
For SQL Server or other databases, set host caching to None on data disks to prevent write corruption.
📊 Production Insight
A team lost a week of data because they only backed up the OS disk, not the attached data disk with the database. Always include all disks in backup policy.
🎯 Key Takeaway
Use managed disks, choose caching wisely, and always enable backup with proper retention.

High Availability: Availability Sets vs Zones

For production, you need redundancy. Azure offers two options: Availability Sets and Availability Zones. Availability Sets distribute VMs across up to 3 fault domains (racks) and update domains (maintenance windows). They protect against hardware failures and planned maintenance within a datacenter. Availability Zones place VMs in physically separate datacenters within a region, protecting against entire datacenter failures. For most production workloads, use Availability Zones—they offer higher SLA (99.99% vs 99.95% for multi-VM in set). However, Zones incur inter-zone network latency (typically <2ms). For stateful applications like databases, you need to handle data replication yourself (e.g., SQL Always On, MongoDB replica sets). A common mistake is deploying VMs in the same zone thinking they're in different zones—always check the zone property. Also, load balancers must be zone-redundant or zone-specific. Use Azure Standard Load Balancer with zone-redundant frontend.

create-vm-zones.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
# Create VMs in different availability zones
for zone in 1 2 3; do
  az vm create \
    --resource-group prod-rg \
    --name prod-web-00$zone \
    --image UbuntuLTS \
    --size Standard_D2s_v3 \
    --zone $zone \
    --vnet-name prod-vnet \
    --subnet web-subnet \
    --public-ip-address "" \
    --admin-username azureuser \
    --ssh-key-values ~/.ssh/id_rsa.pub
done
Output
{
"id": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/prod-web-001",
"zones": ["1"],
"powerState": "VM running"
}
{
"id": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/prod-web-002",
"zones": ["2"],
"powerState": "VM running"
}
{
"id": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/prod-web-003",
"zones": ["3"],
"powerState": "VM running"
}
💡Zone-Aware Load Balancer
Use Standard Load Balancer with zone-redundant frontend IP to distribute traffic across zones.
📊 Production Insight
A customer used Availability Set but a cooling failure took down an entire datacenter rack, affecting 2 of 3 VMs. They switched to Zones and never had a full outage again.
🎯 Key Takeaway
Prefer Availability Zones for higher SLA; plan for data replication across zones.

Scaling: Scale Sets and Autoscale

For stateless workloads, use Virtual Machine Scale Sets (VMSS) with autoscale. VMSS allows you to manage a group of identical VMs that can scale in/out based on metrics like CPU, memory, or custom metrics. Always use a custom image or VMSS with the latest OS image to ensure consistency. For production, configure a minimum instance count (e.g., 2) and maximum (e.g., 10). Set scale-out rules to be aggressive (e.g., CPU > 75% for 5 minutes) and scale-in rules to be conservative (e.g., CPU < 30% for 15 minutes) to avoid thrashing. Use Azure Monitor autoscale with multiple profiles for different times of day. A common mistake is not setting a scale-in policy—by default, the newest VM is removed, which may cause connection draining issues. Use the 'NewestVM' or 'OldestVM' policy based on your needs. Also, integrate with Azure Load Balancer health probes to ensure only healthy instances receive traffic.

Create-ScaleSet.ps1POWERSHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Create a VMSS with autoscale
$vmssConfig = New-AzVmssConfig `
  -Location eastus `
  -SkuName Standard_D2s_v3 `
  -InstanceCount 2 `
  -UpgradePolicyMode Automatic

$vmss = New-AzVmss `
  -ResourceGroupName prod-rg `
  -Name web-scale-set `
  -VirtualMachineScaleSet $vmssConfig

# Add autoscale rule
$rule = New-AzAutoscaleRule `
  -MetricName "Percentage CPU" `
  -MetricResourceId $vmss.Id `
  -Operator GreaterThan `
  -MetricStatistic Average `
  -Threshold 75 `
  -TimeGrain 00:01:00 `
  -TimeWindow 00:05:00 `
  -ScaleActionCooldown 00:05:00 `
  -ScaleActionDirection Increase `
  -ScaleActionValue 1

Add-AzAutoscaleSetting `
  -ResourceGroupName prod-rg `
  -Name web-autoscale `
  -Location eastus `
  -AutoscaleProfiles (New-AzAutoscaleProfile -Name default -DefaultCapacity 2 -MaximumCapacity 10 -MinimumCapacity 2 -Rules $rule)
Output
{
"id": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.Insights/autoscalesettings/web-autoscale",
"name": "web-autoscale",
"profiles": [
{
"capacity": {
"default": "2",
"maximum": "10",
"minimum": "2"
},
"name": "default",
"rules": [...]
}
]
}
⚠ Avoid Scale-In Thrashing
Set scale-in cooldown longer than scale-out. Use a lower threshold for scale-in and a longer evaluation window.
📊 Production Insight
A company set scale-in threshold same as scale-out. During a flash sale, VMs kept scaling in and out, causing 503 errors. They fixed it by making scale-in more conservative.
🎯 Key Takeaway
Use VMSS with autoscale for stateless workloads; configure scale-in policies to avoid thrashing.

Configuration Management with Extensions and Desired State

After provisioning a VM, you need to configure it—install software, apply settings, join domains. Azure VM Extensions automate this. Common extensions: Custom Script Extension (run scripts), DSC (Desired State Configuration), Chef, Puppet. For production, use Custom Script Extension to bootstrap configuration, but avoid embedding secrets in scripts. Instead, use Azure Key Vault to pull secrets at runtime. For Windows, DSC is powerful for ensuring consistent state. For Linux, use cloud-init for initial setup and then configuration management tools like Ansible or Chef. A common mistake is relying on manual SSH/RDP to configure VMs—this is error-prone and not repeatable. Always use extensions or configuration management tools. Also, extensions run as part of VM provisioning; if they fail, the VM may be in an inconsistent state. Monitor extension status and set up alerts. For scale sets, use the extensions profile to apply to all instances.

install-nginx-extension.shBASH
1
2
3
4
5
6
7
8
#!/bin/bash
# Install Nginx via Custom Script Extension
az vm extension set \
  --resource-group prod-rg \
  --vm-name prod-web-001 \
  --name customScript \
  --publisher Microsoft.Azure.Extensions \
  --settings '{"commandToExecute": "apt-get update && apt-get install -y nginx"}'
Output
{
"autoUpgradeMinorVersion": true,
"forceUpdateTag": null,
"id": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/prod-web-001/extensions/customScript",
"instanceView": null,
"location": "eastus",
"name": "customScript",
"protectedSettings": null,
"provisioningState": "Succeeded",
"publisher": "Microsoft.Azure.Extensions",
"resourceGroup": "prod-rg",
"settings": {
"commandToExecute": "apt-get update && apt-get install -y nginx"
},
"tags": null,
"type": "Microsoft.Azure.Extensions/customScript",
"typeHandlerVersion": "2.1",
"vmId": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/prod-web-001"
}
🔥Secrets in Extensions
Never hardcode passwords or keys in extension settings. Use protectedSettings with references to Key Vault.
📊 Production Insight
A team hardcoded a database password in a Custom Script Extension. When they rotated the password, they had to update every VM manually. Use Key Vault to avoid this.
🎯 Key Takeaway
Automate VM configuration with extensions; avoid manual setup; use Key Vault for secrets.

Monitoring and Diagnostics: Azure Monitor and Log Analytics

You can't manage what you don't measure. Enable Azure Monitor for every VM. At minimum, collect metrics like CPU, memory, disk IOPS, and network. Use Azure Monitor alerts to notify on high CPU, disk space, or VM unavailability. For deeper analysis, install the Log Analytics agent (or Azure Monitor agent) to collect logs and performance counters. Create a Log Analytics workspace and configure data sources. For production, set up alerts for common failure modes: disk space < 10%, memory > 90%, CPU > 80% for extended periods. Also enable boot diagnostics to capture serial console output—invaluable for troubleshooting boot failures. A common mistake is not setting up alerts for VM heartbeat—if a VM stops responding, you want to know immediately. Use VM Insights (previously Service Map) to visualize dependencies between VMs and processes. This helps during incident response.

Enable-Monitoring.ps1POWERSHELL
1
2
3
4
5
6
7
8
9
10
11
# Enable Azure Monitor for VM
$vm = Get-AzVM -ResourceGroupName prod-rg -Name prod-web-001

# Enable boot diagnostics
Set-AzVMBootDiagnostic -VM $vm -Enable -ResourceGroupName prod-rg -StorageAccountName proddiag

# Install Log Analytics agent
Set-AzVMExtension -ResourceGroupName prod-rg -VMName prod-web-001 -Name "OmsAgentForLinux" `
  -Publisher "Microsoft.EnterpriseCloud.Monitoring" -ExtensionType "OmsAgentForLinux" `
  -TypeHandlerVersion "1.0" -Settings @{workspaceId = "workspace-id"} `
  -ProtectedSettings @{workspaceKey = "workspace-key"}
Output
{
"provisioningState": "Succeeded",
"id": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/prod-web-001/extensions/OmsAgentForLinux",
"name": "OmsAgentForLinux",
"type": "Microsoft.Compute/virtualMachines/extensions",
"location": "eastus"
}
💡Set Up VM Heartbeat Alert
Create a metric alert on 'Heartbeat' from Log Analytics. If no heartbeat for 5 minutes, trigger an action group.
📊 Production Insight
A production VM ran out of disk space silently because no alert was configured. The application crashed, and it took 2 hours to detect. Now they alert on disk < 10%.
🎯 Key Takeaway
Enable Azure Monitor, boot diagnostics, and Log Analytics; set alerts for key metrics.

Security: Identity, Encryption, and Updates

Security for Azure VMs starts with identity. Use managed identities for Azure resources instead of storing credentials in VMs. This allows VMs to authenticate to Azure services without secrets. For OS-level access, use Azure AD authentication for Windows VMs (SSH key for Linux). Enable Azure Disk Encryption (ADE) for OS and data disks using Azure Key Vault. ADE uses BitLocker for Windows and DM-Crypt for Linux. For production, encrypt all disks. Also, enable just-in-time (JIT) VM access from Microsoft Defender for Cloud to reduce exposure of management ports. For patching, use Azure Update Management to schedule updates and get compliance reports. A common mistake is not applying security updates promptly—use automatic VM guest patching for Windows (available in preview) or schedule maintenance windows. Also, restrict network traffic with NSGs and use Azure Firewall for egress filtering. Finally, enable Azure Defender for Servers for threat detection.

enable-disk-encryption.shBASH
1
2
3
4
5
6
7
8
#!/bin/bash
# Enable Azure Disk Encryption
az vm encryption enable \
  --resource-group prod-rg \
  --name prod-web-001 \
  --disk-encryption-keyvault prod-keyvault \
  --key-encryption-key mykey \
  --volume-type all
Output
{
"status": "Encryption succeeded",
"encryptionSettings": [
{
"diskEncryptionKey": {
"secretUrl": "https://prod-keyvault.vault.azure.net/secrets/...",
"sourceVault": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.KeyVault/vaults/prod-keyvault"
},
"enabled": true
}
]
}
⚠ Key Vault Access
Ensure the VM has managed identity with Get and WrapKey permissions on Key Vault for encryption to work.
📊 Production Insight
A company suffered a data breach when an unencrypted disk was stolen from a decommissioned VM. Now they enforce encryption on all disks via Azure Policy.
🎯 Key Takeaway
Use managed identities, encrypt disks, enable JIT access, and automate patching.

Cost Management and Right-Sizing

Azure VMs can be expensive if not managed. Start with right-sizing: use Azure Advisor recommendations to identify underutilized VMs (CPU < 5% and memory < 20% for 7 days). Downsize or shut them down during off-hours. Use Azure Cost Management + Billing to set budgets and alerts. For production VMs that run 24/7, buy Reserved Instances or use Azure Savings Plan for compute. For dev/test, use Azure Dev/Test pricing or spot VMs (if interruptible). Another cost-saving technique: use Azure Hybrid Benefit if you have Windows Server or SQL Server licenses with Software Assurance. Also, consider using Azure Dedicated Hosts only if you need physical isolation—they're expensive. A common mistake is leaving VMs running when not needed. Use auto-shutdown for dev VMs. For production, use autoscale to scale in during low traffic. Finally, monitor egress costs—data transfer out of Azure can be significant.

Get-CostRecommendations.ps1POWERSHELL
1
2
# Get Azure Advisor cost recommendations
Get-AzAdvisorRecommendation -Category Cost | Where-Object {$_.Impact -eq "High"} | Select-Object ResourceName, ShortDescription, ImpactedField
Output
ResourceName ShortDescription ImpactedField
------------- ---------------- -------------
prod-web-001 Underutilized virtual machine (CPU 2%, memory 15%) Microsoft.Compute/virtualMachines
prod-db-001 Reserved Instance purchase recommended Microsoft.Compute/virtualMachines
💡Use Azure Hybrid Benefit
If you have on-prem Windows Server licenses with SA, apply Azure Hybrid Benefit to save up to 40% on VM costs.
📊 Production Insight
A client had 50 VMs running 24/7 for a batch job that ran 2 hours a day. They switched to spot VMs and saved 80% on compute costs.
🎯 Key Takeaway
Right-size VMs, use reserved instances for steady workloads, and shut down idle VMs.

Disaster Recovery: Backup and Site Recovery

Disaster recovery is not optional. Azure Backup provides simple, automated backups for VMs. Configure daily backups with retention up to 99 years. For cross-region recovery, use Azure Site Recovery (ASR) to replicate VMs to a secondary region. ASR provides continuous replication with RPO of seconds. For production, test your recovery plan regularly—at least quarterly. A common mistake is not testing failover. When a real disaster hits, you'll discover missing dependencies, incorrect network configurations, or insufficient capacity. Use ASR's test failover feature to validate without impacting production. Also, ensure your backup vault and ASR vault are in different regions. For critical databases, consider application-level replication (e.g., SQL Always On) in addition to VM-level backup. Finally, document your RPO and RTO and ensure your solution meets them.

Configure-ASR.ps1POWERSHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Configure Azure Site Recovery for a VM
$vault = Get-AzRecoveryServicesVault -ResourceGroupName prod-rg -Name prod-asr-vault
Set-AzRecoveryServicesVaultContext -Vault $vault

$policy = Get-AzRecoveryServicesAsrPolicy -Name "24-hour-retention"
$protectionContainer = Get-AzRecoveryServicesAsrProtectionContainer -Fabric (Get-AzRecoveryServicesAsrFabric)

$vm = Get-AzVM -ResourceGroupName prod-rg -Name prod-web-001
$asrVM = New-AzRecoveryServicesAsrProtectableItem -VM $vm -ProtectionContainer $protectionContainer

Enable-AzRecoveryServicesAsrReplication `
  -ProtectableItem $asrVM `
  -Policy $policy `
  -RecoveryResourceGroupName prod-dr-rg `
  -RecoveryCloudServiceName "" `
  -RecoveryAzureNetworkName prod-dr-vnet
Output
{
"Job": {
"ActivityId": "...",
"AllowedActions": [],
"CustomDetails": null,
"EndTime": null,
"Errors": [],
"FriendlyName": "Enable replication",
"Id": "/...",
"StartTime": "2026-07-12T10:00:00Z",
"State": "InProgress",
"StateDescription": "Completed",
"TargetObjectId": "...",
"TargetObjectName": "prod-web-001",
"Tasks": []
}
}
⚠ Test Failover Regularly
Don't wait for a disaster to test your recovery plan. Run test failover every quarter to ensure it works.
📊 Production Insight
A company's primary region went down due to a natural disaster. They had ASR configured but never tested failover. When they tried, it failed because the target region had insufficient quota. Always test.
🎯 Key Takeaway
Use Azure Backup for daily backups and ASR for cross-region DR; test failover regularly.

Automation and Infrastructure as Code

Manual VM management is a recipe for disaster. Use Infrastructure as Code (IaC) with ARM templates, Bicep, or Terraform. Define everything: resource group, VNet, subnets, NSGs, VMs, disks, extensions, and monitoring. Store templates in Git and use CI/CD pipelines (Azure DevOps, GitHub Actions) to deploy. For production, use deployment stacks to manage resource lifecycle. A common mistake is using the Azure Portal to make one-off changes—this creates configuration drift. Enforce that all changes go through IaC. Use Azure Policy to audit and enforce compliance (e.g., require tags, enforce disk encryption). For secrets, use Azure Key Vault and reference them in templates. Also, use Azure Blueprints to package policies, RBAC, and resource templates for consistent environments. Finally, automate VM shutdown/startup schedules using Azure Automation or Logic Apps to save costs.

vm.bicepBICEP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
param location string = resourceGroup().location
param vmName string = 'prod-web-001'
param adminUsername string

resource vnet 'Microsoft.Network/virtualNetworks@2021-02-01' existing = {
  name: 'prod-vnet'
}

resource nic 'Microsoft.Network/networkInterfaces@2021-02-01' = {
  name: '${vmName}-nic'
  location: location
  properties: {
    ipConfigurations: [
      {
        name: 'ipconfig1'
        properties: {
          subnet: {
            id: '${vnet.id}/subnets/web-subnet'
          }
        }
      }
    ]
  }
}

resource vm 'Microsoft.Compute/virtualMachines@2021-03-01' = {
  name: vmName
  location: location
  properties: {
    hardwareProfile: {
      vmSize: 'Standard_D2s_v3'
    }
    osProfile: {
      computerName: vmName
      adminUsername: adminUsername
      linuxConfiguration: {
        disablePasswordAuthentication: true
        ssh: {
          publicKeys: [
            {
              path: '/home/${adminUsername}/.ssh/authorized_keys'
              keyData: 'ssh-rsa AAAAB3NzaC1yc2E...'
            }
          ]
        }
      }
    }
    storageProfile: {
      imageReference: {
        publisher: 'Canonical'
        offer: 'UbuntuServer'
        sku: '18.04-LTS'
        version: 'latest'
      }
      osDisk: {
        createOption: 'FromImage'
        managedDisk: {
          storageAccountType: 'Premium_LRS'
        }
      }
    }
    networkProfile: {
      networkInterfaces: [
        {
          id: nic.id
        }
      ]
    }
  }
}
Output
Deployment succeeded. VM created with specified configuration.
🔥Avoid Portal Changes
Every manual change in the portal creates drift. Use IaC exclusively for production environments.
📊 Production Insight
A team manually resized a VM in the portal. Later, a Terraform deployment reverted it to the old size, causing an outage. Always update IaC first.
🎯 Key Takeaway
Use IaC (Bicep/Terraform) for all resources; enforce via CI/CD and Azure Policy.

VM Migration and Modernization with Azure Migrate

Migrating on-premises workloads to Azure VMs is one of the most common scenarios. Azure Migrate provides a centralized hub for discovery, assessment, and migration. Use Azure Migrate: Discovery and assessment to inventory your on-premises VMs, dependencies, and performance data. It provides right-sizing recommendations and cost estimates. For actual migration, use Azure Migrate: Server Migration (agentless for VMware, agent-based for other hypervisors). The agentless method replicates VMs without installing software—ideal for large-scale migrations. For database migrations, use Azure Database Migration Service. A common mistake is doing a 'lift and shift' without right-sizing—migrating with the same oversized specs as on-premises. Use the assessment to right-size. Also, test migrations with a pilot group before full cutover. For large-scale migrations (500+ VMs), use Azure Site Recovery for ongoing replication and planned failover. Post-migration, use Azure Advisor to continue optimizing.

assess-migration.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
# Create an Azure Migrate project
az migrate project create \
  --resource-group prod-rg \
  --name my-migration-project

# Assess on-prem VMs
az migrate assessment create \
  --resource-group prod-rg \
  --project-name my-migration-project \
  --name my-assessment \
  --group-name my-vm-group \
  --assessment-style 'Recommended' \
  --sizing-criteria 'PerformanceBased' \
  --percentile 'Percentile95' \
  --time-duration 'P30D' \
  --currency 'USD'
Output
{
"id": "/subscriptions/.../assessments/my-assessment",
"name": "my-assessment",
"properties": {
"sizingCriterion": "PerformanceBased",
"stage": "InProgress"
}
}
💡Use Pilot Migrations
Migrate a non-critical workload first to validate the process, tooling, and timing. Document lessons learned before the full cutover.
📊 Production Insight
We migrated 200 VMs from VMware to Azure using agentless migration. The first batch of 10 VMs revealed that our network bandwidth was insufficient—we had to upgrade ExpressRoute before continuing.
🎯 Key Takeaway
Azure Migrate provides end-to-end discovery, assessment, and migration; always right-size during migration.

Confidential Computing and Sensitive Workloads

For regulated industries handling sensitive data, Azure offers confidential computing VMs that encrypt data in use. DCasv5 and ECasv5 series use AMD SEV-SNP to create trusted execution environments (TEEs). This protects data even from Azure administrators. Use cases include multi-party data analytics, anti-money laundering, and healthcare data processing. For SQL Server, Always Encrypted with secure enclaves leverages confidential computing to process queries on encrypted data. In production, confidential VMs are 10-20% more expensive than standard VMs, but the security benefit justifies the cost for sensitive workloads. Always verify that your operating system and application support confidential computing. For example, Linux kernel 5.19+ is required for AMD SEV-SNP. Also, use Azure Attestation to verify that the TEE is genuine before processing sensitive data.

create-confidential-vm.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# Create a confidential VM with AMD SEV-SNP
az vm create \
  --resource-group prod-rg \
  --name confidential-vm-001 \
  --image Canonical:UbuntuServer:22_04-lts-gen2:latest \
  --size Standard_DC4as_v5 \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_rsa.pub \
  --security-type ConfidentialVM \
  --os-disk-security-encryption-type VMGuestStateOnly \
  --enable-vtpm true \
  --enable-secure-boot true
Output
{
"securityProfile": {
"securityType": "ConfidentialVM",
"uefiSettings": {
"secureBootEnabled": true,
"vTpmEnabled": true
}
},
"powerState": "VM running"
}
🔥TEE Verification
Use Azure Attestation to verify your VM is running in a genuine TEE before processing sensitive data. This prevents man-in-the-cloud attacks.
📊 Production Insight
A healthcare client needed to process PHI in the cloud but was blocked by compliance. Confidential VMs with Azure Attestation satisfied their auditor and unblocked the migration.
🎯 Key Takeaway
Confidential computing VMs protect data in use; use them for regulated workloads requiring TEE guarantees.
Availability Sets vs Availability Zones Trade-offs between fault domain isolation and latency Availability Set Availability Zone Fault Domain Isolation Shared rack within datacenter Separate physical datacenters Update Domain Handling Sequential reboot across groups Independent maintenance per zone Latency Low latency within datacenter Higher latency across zones SLA for Uptime 99.95% 99.99% Cost No additional cost Inter-zone data transfer charges Best For Legacy apps with low latency needs Mission-critical apps requiring high res THECODEFORGE.IO
thecodeforge.io
Azure Virtual Machines

VM Naming Conventions and Azure VM Families Deep Dive

Azure VM names encode critical information. The format is: Standard_{Family}{Sub-family}{vCPU count}{v}{Version}. For example, Standard_D2s_v5 means D-family (general purpose), 2 vCPUs, s (premium storage capable), v5 (5th generation). Understanding this helps you choose the right VM without memorizing every SKU. General purpose: D-series (balanced), B-series (burstable, credit-based). Compute optimized: F-series (high CPU-to-memory ratio). Memory optimized: E-series (high memory-to-CPU), M-series (very high memory for SAP HANA). Storage optimized: L-series (high disk throughput), NVMe (for databases). GPU: NC, ND, NV (AI/ML, visualization). HPC: HB, HC (high-performance computing). In 2026, the newest generations are v5 (Intel) and v6 (AMD). Always prefer the latest generation for better price-performance. For example, D5 v5 offers ~15% better performance per dollar than D4 v4. Use Azure Pricing Calculator to compare. Also, note that not all VM sizes are available in all regions—use az vm list-skus to check availability.

check-vm-skus.shBASH
1
2
3
4
5
# Check available VM SKUs in a region
az vm list-skus --location eastus --size Standard_D --all --output table

# Get information about a specific VM size
az vm list-skus --location eastus --size Standard_D2s_v5 --query "[].capabilities[]" -o table
Output
ResourceType Locations Name Zones
------------ --------- ---- -----
virtualMachines eastus Standard_D2s_v5 1,2,3
virtualMachines eastus Standard_D4s_v5 1,2,3
virtualMachines eastus Standard_D8s_v5 1,2,3
💡Generation Matters
Always use Gen2 VMs for newer features (confidential computing, larger memory). Gen1 VMs are legacy. Most new VM series require Gen2.
📊 Production Insight
We were using Standard_D4s_v4 and saw an opportunity to upgrade to v5 at no extra cost. The v5 had 50% better network bandwidth and newer Intel Xeon Platinum processors, improving our app latency by 20%.
🎯 Key Takeaway
Learn the VM naming convention to decode SKUs; prefer latest generations (v5/v6) for best price-performance.
⚙ Quick Reference
15 commands from this guide
FileCommand / CodePurpose
create-vm.shaz vm create \Azure VMs
Get-VMSizes.ps1Get-AzVMSize -Location eastus | Where-Object {$_.Name -like "Standard_D*"} | Sel...Choosing the Right VM Size and Series
create-vnet-nsg.shaz network vnet create \Networking
Configure-Backup.ps1$vault = Get-AzRecoveryServicesVault -ResourceGroupName prod-rg -Name prod-vaultStorage
create-vm-zones.shfor zone in 1 2 3; doHigh Availability
Create-ScaleSet.ps1$vmssConfig = New-AzVmssConfig `Scaling
install-nginx-extension.shaz vm extension set \Configuration Management with Extensions and Desired State
Enable-Monitoring.ps1$vm = Get-AzVM -ResourceGroupName prod-rg -Name prod-web-001Monitoring and Diagnostics
enable-disk-encryption.shaz vm encryption enable \Security
Get-CostRecommendations.ps1Get-AzAdvisorRecommendation -Category Cost | Where-Object {$_.Impact -eq "High"}...Cost Management and Right-Sizing
Configure-ASR.ps1$vault = Get-AzRecoveryServicesVault -ResourceGroupName prod-rg -Name prod-asr-v...Disaster Recovery
vm.bicepparam location string = resourceGroup().locationAutomation and Infrastructure as Code
assess-migration.shaz migrate project create \VM Migration and Modernization with Azure Migrate
create-confidential-vm.shaz vm create \Confidential Computing and Sensitive Workloads
check-vm-skus.shaz vm list-skus --location eastus --size Standard_D --all --output tableVM Naming Conventions and Azure VM Families Deep Dive

Key takeaways

1
Infrastructure as Code
Always define VMs, networking, and configuration in code (Bicep/Terraform) to avoid drift and enable repeatable deployments.
2
High Availability
Use Availability Zones for critical workloads; test failover regularly with Azure Site Recovery.
3
Security First
Encrypt disks, use managed identities, enable JIT access, and automate patching to reduce attack surface.
4
Cost Management
Right-size VMs, use reserved instances, and shut down idle resources to control cloud spend.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
Explain Virtual Machines and its use cases.
Q02JUNIOR
How does Virtual Machines handle high availability?
Q03JUNIOR
What are the security best practices for virtual machines?
Q04JUNIOR
How do you optimize costs for virtual machines?
Q05JUNIOR
Compare Azure virtual machines with self-hosted alternatives.
Q01 of 05JUNIOR

Explain Virtual Machines and its use cases.

ANSWER
Microsoft Azure — Virtual Machines is an Azure service for managing virtual machines in the cloud. Use it when you need reliable, scalable virtual machines without managing underlying infrastructure.
FAQ · 6 QUESTIONS

Frequently Asked Questions

01
What is the difference between Availability Set and Availability Zone?
02
How do I choose the right VM size for my workload?
03
Can I use Azure Backup for VMs with data disks?
04
How do I securely manage secrets in VM extensions?
05
What is the best practice for patching Azure VMs?
06
How can I reduce Azure VM costs?
N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Written from production experience, not tutorials.

Follow
Verified
production tested
July 19, 2026
last updated
2,466
articles · all by Naren
🔥

That's Azure. Mark it forged?

8 min read · try the examples if you haven't

Previous
Azure vs AWS vs GCP
9 / 55 · Azure
Next
Virtual Machine Scale Sets