Skip to main content

Azure Virtual Machines — Launch, Connect, and Manage Your First VM

· 6 min read
Goel Academy
DevOps & Cloud Learning Hub

Your team needs a Linux server running in the cloud by end of day. You could click through the Azure portal for 15 minutes, or you could type one CLI command and have a production-ready VM in under 3 minutes. Let us go with option two.

Choosing the Right VM Size

Azure offers over 700 VM sizes across multiple families. Picking the wrong one means either wasting money or hitting performance walls. Here is a cheat sheet for the most common families:

SeriesOptimized ForvCPUsRAMUse Case
BBurstable1-200.5-80 GBDev/test, low-traffic web servers
DGeneral Purpose2-968-384 GBMost production workloads
EMemory Optimized2-10416-672 GBDatabases, in-memory caching
FCompute Optimized2-724-144 GBBatch processing, gaming servers
NGPU6-24112-448 GBML training, video rendering

Pro tip: Start with a B-series for development and testing. A Standard_B2s (2 vCPUs, 4 GB RAM) costs roughly $30/month and handles most non-production workloads.

Creating Your First VM

# Create a resource group first
az group create --name rg-dev-compute-eastus --location eastus

# Create an Ubuntu VM with SSH key authentication
az vm create \
--resource-group rg-dev-compute-eastus \
--name vm-dev-web-001 \
--image Ubuntu2204 \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard \
--tags Environment=Development Team=Platform

This single command creates the VM plus a virtual network, subnet, public IP, network security group, and network interface. Azure wires them all together automatically.

Listing Available VM Sizes for Your Region

# List VM sizes available in East US
az vm list-sizes \
--location eastus \
--output table \
--query "[?starts_with(name, 'Standard_B')]"

Connecting to Your VM

SSH (Linux VMs)

# Get the public IP
az vm show \
--resource-group rg-dev-compute-eastus \
--name vm-dev-web-001 \
--show-details \
--query publicIps \
--output tsv

# Connect via SSH
ssh azureuser@<public-ip>

RDP (Windows VMs)

For Windows VMs, you need to open port 3389:

# Create a Windows VM
az vm create \
--resource-group rg-dev-compute-eastus \
--name vm-dev-win-001 \
--image Win2022Datacenter \
--size Standard_B2s \
--admin-username azureuser \
--admin-password 'YourP@ssw0rd123!' \
--public-ip-sku Standard

# Open RDP port
az vm open-port \
--resource-group rg-dev-compute-eastus \
--name vm-dev-win-001 \
--port 3389

Managed Disks

Every VM needs at least an OS disk. Azure Managed Disks handle the storage account complexity for you. Here are your options:

Disk TypeIOPS (max)ThroughputCost (128 GB/mo)Use Case
Standard HDD50060 MB/s~$5Backups, dev/test
Standard SSD6,000750 MB/s~$10Web servers, light workloads
Premium SSD7,500250 MB/s~$19Production databases
Ultra Disk160,0004,000 MB/s~$65+SAP HANA, top-tier databases

Adding a Data Disk

# Attach a 128 GB Premium SSD data disk
az vm disk attach \
--resource-group rg-dev-compute-eastus \
--vm-name vm-dev-web-001 \
--name disk-data-web-001 \
--size-gb 128 \
--sku Premium_LRS \
--new

After attaching, SSH into the VM and format the disk:

# Inside the VM — find the new disk
lsblk

# Partition, format, and mount
sudo parted /dev/sdc --script mklabel gpt mkpart primary ext4 0% 100%
sudo mkfs.ext4 /dev/sdc1
sudo mkdir /data
sudo mount /dev/sdc1 /data

# Persist the mount across reboots
echo '/dev/sdc1 /data ext4 defaults 0 2' | sudo tee -a /etc/fstab

Availability: Sets vs Zones

Downtime is not an option for production. Azure gives you two strategies:

Availability Sets distribute VMs across fault domains (separate racks) and update domains (separate maintenance windows) within a single datacenter. You get 99.95% SLA.

Availability Zones spread VMs across physically separate datacenters in a region. You get 99.99% SLA.

# Create a VM in a specific availability zone
az vm create \
--resource-group rg-dev-compute-eastus \
--name vm-prod-web-001 \
--image Ubuntu2204 \
--size Standard_D2s_v5 \
--zone 1 \
--admin-username azureuser \
--generate-ssh-keys

Use Availability Zones for production workloads whenever the region supports them. Use Availability Sets only when zones are unavailable.

VM Scale Sets

Need to auto-scale from 2 to 50 instances based on CPU load? VM Scale Sets handle this automatically.

# Create a scale set with 2 initial instances
az vmss create \
--resource-group rg-dev-compute-eastus \
--name vmss-web \
--image Ubuntu2204 \
--vm-sku Standard_B2s \
--instance-count 2 \
--admin-username azureuser \
--generate-ssh-keys \
--upgrade-policy-mode automatic

# Add auto-scale rule: scale out when CPU > 70%
az monitor autoscale create \
--resource-group rg-dev-compute-eastus \
--resource vmss-web \
--resource-type Microsoft.Compute/virtualMachineScaleSets \
--min-count 2 \
--max-count 10 \
--count 2

az monitor autoscale rule create \
--resource-group rg-dev-compute-eastus \
--autoscale-name vmss-web \
--condition "Percentage CPU > 70 avg 5m" \
--scale out 2

Cloud-Init: Configure VMs at Boot

Cloud-init lets you install packages, write files, and run commands the instant a VM boots — no SSH required.

Create a file called cloud-init.yaml:

#cloud-config
package_update: true
packages:
- nginx
- docker.io
- curl
runcmd:
- systemctl enable nginx
- systemctl start nginx
- echo "<h1>Hello from $(hostname)</h1>" > /var/www/html/index.html

Then pass it when creating the VM:

az vm create \
--resource-group rg-dev-compute-eastus \
--name vm-dev-web-002 \
--image Ubuntu2204 \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--custom-data cloud-init.yaml

Within 60 seconds of boot, your VM has Nginx and Docker running with a custom landing page.

Cost Optimization: Pay-as-you-go vs Reserved vs Spot

Pricing ModelDiscountCommitmentBest For
Pay-as-you-go0%NoneDev/test, variable workloads
1-Year Reserved~35%1 yearSteady-state production
3-Year Reserved~55%3 yearsLong-running infrastructure
Spot InstancesUp to 90%None (can be evicted)Batch jobs, fault-tolerant work

Managing VM Power State

Stop billing when you are not using a VM:

# Deallocate (stops billing for compute, keeps disk)
az vm deallocate \
--resource-group rg-dev-compute-eastus \
--name vm-dev-web-001

# Start it back up
az vm start \
--resource-group rg-dev-compute-eastus \
--name vm-dev-web-001

# Check power state
az vm get-instance-view \
--resource-group rg-dev-compute-eastus \
--name vm-dev-web-001 \
--query instanceView.statuses[1].displayStatus \
--output tsv

Important: az vm stop keeps the VM allocated and you still pay for compute. Always use az vm deallocate to stop billing.

Wrapping Up

Azure VMs are the workhorse of cloud computing. Pick the right size family, use managed disks, deploy across availability zones, and automate configuration with cloud-init. Most importantly, deallocate your dev VMs at night — your finance team will thank you.


Next up: We dive into Azure Storage — Blobs, Queues, Tables, and Files — the four pillars of cloud-native data storage.