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β
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:
| Type | Abbreviation | Technology | Max IOPS | Max Throughput | Latency | Use case |
|---|---|---|---|---|---|---|
| Ultra Disk | Ultra | NVMe | 160,000 | 2,000 MB/s | < 1ms | Tier-1 databases, SAP HANA |
| Premium SSD v2 | Prem v2 | SSD NVMe | 80,000 | 1,200 MB/s | < 1ms | Tier-2 databases, I/O intensive workloads |
| Premium SSD | P | SSD | 20,000 | 900 MB/s | ~1ms | General production, databases |
| Standard SSD | E | SSD | 6,000 | 750 MB/s | ~5ms | Web servers, light dev/test |
| Standard HDD | S | HDD | 2,000 | 500 MB/s | ~10ms | Backups, cold files |
3.2 Premium SSD disk namingβ
Premium SSD disks follow a size-based nomenclature (P-tiers):
| Tier | Size | IOPS | Throughput |
|---|---|---|---|
| P4 | 32 GB | 120 | 25 MB/s |
| P6 | 64 GB | 240 | 50 MB/s |
| P10 | 128 GB | 500 | 100 MB/s |
| P15 | 256 GB | 1,100 | 125 MB/s |
| P20 | 512 GB | 2,300 | 150 MB/s |
| P30 | 1 TB | 5,000 | 200 MB/s |
| P40 | 2 TB | 7,500 | 250 MB/s |
| P50 | 4 TB | 7,500 | 250 MB/s |
| P60 | 8 TB | 16,000 | 500 MB/s |
| P70 | 16 TB | 18,000 | 750 MB/s |
| P80 | 32 TB | 20,000 | 900 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 Mode | Behavior | Recommended for |
|---|---|---|
| None | No cache; read and write go directly to Azure Storage | Database log disks, Ultra disks |
| ReadOnly | Reads served from cache; writes go directly | OS disk, disks with more reads than writes |
| ReadWrite | Reads and writes go through cache | Only 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.
### 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β
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:
- Portal > VM > Disks > + Add data disk
- Select existing disk or create new
- Configure LUN, caching
- Save
To expand disk:
- Portal > VM > Disks > click on the disk
- Size + performance
- Change size and tier if needed
- Save
- Afterwards: extend partition inside the OS
To create snapshot:
- Portal > navigate to the disk
- + Create snapshot
- Name, choose type (Full or Incremental)
- 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:
| Model | Keys | Control |
|---|---|---|
| PMK (Platform Managed Keys) | Microsoft manages | Automatic, no configuration |
| CMK (Customer Managed Keys) | Customer manages in Key Vault | Requires Disk Encryption Set |
| Double Encryption | Two layers: PMK + CMK | Maximum 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β
| Situation | Recommended type | Reason |
|---|---|---|
| Tier-1 database (SQL, Oracle) | Premium SSD or Ultra Disk | Low latency, high IOPS |
| SAP HANA server | Ultra Disk | Latency < 1ms, very high IOPS |
| OS disk for web server | Premium SSD (P10 to P20) | Adequate performance, reasonable cost |
| File server with frequent access | Standard SSD (E) | Lower cost, acceptable performance |
| Backup and archiving | Standard HDD (S) | Minimal cost for cold data |
| Read cache for CDN/web | Premium SSD with ReadOnly cache | Maximizes reads from cache |
| Database log files | Premium SSD with caching None | Sequential writes don't benefit from cache |
| Dev/test with low usage | Standard SSD (E) | Controlled cost |
Full snapshot vs. Incremental snapshotβ
| Situation | Type | Reason |
|---|---|---|
| First snapshot of a disk | Full or Incremental | For incrementals, the first always has full cost |
| Daily recurring backup | Incremental | Pay only for changes, much more economical |
| Copy disk to another region | Full | Incrementals have restrictions for cross-region copying |
| Restore specific point in time | Incremental (if chain intact) | More economical for historical series |
Disk cachingβ
| Workload | OS Disk | Data Disks (read) | Data Disks (write/log) |
|---|---|---|---|
| SQL Server | ReadOnly or ReadWrite | ReadOnly | None |
| IIS/Apache web server | ReadOnly | ReadOnly | None |
| Development VM | ReadWrite | ReadOnly | None |
| Redis, Memcached | ReadOnly | None | None |
| Generic application | ReadOnly | ReadOnly | None |
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β
| Error | Why it happens | How to avoid |
|---|---|---|
| Disk unusable after expansion in Azure | Expands in Azure but forgets to extend partition in OS | Always run growpart/resize2fs after expanding in Azure |
| Data corruption when detaching without unmounting | File system with pending writes in buffer | Always umount before detach on Linux; eject on Windows |
| Orphaned disks accumulating cost | deleteOption=Detach default, VM deleted without deleting disks | Regularly audit disks without associated VM; use deleteOption=Delete |
| Trying to reduce disk size | Operation not supported | Disks only grow; create new smaller disk and migrate data |
| Data disk exceeding IOPS limit | Workload larger than sized | Monitor IOPS and upgrade tier before hitting limit |
| Incremental snapshot with corrupted chain | Delete snapshot from middle of chain | Never delete middle snapshots; always delete from oldest |
| Ultra Disk on incompatible VM SKU | Not all SKUs support Ultra Disk | Check support first: az vm list-skus --query "capabilities[?name=='UltraSSDAvailable']" |
| ReadWrite caching on database disk | Configuration mistake causes data loss on failure | Use 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β
| Limit | Value |
|---|---|
| Data disks per VM (max) | 64 (depends on SKU) |
| Maximum managed disk size | 32 TB |
| Snapshots per disk | No 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 VM | 0 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
deleteOptionoption determines if the disk is deleted or preserved when the VM is removed; default for data disks isDetach
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 == nullare orphaned and continue generating cost - Ultra Disk requires that the VM SKU supports
UltraSSDAvailableand is in an Availability Zone