Home DevOps Microsoft Azure — Virtual Machines
Intermediate 6 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 12, 2026
last updated
436
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 Microsoft Azure?

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.
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

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.
⚙ Quick Reference
12 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

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.

Common mistakes to avoid

3 patterns
×

Not planning virtual machines properly before deployment

Fix
Design your architecture with redundancy, scaling, and security in mind from the start.
×

Ignoring Azure best practices for virtual machines

Fix
Follow Microsoft's Well-Architected Framework and review Azure Advisor recommendations regularly.
×

Overlooking cost implications of virtual machines

Fix
Set budgets and alerts, right-size resources, and use Azure pricing calculator before deploying.
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 12, 2026
last updated
436
articles · all by Naren
🔥

That's Azure. Mark it forged?

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

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