Skip to main content

Theoretical Foundation: Manage Virtual Machine Disks


1. Initial Intuition​

Think of a VM as a complete computer. Every computer has at least one disk where the operating system is installed. But serious work computers also have additional disks for data, logs, backups and databases, each with different speed and size characteristics.

In Azure, VM disks work the same way, but with a fundamental difference compared to physical hardware: they are objects independent of the VM. A managed disk in Azure exists as a separate resource that can be created, expanded, disconnected, moved and protected independently of the VM to which it's connected.

Managing VM disks means understanding these objects: their types (HDD, SSD, Ultra), their performance characteristics, how to add and remove them from running VMs, how to expand their capacity, how to take snapshots for backup and how to protect against data loss.


2. Context​

Types of storage associated with VMs​

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

Managed Disks are the modern and recommended type: disks managed by Azure as independent ARM resources, with automatic encryption, replication and snapshots.

Unmanaged Disks (the legacy type) were VHDs stored in Storage Accounts managed by the customer. This format is considered legacy and should not be used in new environments.

Temporary Disk is covered in the VM Sizes module and is not a Managed Disk.

Why disks are objects independent of the VM​

In the physical world, an HD is inside the computer. If the computer burns out, the HD goes with it (unless you remove it beforehand).

In Azure, managed disks are objects separate from the VM. This allows:

  • Increasing the OS disk without recreating the VM
  • Moving a data disk from one VM to another
  • Creating snapshots of the disk without stopping the VM (for most types)
  • Protecting data on disk even after deleting the VM (if not deleted together)

3. Concept Construction​

3.1 Disk types by performance​

Azure offers four types of Managed disks, each with different performance and cost characteristics:

TypeAbbreviationTechnologyMax IOPSMax ThroughputLatencyUse case
Ultra DiskUltraNVMe160,0002,000 MB/s< 1msTier-1 databases, SAP HANA
Premium SSD v2Prem v2SSD NVMe80,0001,200 MB/s< 1msTier-2 databases, I/O intensive workloads
Premium SSDPSSD20,000900 MB/s~1msGeneral production, databases
Standard SSDESSD6,000750 MB/s~5msWeb servers, light dev/test
Standard HDDSHDD2,000500 MB/s~10msBackups, cold files

3.2 Premium SSD disk naming​

Premium SSD disks follow a size-based nomenclature (P-tiers):

TierSizeIOPSThroughput
P432 GB12025 MB/s
P664 GB24050 MB/s
P10128 GB500100 MB/s
P15256 GB1,100125 MB/s
P20512 GB2,300150 MB/s
P301 TB5,000200 MB/s
P402 TB7,500250 MB/s
P504 TB7,500250 MB/s
P608 TB16,000500 MB/s
P7016 TB18,000750 MB/s
P8032 TB20,000900 MB/s

The disk size determines its performance. A P30 1 TB disk has more IOPS than a P10 128 GB disk. If you need more IOPS but don't need more space, you can do performance tier bursting or use a higher tier.

3.3 Disk caching​

Disk caching is a per-disk configuration that defines whether the physical host uses its high-speed cache (RAM/local NVMe) for operations on that disk:

Cache ModeBehaviorRecommended for
NoneNo cache; read and write go directly to Azure StorageDatabase log disks, Ultra disks
ReadOnlyReads served from cache; writes go directlyOS disk, disks with more reads than writes
ReadWriteReads and writes go through cacheOnly when application guarantees consistency (journaled FS)

Critical attention: ReadWrite caching can cause data loss in case of host failure if the application doesn't have consistency mechanisms. For database data disks, use None or ReadOnly.

3.4 Shared Disks​

Premium SSD and Ultra Disk can be configured as Shared Disks, allowing multiple VMs to connect to the same disk simultaneously. This is used to implement high availability clusters like Windows Server Failover Clustering (WSFC) or Linux Pacemaker.

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

### 3.5 Snapshots

A **Snapshot** is a point-in-time copy of a managed disk. Snapshots are read-only and can be used to:
- Create backups before risky operations
- Create new disks based on the captured state
- Restore a disk to a previous state
- Copy disks between regions or subscriptions

