Hello! When working with cloud environments, there are many times when you need to back up a Virtual Machine (VM) or replicate a VM exactly as it is at a specific point in time to create a test environment.
The common method many people use probably goes like this:
- Create a snapshot of the VM disk. πΈ
- Download the snapshot as a VHD file to your local computer. (β³ Takes forever…)
- Upload the downloaded VHD file back to Blob storage. (π© Takes forever again…)
- Create a new disk from the uploaded VHD, and then create a new VM from that disk.
Doesn’t this process seem a bit odd? You’re just moving data from one place in Azure to another, so why does it have to go through your computer? This method is time-consuming, wastes your computer’s network bandwidth and storage space, and has a higher chance of errors occurring in between.
So today! I will show you a very smart way to completely skip this inefficient process and replicate a VM by directly copying a snapshot to a Blob within Azure, along with an Azure CLI script.

π€ Core Principle: Local Transit vs. Direct Azure
If the old method is like taking a plane from Seoul to Busan but detouring via Jeju Island (my computer), the method I’m introducing today is like taking the KTX directly. π
The core is the Azure CLI command `az storage blob copy start`. This command instructs Azure: “Azure, please copy the data yourself from location A (snapshot) to location B (Blob storage)!” The data moves directly through Azure’s fast and stable internal network, without ever touching our computer.
This is called Server-Side Copy, and it offers tremendous advantages:
- β‘οΈ Speed: Incomparably faster than local network speeds.
- π Efficiency: Uses none of your computer’s resources (CPU, network, disk).
- π Stability: Reliably copies large files without worrying about internet disconnections.
π Full Script Revealed!
Seeing is believing, right? Below is the complete Bash script that automates this entire process. Feel free to copy and use it.
#!/bin/bash
# --- User-configurable variables ---
# Please accurately enter the name of the already created resource.
resourceGroup="gasbugs_group" # Resource Group
vmName="gasbugs" # Original Virtual Machine
storageAccount="storageaccountgasbugs0" # Storage account to save VHD
containerName="blob-test" # Container to save VHD
# Set the name of the new resource as desired.
snapshotName="new-snapshot-$(date +%s)" # Snapshot name (timestamp added to prevent duplication)
newDiskName="new-disk-$(date +%s)" # New Disk Name
newVmName="new-vm-$(date +%s)" # New Virtual Machine Name
# --- Script execution ---
echo ">> 1. μλ³Έ VMμ OS λμ€ν¬ IDλ₯Ό κ°μ Έμ΅λλ€..."
osDiskId=$(az vm show --resource-group $resourceGroup --name $vmName --query "storageProfile.osDisk.managedDisk.id" -o tsv)
if [ -z "$osDiskId" ]; then echo "μ€λ₯: OS λμ€ν¬ IDλ₯Ό μ°Ύμ μ μμ΅λλ€."; exit 1; fi
echo " - OS Disk ID: $osDiskId"
echo -e "
>> 2. OS λμ€ν¬μ μ€λ
μ·μ μμ±ν©λλ€..."
az snapshot create --resource-group $resourceGroup --name $snapshotName --source $osDiskId
echo " - μμ±λ μ€λ
μ·: $snapshotName"
echo -e "
>> 3. μ€λ
μ·μ μ κ·Όν μ μλ μμ SAS URLμ μμ±ν©λλ€..."
snapshotUrl=$(az snapshot grant-access --duration-in-seconds 3600 --name $snapshotName --resource-group $resourceGroup --query "accessSas" -o tsv)
echo " - SAS URLμ΄ μ±κ³΅μ μΌλ‘ μμ±λμμ΅λλ€."
echo -e "
>> 4. μ€λ
μ·μ Blob Storageλ‘ μλ² μΈ‘ 볡μ¬λ₯Ό μμν©λλ€ (λ‘컬 λ€μ΄λ‘λ μμ)..."
# Full URL of the Blob to copy
sharedVhdUrl="https://$storageAccount.blob.core.windows.net/$containerName/$snapshotName.vhd"
az storage blob copy start
--account-name $storageAccount
--destination-blob "$snapshotName.vhd"
--destination-container $containerName
--source-uri $snapshotUrl
# Check status until copy is complete.
while true; do
copy_status=$(az storage blob show --account-name $storageAccount --container-name $containerName --name "$snapshotName.vhd" --query "properties.copy.status" -o tsv)
echo " - λ³΅μ¬ μν: $copy_status"
if [ "$copy_status" == "success" ]; then
echo " - Blob 볡μ¬κ° μλ£λμμ΅λλ€."
break
elif [ "$copy_status" == "failed" ]; then
echo "μ€λ₯: Blob 볡μ¬μ μ€ν¨νμ΅λλ€."
exit 1
fi
sleep 15
done
echo -e "
>> 5. μ€λ
μ·μ SAS URL μ κ·Ό κΆνμ ν΄μ ν©λλ€..."
az snapshot revoke-access --name $snapshotName --resource-group $resourceGroup
echo -e "
>> 6. 볡μ¬λ VHD Blobμ μμ€λ‘ νμ¬ μ κ΄λ¦¬ λμ€ν¬λ₯Ό μμ±ν©λλ€..."
az disk create --resource-group $resourceGroup --name $newDiskName --source $sharedVhdUrl
echo " - μμ±λ λμ€ν¬: $newDiskName"
echo -e "
>> 7. μμ±λ λμ€ν¬λ₯Ό μ¬μ©νμ¬ μ κ°μ λ¨Έμ μ μμ±ν©λλ€..."
az vm create --resource-group $resourceGroup --name $newVmName --attach-os-disk $newDiskName --os-type Linux --public-ip-address "" # Create without Public IP
echo " - μμ±λ VM: $newVmName"
echo -e "
β
λͺ¨λ μμ
μ΄ μ±κ³΅μ μΌλ‘ μλ£λμμ΅λλ€."
###
π¬ Detailed Script Analysis
Let’s take a closer look at how the script works, step by step.
Step 1: Variable Configuration βοΈ
At the top of the script, you configure basic information such as the target VM to replicate, resource group, and storage account to save the VHD. To prevent name conflicts when running the script multiple times, `$(date +%s)` is appended to the new resource names to create unique names based on the current time.
Step 2: Snapshot Creation πΈ
After getting the OS disk ID of the source VM with `az vm show`, a point-in-time copy of the disk, i.e., a snapshot, is created using the `az snapshot create` command.
Step 3: SAS URL Generation π
`az snapshot grant-access` plays a crucial role. It creates a URL containing a temporary secret key that allows access to the created snapshot data for exactly 1 hour (3600 seconds), which is a SAS (Shared Access Signature) URL. This URL becomes our data’s ‘direct ticket’.
Step 4: Server-Side Copy and Status Check βοΈβ‘οΈβοΈ
This is the highlight of the script! The `az storage blob copy start` command is given the newly created SAS URL as `–source-uri` and the target Blob information as `–destination-blob`, etc.
As soon as the command is executed, Azure starts copying in the background. But we need to wait until the copy is finished to proceed with the next tasks, right? So, a `while` loop is used to check the copy status every 15 seconds with the `az storage blob show` command. When the status changes to ‘success’, the loop is exited, and the script moves to the next step. Pretty smart, isn’t it?
Steps 5-7: Revoke Access and Resource Creation ποΈ
Once the copy is complete, for security, the SAS URL is immediately revoked using `az snapshot revoke-access`. Now, using the URL of the VHD file safely stored in Blob storage as the source, `az disk create` is executed to create a new managed disk. Finally, using this disk as the OS disk, `az vm create` is used to create the final replicated VM, completing the entire process!
β¨ Concluding Remarks
No more wasting time downloading and uploading VHD files locally every time you replicate or back up a VM. By utilizing the server-side copy method learned today, you can automate the entire process quickly and reliably with just one Azure CLI script execution.
How about using this script to create your own VM backup system or to quickly set up development/test environments?
Tags: Azure, VM, Virtual Machine, Snapshot, Blob, Storage, Azure CLI, Bash, Script, DevOps, IaC, Cloud, IT
Leave a Reply