Virtual Machines & Scale Sets
By the end of this lesson you will be able to choose a VM size and image, create a Linux VM that installs a web server on first boot, run a command on it without SSH, stop it so billing for compute stops, and run a group of identical VMs with a scale set that grows and shrinks with load.
What is an Azure virtual machine?
An Azure virtual machine (VM) is a computer that runs in Microsoft's data centre. It has CPUs, memory, disks and a network card, and you install and manage its operating system. This is IaaS: maximum control, maximum responsibility. You patch it, secure it and back it up.
A VM is like renting a furnished flat. The building, water and electricity are the landlord's job. Locking the door, cleaning and what you put inside are yours.
Use VMs when you need full control: custom software, older apps that expect a full server, special drivers, or lift-and-shift migration from an office data centre. For a normal web app, App Service is usually less work.
Sizes, images and disks
Sizes describe CPU, memory and features. Read a size name from left to right:
Part of Standard_D2s_v5 | Meaning |
|---|---|
D | Family: general purpose. Others: B burstable, E memory-heavy, F compute-heavy, N GPU |
2 | Number of vCPUs (virtual CPUs) |
s | Supports Premium SSD disks |
v5 | Generation of the hardware |
B-series (burstable) VMs earn CPU credits while idle and spend them in short bursts. They suit small websites and practice labs.
Images are templates for the operating system disk, such as Ubuntu Server 24.04 LTS or Windows Server. They come from the Azure Marketplace and are named by a URN, publisher:offer:sku:version. The CLI also accepts short aliases such as Ubuntu2404; run az vm image list --output table to see the aliases your CLI version knows.
Managed disks store data. Every VM has an OS disk and can have data disks. Disk types range from Standard HDD (cheapest, slowest) through Standard SSD and Premium SSD to Premium SSD v2 and Ultra Disk (fastest). Many sizes also have a temporary disk that is wiped when the VM moves hosts: never keep important files there.
Step by step: a web server VM with cloud-init
cloud-init is a standard tool that runs setup instructions on a Linux VM's first boot. You pass it as custom data.
Step 1: save this file as cloud-init.yaml. It installs nginx and writes a home page.
#cloud-config
package_update: true
packages:
- nginx
write_files:
- path: /var/www/html/index.html
content: |
<h1>Rohtak Library Catalogue</h1>
<p>Served from an Azure VM.</p>
runcmd:
- systemctl enable --now nginxStep 2: create the resource group and the VM. This VM gets a public IP so you can test it; production VMs usually sit behind a load balancer with no public IP.
az group create --name rg-vm-demo --location centralindia --output none
az vm create --resource-group rg-vm-demo --name vm-library-01 \
--image Ubuntu2404 --size Standard_B2s \
--admin-username azureuser --generate-ssh-keys \
--custom-data cloud-init.yaml --public-ip-sku Standard{
"fqdns": "",
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-vm-demo/providers/Microsoft.Compute/virtualMachines/vm-library-01",
"location": "centralindia",
"macAddress": "00-0D-3A-00-00-01",
"powerState": "VM running",
"privateIpAddress": "10.0.0.4",
"publicIpAddress": "203.0.113.40",
"resourceGroup": "rg-vm-demo",
"zones": ""
}This output is traced from Microsoft's VM quickstart with placeholder addresses. --generate-ssh-keys uses your existing SSH key or creates one in ~/.ssh. The command also creates a VNet, subnet, NSG, public IP and NIC for you, all named after the VM.
Step 3: open port 80 in the VM's NSG and visit http://<publicIpAddress>.
az vm open-port --resource-group rg-vm-demo --name vm-library-01 --port 80 --priority 900 --output noneYou should see "Rohtak Library Catalogue" in the browser.
Step 4: run a command inside the VM without SSH, using Run Command:
az vm run-command invoke --resource-group rg-vm-demo --name vm-library-01 \
--command-id RunShellScript --scripts "systemctl is-active nginx" \
--query "value[0].message" --output tsvEnable succeeded: [stdout] active [stderr]
The message format is traced from the Run Command documentation.
Stopped versus deallocated
This difference costs learners real money:
| State | How you get there | Compute billing |
|---|---|---|
| Running | Normal | Yes |
| Stopped | Shutting down from inside the OS, or az vm stop | Yes, the hardware is still reserved |
| Stopped (deallocated) | az vm deallocate, or Stop in the portal | No, but disks are still billed |
az vm deallocate --resource-group rg-vm-demo --name vm-library-01
az vm get-instance-view --resource-group rg-vm-demo --name vm-library-01 \
--query "instanceView.statuses[1].displayStatus" --output tsvVM deallocated
You can also set auto-shutdown in the portal so practice VMs deallocate every evening.
Availability: sets, zones and scale sets
A single VM can fail during hardware faults or maintenance. Options, from oldest to newest:
- Availability sets spread VMs across fault domains (separate racks) and update domains in one data centre. You still meet them in older designs.
- Availability zones place VMs in different buildings of a region, as you saw in Regions.
- Virtual Machine Scale Sets manage a group of VMs as one, spread them across zones and add or remove instances automatically.
Scale sets
A scale set is like a bus depot that adds buses on festival days and parks them afterwards. Use Flexible orchestration, the recommended mode for new scale sets. Uniform mode is the older style where every instance is identical and managed only through the scale set.
Step 1: create a zone-spread Flexible scale set with the same cloud-init file.
az vmss create --resource-group rg-vm-demo --name vmss-library \
--orchestration-mode Flexible --image Ubuntu2404 --vm-sku Standard_B2s \
--instance-count 2 --zones 1 2 3 \
--admin-username azureuser --generate-ssh-keys --custom-data cloud-init.yaml --output noneStep 2: add autoscale rules: keep 2 to 6 instances, add one when average CPU stays above 70% for 5 minutes, remove one below 30%.
az monitor autoscale create --resource-group rg-vm-demo --name as-library \
--resource vmss-library --resource-type Microsoft.Compute/virtualMachineScaleSets \
--min-count 2 --max-count 6 --count 2 --output none
az monitor autoscale rule create --resource-group rg-vm-demo --autoscale-name as-library \
--condition "Percentage CPU > 70 avg 5m" --scale out 1 --output none
az monitor autoscale rule create --resource-group rg-vm-demo --autoscale-name as-library \
--condition "Percentage CPU < 30 avg 5m" --scale in 1 --output nonePut the scale set behind a load balancer so users always reach a healthy instance.
Clean up: az group delete --name rg-vm-demo --yes --no-wait.
Common mistakes
- Shutting down from inside Linux and assuming billing stops. Deallocate instead.
- Leaving port 22 open to the internet. Use Azure Bastion or Run Command.
- Storing data on the temporary disk. It can be wiped. Use a managed data disk.
- Building pets. Hand-configured servers are hard to replace. Use cloud-init and scale sets so any instance can be rebuilt.
Key points
- A VM is IaaS: you manage the OS, patches and security.
- Size names encode family, vCPUs, features and generation; B-series suits small workloads.
- cloud-init custom data configures Linux VMs on first boot; Run Command runs scripts without SSH.
- Only a deallocated VM stops compute billing; disks are billed until deleted.
- Flexible scale sets with autoscale and zones give resilient, elastic VM groups.
Exercise
Write the commands to create a VM named vm-exam-01 in rg-exam (Central India) using the Ubuntu2404 image, size Standard_B1s, SSH keys, no public IP (--public-ip-address ""), and then deallocate it. Explain in one sentence why a VM without a public IP is safer.
Show solution
az group create --name rg-exam --location centralindia --output none
az vm create --resource-group rg-exam --name vm-exam-01 --image Ubuntu2404 --size Standard_B1s \
--admin-username azureuser --generate-ssh-keys --public-ip-address "" --output none
az vm deallocate --resource-group rg-exam --name vm-exam-01Without a public IP, nothing on the internet can even try to connect to the VM; you reach it through Bastion or Run Command, and it reaches the internet only through an explicit outbound method such as a NAT gateway.
Quick Quiz
1. Which state stops compute billing for a VM?
Only deallocation releases the hardware; disks are still billed.
2. What does the s in Standard_D2s_v5 mean?
The s marks support for premium storage.
3. Which orchestration mode is recommended for new scale sets?
Microsoft recommends Flexible orchestration for new scale sets.
Learn Microsoft Azure with a mentor
Free lessons get you started. Our Cloud & DevOps training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
