Home / Azure

AzureHow-toBeginner

Add a data disk to an Azure VM: attach, initialize and mount it so it survives a reboot

Create and attach a managed data disk with the Azure CLI, then partition, format and mount it on Windows and Linux so it comes back after every reboot.

Deepak Bhardwaj5 min read

Applies toAzure managed disks, Azure CLI 2.x, Windows Server 2016+, Ubuntu/RHEL with ext4 or XFS

Goal

An application needs its own volume for data, logs or database files, separate from the OS disk. You want to add a managed data disk, make it usable in the guest OS, and make sure it's still mounted after the next reboot or redeploy.

Keeping data off the OS disk makes it easier to resize, snapshot or move the data without touching the operating system.

Before you start

Check how many data disks the VM size supports and what's already attached. Each VM size has a maximum data disk count, so check the size documentation for current limits.

RG=rg-prod; VM=vm-app-01
az vm show -g $RG -n $VM --query "{size:hardwareProfile.vmSize, zone:zones, disks:storageProfile.dataDisks[].{lun:lun, name:name, sizeGb:diskSizeGb}}" -o json

SIZE=$(az vm show -g $RG -n $VM --query hardwareProfile.vmSize -o tsv)
LOC=$(az vm show -g $RG -n $VM --query location -o tsv)
az vm list-sizes -l $LOC --query "[?name=='$SIZE'].{size:name, maxDataDisks:maxDataDiskCount}" -o table

If the VM is in an availability zone, the disk must be created in the same zone.

Create and attach the disk

The quickest way is to create and attach in one step. --new creates an empty managed disk:

az vm disk attach -g $RG --vm-name $VM \
  --name ${VM}-data-01 --new --size-gb 256 --sku Premium_LRS --lun 0

Or create the disk first when you need more control, for example a zone or a specific tier:

az disk create -g $RG -n ${VM}-data-01 --size-gb 256 --sku Premium_LRS --zone 1
az vm disk attach -g $RG --vm-name $VM --name ${VM}-data-01 --lun 0 --caching ReadOnly

Pick the LUN deliberately. It's how you find the disk inside the guest, and it should not clash with an existing data disk.

Workload Host caching
Database data files, read-heavy ReadOnly
Database or application log files, write-heavy None
General application data ReadOnly or None

Attaching a data disk doesn't need a reboot on current VM sizes.

Initialize the disk on Windows

The new disk appears offline and RAW. Find it by LUN rather than by disk number, because disk numbers can change:

Get-Disk | Where-Object PartitionStyle -eq 'RAW' |
  Select-Object Number, FriendlyName, Size, Location

# Initialize, partition and format the RAW disk (use the number from above)
$n = 2
Set-Disk -Number $n -IsOffline $false   # needed if the SAN policy left the disk offline
Initialize-Disk -Number $n -PartitionStyle GPT
New-Partition -DiskNumber $n -UseMaximumSize -DriveLetter F |
  Format-Volume -FileSystem NTFS -NewFileSystemLabel "Data" -AllocationUnitSize 65536 -Confirm:$false
Get-Volume -DriveLetter F

The Location column includes the LUN, which you can match to the --lun you used. A 64 KB allocation unit is the usual recommendation for SQL Server data and log volumes; the default is fine for general file storage.

Caution

Initialize-Disk and Format-Volume destroy whatever is on the target disk. Filter on PartitionStyle -eq 'RAW' and check the size and LUN before running them, especially on servers with several data disks.

Windows remembers the drive letter, so no further step is needed to keep it after a reboot.

Initialize the disk on Linux

Azure Linux images create stable symlinks per LUN under /dev/disk/azure/scsi1/ (the exact path can vary by image and storage controller, so ls it first). Use those links instead of /dev/sdc, because sdX names can change between boots.

ls -l /dev/disk/azure/scsi1/          # lun0 -> ../../../sdc, for example
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE

DISK=/dev/disk/azure/scsi1/lun0
sudo parted $DISK --script mklabel gpt mkpart primary 0% 100%
sudo partprobe $DISK
sudo mkfs.xfs ${DISK}-part1           # or: sudo mkfs.ext4 ${DISK}-part1

sudo mkdir -p /data
sudo mount ${DISK}-part1 /data
df -h /data

If the -part1 link doesn't exist on your image, use the partition name that lsblk shows, for example /dev/sdc1, only for the format step.

Make the mount persistent with fstab

Mount by UUID, and add nofail so the VM still boots if the disk is ever detached:

UUID=$(sudo blkid -s UUID -o value ${DISK}-part1)
echo "UUID=$UUID  /data  xfs  defaults,nofail  0  2" | sudo tee -a /etc/fstab

# Test the fstab entry before you reboot
sudo umount /data
sudo mount -a
findmnt /data

Use ext4 instead of xfs in the fstab line if you formatted with ext4.

Warning

A wrong fstab line without nofail can drop a Linux VM into emergency mode on the next boot, and then you need the Serial Console to fix it. Always run sudo mount -a and check for errors before rebooting.

Verify

az vm show -g $RG -n $VM --query "storageProfile.dataDisks[].{lun:lun, name:name, caching:caching, sizeGb:diskSizeGb}" -o table
  • Inside the guest, Get-Volume or df -h shows the new volume with the expected size.
  • Write a test file, reboot the VM, and confirm the volume and file are still there.
  • Point the application at the new path and restart it.

Detach a disk safely

When a disk is no longer needed, stop the application, unmount it in the guest (remove the fstab line on Linux, or take the disk offline on Windows), then detach:

az vm disk detach -g $RG --vm-name $VM --name ${VM}-data-01

Detaching does not delete the disk. It keeps costing money until you run az disk delete, so snapshot it first if there's any doubt about the data.

Prevent it next time

  • Build it into the template. Add data disks in Bicep or Terraform, and format them with cloud-init or a Custom Script Extension, so every rebuild comes out the same.
  • Alert on free space for each data volume, not only the OS disk.
  • Include data disks in backups. Azure Backup protects all disks by default, but check that nobody excluded the new one.
  • Name disks after the VM and purpose (vm-app-01-data-01) and tag them, so unattached disks are easy to spot and clean up.