**Snapshot types:**
- **Full snapshot:** complete copy of the disk. Cost based on used size, not provisioned size.
- **Incremental snapshot:** captures only blocks that changed since the last snapshot. Much more economical for recurring use.

```mermaid
```mermaid
graph LR
D1["Disk: 1 TB\n200 GB used"] --> SNAP1["Full Snapshot\n200 GB charged"]
D1 --> ISNAP1["Incremental Snapshot\n(first)\n200 GB charged"]
D1 -->|"Changes: 10 GB"| ISNAP2["Incremental Snapshot\n(second)\n10 GB charged"]

style SNAP1 fill:#f57c00,stroke:#e65100,color:#fff
style ISNAP1 fill:#2e7d32,stroke:#1b5e20,color:#fff
style ISNAP2 fill:#2e7d32,stroke:#1b5e20,color:#fff

### 3.6 Disk Bursting

Premium SSD (P1 to P20) and Standard SSD disks support **bursting**: ability to temporarily exceed IOPS and throughput limits of the tier during load spikes.

**On-demand bursting** (Premium SSD P30 and above with bursting enabled): allows exceeding the limit for prolonged periods, with credits that accumulate when the disk is below the limit.

**Credit-based bursting** (P1 to P20): credits accumulate when the disk is below the limit and are consumed when it exceeds, similar to B-series VMs model.

---

## 4. Structural View

### Complete disk structure in a VM

```mermaid
graph TD
VM["Virtual Machine"] --> OSD["OS Disk\nRequired\nP30 (1TB) Premium SSD\nCache: ReadOnly"]
VM --> DD1["Data Disk 1\nLUN 0\nP20 (512GB) Premium SSD\nCache: ReadOnly"]
VM --> DD2["Data Disk 2\nLUN 1\nP30 (1TB) Premium SSD\nCache: None (DB logs)"]
VM --> TD["Temporary Disk\nD: or /dev/sdb\nNot a Managed Disk\nEphemeral"]

OSD --> SSE["SSE: encrypted\nPMK or CMK"]
DD1 --> SSE
DD2 --> SSE

style OSD fill:#1565c0,stroke:#0d47a1,color:#fff
style DD1 fill:#2e7d32,stroke:#1b5e20,color:#fff
style DD2 fill:#2e7d32,stroke:#1b5e20,color:#fff
style TD fill:#d32f2f,stroke:#b71c1c,color:#fff
style SSE fill:#6a1b9a,stroke:#4a148c,color:#fff

Data disk lifecycle​

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

5. Practical Operation​

Expanding a disk (critical and non-reversible operation)​

Expanding a disk is a unidirectional operation: disks cannot be reduced in size. Once expanded from 128 GB to 256 GB, there's no way to go back to 128 GB without recreating the disk.

The expansion process has two components:

1. Expand the disk in Azure (management plane):

az disk update --resource-group rg-prod --name vm-data-disk --size-gb 512

2. Extend the partition inside the operating system: Just expanding the disk in Azure is not enough. The operating system still sees the old size until you extend the partition and file system inside the VM.

On Windows:

# Inside the VM - Disk Management GUI or via PowerShell:
$partition = Get-Partition -DriveLetter D
Resize-Partition -DiskNumber $partition.DiskNumber -PartitionNumber $partition.PartitionNumber -Size (Get-PartitionSupportedSize -DiskNumber $partition.DiskNumber -PartitionNumber $partition.PartitionNumber).SizeMax

On Linux:

# Inside the VM:
sudo growpart /dev/sdc 1 # extend partition
sudo resize2fs /dev/sdc1 # extend ext4 filesystem
# or for XFS:
sudo xfs_growfs /mountpoint

Adding data disk without stopping the VM​

Data disks can be added (attach) and removed (detach) from running VMs without needing to stop or restart, except for some older VM SKUs.

The correct process for detach in production (Linux):

# 1. Inside the VM: unmount the disk before detaching
sudo umount /dev/sdc1

# 2. In Azure: perform the detach
az vm disk detach --resource-group rg-prod --vm-name vm-01 --name data-disk-01

# Detaching without unmounting can cause data corruption

Non-obvious behaviors​

Expanding OS disk requires deallocation in most cases. Unlike data disks that can be expanded online (with VM running), the OS disk usually requires the VM to be deallocated before expansion. Check the SKU and OS documentation before planning the operation.

The number of supported data disks depends on the VM SKU. A Standard_B2s VM supports a maximum of 4 data disks. A Standard_D16s_v5 supports 32 disks. Attempting to add more disks than supported by the SKU will fail. Check with az vm list-vm-resize-options or the SKU documentation.

Disks have a deleteOption that determines what happens when the VM is deleted. By default, data disks have deleteOption = Detach (become orphaned when the VM is deleted), while OS disks created through the portal have deleteOption = Delete (are deleted with the VM). This can cause orphaned disks and unexpected costs.

Incremental snapshots cannot be copied to another region directly. To copy data between regions, you need to create a disk from the incremental snapshot in the source region and then copy the disk to the destination region, or use Azure Backup which manages this automatically.

Premium SSD disks without the s suffix in the VM SKU don't have caching benefits. If the VM doesn't support Premium Storage (SKU without s), the Premium SSD disk works but without host caching benefits, losing part of the performance advantage.


6. Implementation Methods​

Azure Portal​

When to use: one-time operations, disk state visualization

To add data disk:

  1. Portal > VM > Disks > + Add data disk
  2. Select existing disk or create new
  3. Configure LUN, caching
  4. Save

To expand disk:

  1. Portal > VM > Disks > click on the disk
  2. Size + performance
  3. Change size and tier if needed
  4. Save
  5. Afterwards: extend partition inside the OS

To create snapshot:

  1. Portal > navigate to the disk
  2. + Create snapshot
  3. Name, choose type (Full or Incremental)
  4. Review + Create

Azure CLI​

# View VM disks
az vm show \
--resource-group "rg-producao" \
--name "vm-db-01" \
--query "{OS: storageProfile.osDisk, Data: storageProfile.dataDisks}" \
--output json

# Create Premium SSD data disk (P30 = 1TB)
az disk create \
--resource-group "rg-producao" \
--name "vm-db-01-data-01" \
--size-gb 1024 \
--sku "Premium_LRS" \
--location "brazilsouth" \
--zone 1 # If VM is in Availability Zone 1

# Attach existing disk to a VM (without stopping)
az vm disk attach \
--resource-group "rg-producao" \
--vm-name "vm-db-01" \
--name "vm-db-01-data-01" \
--caching None \
--lun 0

# Create and attach new disk in one operation
az vm disk attach \
--resource-group "rg-producao" \
--vm-name "vm-db-01" \
--name "vm-db-01-data-02" \
--new \
--size-gb 512 \
--sku "Premium_LRS" \
--caching ReadOnly \
--lun 1

# Expand data disk (can be done with VM running)
az disk update \
--resource-group "rg-producao" \
--name "vm-db-01-data-01" \
--size-gb 2048

# Expand OS disk (usually requires deallocation)
az vm deallocate \
--resource-group "rg-producao" \
--name "vm-web-01"

az disk update \
--resource-group "rg-producao" \
--name "vm-web-01-osdisk" \
--size-gb 256

az vm start \
--resource-group "rg-producao" \
--name "vm-web-01"

# Remove data disk (detach - requires unmounting in OS first)
az vm disk detach \
--resource-group "rg-producao" \
--vm-name "vm-db-01" \
--name "vm-db-01-data-01"

# Create incremental snapshot (recommended for recurring use)
DISK_ID=$(az disk show \
--resource-group "rg-producao" \
--name "vm-db-01-data-01" \
--query "id" --output tsv)

az snapshot create \
--resource-group "rg-backups" \
--name "snap-vm-db-01-data-01-$(date +%Y%m%d)" \
--source "$DISK_ID" \
--incremental \
--location "brazilsouth"

# Create full snapshot
az snapshot create \
--resource-group "rg-backups" \
--name "snap-vm-db-01-data-01-full-$(date +%Y%m%d)" \
--source "$DISK_ID" \
--location "brazilsouth"

# Create new disk from snapshot
SNAP_ID=$(az snapshot show \
--resource-group "rg-backups" \
--name "snap-vm-db-01-data-01-20260324" \
--query "id" --output tsv)

az disk create \
--resource-group "rg-producao" \
--name "vm-db-01-data-01-restored" \
--source "$SNAP_ID" \
--sku "Premium_LRS" \
--location "brazilsouth"

# List orphaned disks (without associated VM) - for cleanup
az disk list \
--query "[?managedBy == null].{Name: name, RG: resourceGroup, Size: diskSizeGb, SKU: sku.name}" \
--output table

# Change disk type (e.g.: Standard SSD to Premium SSD)
# Requires disk to be detached OR VM deallocated
az disk update \
--resource-group "rg-producao" \
--name "vm-web-01-data-01" \
--sku "Premium_LRS"

# Configure deleteOption to avoid orphaned disks
# (when creating VM with Bicep/ARM, define in disks)
# Or update after creation:
az vm update \
--resource-group "rg-producao" \
--name "vm-web-01" \
--set storageProfile.dataDisks[0].deleteOption=Delete

# Enable on-demand bursting on Premium SSD P30+ disk
az disk update \
--resource-group "rg-producao" \
--name "vm-db-01-data-01" \
--enable-bursting true

Azure PowerShell​

# Create and add data disk
$diskConfig = New-AzDiskConfig `
-Location "brazilsouth" `
-DiskSizeGB 1024 `
-SkuName "Premium_LRS" `
-CreateOption Empty `
-Zone 1

$disk = New-AzDisk `
-ResourceGroupName "rg-producao" `
-DiskName "vm-db-01-data-01" `
-Disk $diskConfig

$vm = Get-AzVM -ResourceGroupName "rg-producao" -Name "vm-db-01"
$vm = Add-AzVMDataDisk `
-VM $vm `
-Name "vm-db-01-data-01" `
-ManagedDiskId $disk.Id `
-Lun 0 `
-Caching "None" `
-CreateOption Attach

Update-AzVM -ResourceGroupName "rg-producao" -VM $vm

# Expand data disk
$disk = Get-AzDisk -ResourceGroupName "rg-producao" -DiskName "vm-db-01-data-01"
$disk.DiskSizeGB = 2048
Update-AzDisk -ResourceGroupName "rg-producao" -DiskName $disk.Name -Disk $disk

# Create incremental snapshot
$snapshotConfig = New-AzSnapshotConfig `
-Location "brazilsouth" `
-CreateOption Copy `
-Incremental `
```powershell
-SourceResourceId (Get-AzDisk -ResourceGroupName "rg-producao" -DiskName "vm-db-01-data-01").Id

New-AzSnapshot `
-ResourceGroupName "rg-backups" `
-SnapshotName "snap-vm-db-01-$(Get-Date -Format 'yyyyMMdd')" `
-Snapshot $snapshotConfig

# List orphaned disks
Get-AzDisk |
Where-Object { $null -eq $_.ManagedBy } |
Select-Object Name, ResourceGroupName, DiskSizeGB, Sku |
Format-Table

Bicep​

// Create data disks as independent resources
resource dataDisk01 'Microsoft.Compute/disks@2022-07-02' = {
name: 'vm-db-01-data-01'
location: 'brazilsouth'
zones: ['1']
sku: {
name: 'Premium_LRS'
}
properties: {
creationData: {
createOption: 'Empty'
}
diskSizeGB: 1024
diskIOPSReadWrite: 5000 // Ultra Disk: customizable IOPS
diskMBpsReadWrite: 200 // Ultra Disk: customizable throughput
burstingEnabled: true // Premium SSD: enable bursting
}
}

// VM with disks and deleteOption configured
resource vm 'Microsoft.Compute/virtualMachines@2023-03-01' = {
name: 'vm-db-01'
location: 'brazilsouth'
zones: ['1']
properties: {
storageProfile: {
osDisk: {
name: 'vm-db-01-osdisk'
createOption: 'FromImage'
deleteOption: 'Delete' // OS disk deleted with VM
managedDisk: {
storageAccountType: 'Premium_LRS'
}
caching: 'ReadWrite'
diskSizeGB: 128
}
dataDisks: [
{
lun: 0
name: dataDisk01.name
createOption: 'Attach'
deleteOption: 'Detach' // Data disk NOT deleted with VM
managedDisk: {
id: dataDisk01.id
}
caching: 'None' // No cache for DB data disk
}
]
}
}
}

7. Control and Security​

Disk encryption​

All managed disks in Azure have encryption enabled by default via SSE (Storage Service Encryption). There are three models:

ModelKeysControl
PMK (Platform Managed Keys)Microsoft managesAutomatic, no configuration
CMK (Customer Managed Keys)Customer manages in Key VaultRequires Disk Encryption Set
Double EncryptionTwo layers: PMK + CMKMaximum security

For CMK, the Disk Encryption Set is necessary (as covered in the Encryption at Host module).

Disk backup with Azure Backup​

Azure Backup is the recommended solution for consistent backup of complete VMs (OS + all disks):

# Enable backup for a VM
az backup protection enable-for-vm \
--resource-group "rg-producao" \
--vault-name "rsv-backup-prod" \
--vm "vm-db-01" \
--policy-name "DefaultPolicy"

# Trigger immediate backup
az backup protection backup-now \
--resource-group "rg-producao" \
--vault-name "rsv-backup-prod" \
--container-name "IaasVMContainer;iaasvmcontainerv2;rg-producao;vm-db-01" \
--item-name "vm;iaasvmcontainerv2;rg-producao;vm-db-01" \
--backup-management-type AzureIaasVM

8. Decision Making​

Disk type selection​

SituationRecommended typeReason
Tier-1 database (SQL, Oracle)Premium SSD or Ultra DiskLow latency, high IOPS
SAP HANA serverUltra DiskLatency < 1ms, very high IOPS
OS disk for web serverPremium SSD (P10 to P20)Adequate performance, reasonable cost
File server with frequent accessStandard SSD (E)Lower cost, acceptable performance
Backup and archivingStandard HDD (S)Minimal cost for cold data
Read cache for CDN/webPremium SSD with ReadOnly cacheMaximizes reads from cache
Database log filesPremium SSD with caching NoneSequential writes don't benefit from cache
Dev/test with low usageStandard SSD (E)Controlled cost

Full snapshot vs. Incremental snapshot​

SituationTypeReason
First snapshot of a diskFull or IncrementalFor incrementals, the first always has full cost
Daily recurring backupIncrementalPay only for changes, much more economical
Copy disk to another regionFullIncrementals have restrictions for cross-region copying
Restore specific point in timeIncremental (if chain intact)More economical for historical series

Disk caching​

WorkloadOS DiskData Disks (read)Data Disks (write/log)
SQL ServerReadOnly or ReadWriteReadOnlyNone
IIS/Apache web serverReadOnlyReadOnlyNone
Development VMReadWriteReadOnlyNone
Redis, MemcachedReadOnlyNoneNone
Generic applicationReadOnlyReadOnlyNone

9. Best Practices​

Always configure deleteOption on disks when creating VMs via IaC. The default of Detach for data disks means they become orphaned resources when the VM is deleted, generating ongoing cost without use. Decide consciously: Delete for temporary/disposable disks, Detach for disks with data that should survive the VM.

Use incremental snapshots for regular backups. The savings compared to full snapshots can be 80-95% on disks with low change rate. Configure a daily incremental snapshot policy with 30-day retention for much lower backup costs than full snapshots.

Separate data by function into different disks. Don't put database log files on the same disk as data files. Separate disks allow different cache configurations (None for logs, ReadOnly for data) and enable independent backup of each component.

Monitor IOPS and throughput before choosing disk type. Many teams over-provision disk type as a precaution. A week of Azure Monitor metrics showing actual IOPS often reveals that a P30 Premium SSD would be adequate where an Ultra Disk was placed.

Don't store anything critical on the temporary disk. The temporary disk (D: on Windows) is recreated with every deallocation or resize. It's only suitable for temporary processing data, swap/page files, and data that can be regenerated.

For databases, use Availability Zones with ZRS disks. Managed Disks with ZRS (Zone Redundant Storage) replication replicate data across 3 availability zones within a region, ensuring that the loss of one zone doesn't lose data.


10. Common Errors​

ErrorWhy it happensHow to avoid
Disk unusable after expansion in AzureExpands in Azure but forgets to extend partition in OSAlways run growpart/resize2fs after expanding in Azure
Data corruption when detaching without unmountingFile system with pending writes in bufferAlways umount before detach on Linux; eject on Windows
Orphaned disks accumulating costdeleteOption=Detach default, VM deleted without deleting disksRegularly audit disks without associated VM; use deleteOption=Delete
Trying to reduce disk sizeOperation not supportedDisks only grow; create new smaller disk and migrate data
Data disk exceeding IOPS limitWorkload larger than sizedMonitor IOPS and upgrade tier before hitting limit
Incremental snapshot with corrupted chainDelete snapshot from middle of chainNever delete middle snapshots; always delete from oldest
Ultra Disk on incompatible VM SKUNot all SKUs support Ultra DiskCheck support first: az vm list-skus --query "capabilities[?name=='UltraSSDAvailable']"
ReadWrite caching on database diskConfiguration mistake causes data loss on failureUse None for database logs; ReadOnly for data

The most critical error​

Running az vm disk detach on a production database disk without first stopping the database and unmounting the disk within the OS. The Linux operating system will try to continue writing to a device that no longer exists, resulting in data corruption and application failure. The correct procedure is always: stop the application, unmount the disk in the OS, then detach in Azure.


11. Operations and Maintenance​

Disk inventory and audit​

# List all disks with detailed information
az disk list \
--query "[].{
Name: name,
RG: resourceGroup,
Size: diskSizeGb,
SKU: sku.name,
VM: managedBy,
State: diskState
}" \
--output table

# Orphaned disks (without VM, with unnecessary cost)
az disk list \
--query "[?managedBy == null && diskState != 'Unattached'].{Name: name, RG: resourceGroup, Size: diskSizeGb}" \
--output table

# Estimated cost of orphaned disks via Resource Graph
az graph query -q "
Resources
| where type == 'microsoft.compute/disks'
| where isnull(properties.managedBy)
| project name, resourceGroup, diskSizeGb=properties.diskSizeGB, sku=sku.name, location
| order by diskSizeGb desc"

# Snapshots older than 30 days
az snapshot list \
--query "[?timeCreated < '$(date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZ)'].{Name: name, Created: timeCreated, Size: diskSizeGb}" \
--output table

Monitor disk performance​

# IOPS consumed vs. disk limit
az monitor metrics list \
--resource "/subscriptions/<sub-id>/resourceGroups/rg-producao/providers/Microsoft.Compute/virtualMachines/vm-db-01" \
--metric "Data Disk IOPS Consumed Percentage" \
--interval PT5M \
--aggregation Average \
--output table

# Disk throughput
az monitor metrics list \
--resource "/subscriptions/<sub-id>/resourceGroups/rg-producao/providers/Microsoft.Compute/virtualMachines/vm-db-01" \
--metric "Data Disk Bandwidth Consumed Percentage" \
--interval PT5M \
--aggregation Maximum \
--output table

Important limits​

LimitValue
Data disks per VM (max)64 (depends on SKU)
Maximum managed disk size32 TB
Snapshots per diskNo documented limit (practical: a few hundred)
Disks in Shared Disk (Premium SSD)Up to 5 VMs sharing
Disks in Shared Disk (Ultra Disk)Up to 5 VMs sharing
Available LUNs per VM0 to 63

12. Integration and Automation​

Automated snapshot policy​

Azure Backup manages complete lifecycles, but for pure snapshot scenarios you can use Azure Automation:

# Runbook: create daily incremental snapshots and clean up oldest ones
param (
[string]$ResourceGroup = "rg-producao",
[int]$RetentionDays = 30
)

Connect-AzAccount -Identity

$vms = Get-AzVM -ResourceGroupName $ResourceGroup

foreach ($vm in $vms) {
foreach ($disk in $vm.StorageProfile.DataDisks) {
$diskObj = Get-AzDisk -ResourceGroupName $ResourceGroup -DiskName $disk.Name

# Create incremental snapshot
$snapConfig = New-AzSnapshotConfig `
-Location $diskObj.Location `
-CreateOption Copy `
-Incremental `
-SourceResourceId $diskObj.Id

$snapName = "$($disk.Name)-snap-$(Get-Date -Format 'yyyyMMdd')"
New-AzSnapshot -ResourceGroupName "rg-backups" -SnapshotName $snapName -Snapshot $snapConfig
Write-Output "Snapshot created: $snapName"
}
}

# Delete snapshots older than $RetentionDays
$cutoffDate = (Get-Date).AddDays(-$RetentionDays)
$oldSnapshots = Get-AzSnapshot -ResourceGroupName "rg-backups" |
Where-Object { $_.TimeCreated -lt $cutoffDate }

foreach ($snap in $oldSnapshots) {
Remove-AzSnapshot -ResourceGroupName "rg-backups" -SnapshotName $snap.Name -Force
Write-Output "Snapshot removed: $($snap.Name)"
}

Azure Policy to enforce disk types​

# Deny creation of standard HDD disks in production environment
az policy assignment create \
--name "deny-standard-hdd-prod" \
--display-name "Prohibit Standard HDD in production" \
--policy "11ac78e3-31dc-4ccb-a61a-1cde2a38a2a0" \
--scope "/subscriptions/<sub-id>/resourceGroups/rg-producao" \
--params '{"listOfAllowedSKUs": {"value": ["Premium_LRS", "StandardSSD_LRS", "UltraSSD_LRS"]}}'

13. Final Summary​

Essential points:

  • Managed Disks are ARM objects independent of the VM, persistent and replicated by Azure
  • There are four types by performance: Ultra Disk (maximum), Premium SSD v2, Premium SSD (most common in production), Standard SSD and Standard HDD (archival)
  • Disk caching has three modes: None, ReadOnly and ReadWrite; use None for database logs to avoid data loss
  • Data disks can be added and removed without stopping the VM; OS disk usually requires deallocation for expansion
  • Disk expansion is irreversible: disks cannot be reduced in size
  • Incremental snapshots capture only changed blocks and are much more economical for recurring use than full snapshots
  • The deleteOption option determines if the disk is deleted or preserved when the VM is removed; default for data disks is Detach

Critical differences:

  • Managed Disk vs. Temporary Disk: Managed is persistent and independent; Temporary is ephemeral and lost on every deallocation
  • Full Snapshot vs. Incremental Snapshot: Full copies the entire disk; Incremental copies only changed blocks since the last snapshot
  • Detach vs. Delete: Detach disconnects the disk but preserves it as a resource; Delete permanently removes it
  • Caching ReadOnly vs. ReadWrite: ReadOnly is safe for most workloads; ReadWrite can cause data loss on host failure if the application is not journal-safe

What needs to be remembered for the AZ-104:

  • Disk SKU suffix: Premium_LRS, StandardSSD_LRS, Standard_LRS (HDD), UltraSSD_LRS
  • Command to expand: az disk update --size-gb (then extend partition in OS)
  • Command to add disk: az vm disk attach
  • Command to remove disk: az vm disk detach (unmount in OS first)
  • Maximum number of data disks per VM: up to 64, depending on SKU
  • Incremental snapshots are recommended for recurring backup use
  • Disks with managedBy == null are orphaned and continue generating cost
  • Ultra Disk requires that the VM SKU supports UltraSSDAvailable and is in an Availability Zone