为 download/export 减小 Azure VM OS 磁盘的大小
Reducing size of Azure VM OS Disk for download/export
我想用 OS 比默认 127gb 小的磁盘创建 Azure VM。我一直无法在 Azure 门户中找到这样的选项,因此我尝试缩小磁盘。我还没有成功。
我知道我可以 trim(使用碎片整理工具)并缩小卷(使用磁盘管理),但这不会改变硬盘的 "physical" 大小。也就是说,如果我将磁盘缩小到 40gb,将只有 87gb 未分配,而 blob 仍将报告 127gb。
我试图实现的是缩小 blob 以匹配分配的 space 以促进更小的 downloads/exports VM 映像(例如 40 vs 127gb)。
感谢任何帮助。
您必须创建自己的 VM 映像,然后使用它进行部署。此模板向您展示了如何使用您自己的映像进行部署。
https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-from-user-image
目前图库中的图片都是127gb。由于 Azure VM 仅使用固定大小的光盘,因此您不能只 select 大小。
我写了一篇博客 post 详细说明了这个答案。但这里的主要问题是能够减小默认为 127gb 的 Azure VM 的大小,以允许禁食 export/download。我实现此目的的方法是修整硬盘,然后使用 Disk2VHD 创建 运行 VM 的 VHD 文件。 Disk2VHD 将创建一个可扩展磁盘,该磁盘仅与磁盘上的当前数据一样大,而不是整个可用磁盘。在我的例子中是 40gb 和 127gb。如果将此 VHD 文件保存到附加磁盘(读取:blob 存储),您的整个团队都可以通过 HTTP 轻松下载它。因此,下载现在是 40gbs 而不是 127gbs。更多请看我的详细博文post:
http://www.kevinmcloutier.com/?p=263
原来的link不再有效:
https://web.archive.org/web/20161027213258/http://kevinmcloutier.com/post/4
在 Azure 中,如果您创建 VM,它将使用一些默认配置创建。目前不支持从 Azure 门户 reduce/shrink OS Azure VM 的磁盘(托管或非托管)大小(例如从 128Gb 到 32Gb),使用以下过程我们可以存档并降低磁盘成本。
步骤 1. 打开您的 VM 并转到磁盘管理。
步骤 2. 打开 PowerShell 并执行以下命令。
执行成功后可以看到如下内容
第 3 步。现在从 Azure 门户解除分配 VM
第 4 步。现在转到磁盘的属性边栏选项卡并复制资源 ID
第 5 步。现在从您的本地系统执行以下 PowerShell 脚本。必须用您的值更改 $DiskID、$VMName、$AzSubscription
# Variables
$DiskID = ""# eg. "/subscriptions/203bdbf0-69bd-1a12-a894-a826cf0a34c8/resourcegroups/rg-server1-prod-1/providers/Microsoft.Compute/disks/Server1-Server1"
$VMName = "VM-Server1"
$DiskSizeGB = 32
$AzSubscription = "Prod Subscription"
# Script
# Provide your Azure admin credentials
Connect-AzAccount
#Provide the subscription Id of the subscription where snapshot is created
Select-AzSubscription -Subscription $AzSubscription
# VM to resize disk of
$VM = Get-AzVm | ? Name -eq $VMName
#Provide the name of your resource group where snapshot is created
$resourceGroupName = $VM.ResourceGroupName
# Get Disk from ID
$Disk = Get-AzDisk | ? Id -eq $DiskID
# Get VM/Disk generation from Disk
$HyperVGen = $Disk.HyperVGeneration
# Get Disk Name from Disk
$DiskName = $Disk.Name
# Get SAS URI for the Managed disk
$SAS = Grant-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $DiskName -Access 'Read' -DurationInSecond 600000;
#Provide the managed disk name
#$managedDiskName = "yourManagedDiskName"
#Provide Shared Access Signature (SAS) expiry duration in seconds e.g. 3600.
#$sasExpiryDuration = "3600"
#Provide storage account name where you want to copy the snapshot - the script will create a new one temporarily
$storageAccountName = "shrink" + [system.guid]::NewGuid().tostring().replace('-','').substring(1,18)
#Name of the storage container where the downloaded snapshot will be stored
$storageContainerName = $storageAccountName
#Provide the key of the storage account where you want to copy snapshot.
#$storageAccountKey = "yourStorageAccountKey"
#Provide the name of the VHD file to which snapshot will be copied.
$destinationVHDFileName = "$($VM.StorageProfile.OsDisk.Name).vhd"
#Generate the SAS for the managed disk
#$sas = Grant-AzureRmDiskAccess -ResourceGroupName $resourceGroupName -DiskName $managedDiskName -Access Read -DurationInSecond $sasExpiryDuration
#Create the context for the storage account which will be used to copy snapshot to the storage account
$StorageAccount = New-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName -SkuName Standard_LRS -Location $VM.Location
$destinationContext = $StorageAccount.Context
$container = New-AzStorageContainer -Name $storageContainerName -Permission Off -Context $destinationContext
#Copy the snapshot to the storage account and wait for it to complete
Start-AzStorageBlobCopy -AbsoluteUri $SAS.AccessSAS -DestContainer $storageContainerName -DestBlob $destinationVHDFileName -DestContext $destinationContext
while(($state = Get-AzStorageBlobCopyState -Context $destinationContext -Blob $destinationVHDFileName -Container $storageContainerName).Status -ne "Success") { $state; Start-Sleep -Seconds 20 }
$state
# Revoke SAS token
Revoke-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $DiskName
# Emtpy disk to get footer from
$emptydiskforfootername = "$($VM.StorageProfile.OsDisk.Name)-empty.vhd"
# Empty disk URI
#$EmptyDiskURI = $container.CloudBlobContainer.Uri.AbsoluteUri + "/" + $emptydiskforfooter
$diskConfig = New-AzDiskConfig `
-Location $VM.Location `
-CreateOption Empty `
-DiskSizeGB $DiskSizeGB `
-HyperVGeneration $HyperVGen
$dataDisk = New-AzDisk `
-ResourceGroupName $resourceGroupName `
-DiskName $emptydiskforfootername `
-Disk $diskConfig
$VM = Add-AzVMDataDisk `
-VM $VM `
-Name $emptydiskforfootername `
-CreateOption Attach `
-ManagedDiskId $dataDisk.Id `
-Lun 63
Update-AzVM -ResourceGroupName $resourceGroupName -VM $VM
$VM | Stop-AzVM -Force
# Get SAS token for the empty disk
$SAS = Grant-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $emptydiskforfootername -Access 'Read' -DurationInSecond 600000;
# Copy the empty disk to blob storage
Start-AzStorageBlobCopy -AbsoluteUri $SAS.AccessSAS -DestContainer $storageContainerName -DestBlob $emptydiskforfootername -DestContext $destinationContext
while(($state = Get-AzStorageBlobCopyState -Context $destinationContext -Blob $emptydiskforfootername -Container $storageContainerName).Status -ne "Success") { $state; Start-Sleep -Seconds 20 }
$state
# Revoke SAS token
Revoke-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $emptydiskforfootername
# Remove temp empty disk
Remove-AzVMDataDisk -VM $VM -DataDiskNames $emptydiskforfootername
Update-AzVM -ResourceGroupName $resourceGroupName -VM $VM
# Delete temp disk
Remove-AzDisk -ResourceGroupName $resourceGroupName -DiskName $emptydiskforfootername -Force;
# Get the blobs
$emptyDiskblob = Get-AzStorageBlob -Context $destinationContext -Container $storageContainerName -Blob $emptydiskforfootername
$osdisk = Get-AzStorageBlob -Context $destinationContext -Container $storageContainerName -Blob $destinationVHDFileName
$footer = New-Object -TypeName byte[] -ArgumentList 512
write-output "Get footer of empty disk"
$downloaded = $emptyDiskblob.ICloudBlob.DownloadRangeToByteArray($footer, 0, $emptyDiskblob.Length - 512, 512)
$osDisk.ICloudBlob.Resize($emptyDiskblob.Length)
$footerStream = New-Object -TypeName System.IO.MemoryStream -ArgumentList (,$footer)
write-output "Write footer of empty disk to OSDisk"
$osDisk.ICloudBlob.WritePages($footerStream, $emptyDiskblob.Length - 512)
Write-Output -InputObject "Removing empty disk blobs"
$emptyDiskblob | Remove-AzStorageBlob -Force
#Provide the name of the Managed Disk
$NewDiskName = "$DiskName" + "-new"
#Create the new disk with the same SKU as the current one
$accountType = $Disk.Sku.Name
# Get the new disk URI
$vhdUri = $osdisk.ICloudBlob.Uri.AbsoluteUri
# Specify the disk options
$diskConfig = New-AzDiskConfig -AccountType $accountType -Location $VM.location -DiskSizeGB $DiskSizeGB -SourceUri $vhdUri -CreateOption Import -StorageAccountId $StorageAccount.Id -HyperVGeneration $HyperVGen
#Create Managed disk
$NewManagedDisk = New-AzDisk -DiskName $NewDiskName -Disk $diskConfig -ResourceGroupName $resourceGroupName
$VM | Stop-AzVM -Force
# Set the VM configuration to point to the new disk
Set-AzVMOSDisk -VM $VM -ManagedDiskId $NewManagedDisk.Id -Name $NewManagedDisk.Name
# Update the VM with the new OS disk
Update-AzVM -ResourceGroupName $resourceGroupName -VM $VM
$VM | Start-AzVM
start-sleep 180
# Please check the VM is running before proceeding with the below tidy-up steps
# Delete old Managed Disk
Remove-AzDisk -ResourceGroupName $resourceGroupName -DiskName $DiskName -Force;
# Delete old blob storage
$osdisk | Remove-AzStorageBlob -Force
# Delete temp storage account
$StorageAccount | Remove-AzStorageAccount -Force
Sapnandu 的解决方案有效。非常感谢!
我仍然不是 100% 确定让它工作的神奇标准是什么,但最后我有一个 vm 运行 减少的磁盘。让它成为 Gen1 绝对是其中之一。
我尝试了很多类似的东西,但它们都在启动时卡住了。
我的方法是:
从图库图像创建虚拟机。您将拥有一个 128Gb OS 磁盘。
根据需要调整虚拟机。您可以在此处 运行 调整大小脚本。所以,你最终会得到 ~90Gb 未分配的 space.
经过几次失败的尝试后,我开始重视配置的虚拟机,我真的不想再次重复配置。
制作此磁盘的快照,然后从快照制作磁盘。这些选项将通过快照和磁盘呈现给您。
然后从磁盘创建一个新的虚拟机。检查它是否启动。启动诊断显示它相当快。
停止新虚拟机后,我查找了 Sapnandu 脚本所需的 3 个(subscriptionID、diskID、vmName)参数(在他的 post 中的第 5 步)并在 azure cloud shell. (header中的图标)
需要时间,大概10分钟左右。
当脚本完成时,新虚拟机是 运行 较小的磁盘。
所以,有一个 vm 设置,脚本可以完美运行。
我想用 OS 比默认 127gb 小的磁盘创建 Azure VM。我一直无法在 Azure 门户中找到这样的选项,因此我尝试缩小磁盘。我还没有成功。
我知道我可以 trim(使用碎片整理工具)并缩小卷(使用磁盘管理),但这不会改变硬盘的 "physical" 大小。也就是说,如果我将磁盘缩小到 40gb,将只有 87gb 未分配,而 blob 仍将报告 127gb。
我试图实现的是缩小 blob 以匹配分配的 space 以促进更小的 downloads/exports VM 映像(例如 40 vs 127gb)。
感谢任何帮助。
您必须创建自己的 VM 映像,然后使用它进行部署。此模板向您展示了如何使用您自己的映像进行部署。
https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-from-user-image
目前图库中的图片都是127gb。由于 Azure VM 仅使用固定大小的光盘,因此您不能只 select 大小。
我写了一篇博客 post 详细说明了这个答案。但这里的主要问题是能够减小默认为 127gb 的 Azure VM 的大小,以允许禁食 export/download。我实现此目的的方法是修整硬盘,然后使用 Disk2VHD 创建 运行 VM 的 VHD 文件。 Disk2VHD 将创建一个可扩展磁盘,该磁盘仅与磁盘上的当前数据一样大,而不是整个可用磁盘。在我的例子中是 40gb 和 127gb。如果将此 VHD 文件保存到附加磁盘(读取:blob 存储),您的整个团队都可以通过 HTTP 轻松下载它。因此,下载现在是 40gbs 而不是 127gbs。更多请看我的详细博文post:
http://www.kevinmcloutier.com/?p=263
原来的link不再有效: https://web.archive.org/web/20161027213258/http://kevinmcloutier.com/post/4
在 Azure 中,如果您创建 VM,它将使用一些默认配置创建。目前不支持从 Azure 门户 reduce/shrink OS Azure VM 的磁盘(托管或非托管)大小(例如从 128Gb 到 32Gb),使用以下过程我们可以存档并降低磁盘成本。
步骤 1. 打开您的 VM 并转到磁盘管理。
步骤 2. 打开 PowerShell 并执行以下命令。
执行成功后可以看到如下内容
第 3 步。现在从 Azure 门户解除分配 VM
第 4 步。现在转到磁盘的属性边栏选项卡并复制资源 ID
第 5 步。现在从您的本地系统执行以下 PowerShell 脚本。必须用您的值更改 $DiskID、$VMName、$AzSubscription
# Variables
$DiskID = ""# eg. "/subscriptions/203bdbf0-69bd-1a12-a894-a826cf0a34c8/resourcegroups/rg-server1-prod-1/providers/Microsoft.Compute/disks/Server1-Server1"
$VMName = "VM-Server1"
$DiskSizeGB = 32
$AzSubscription = "Prod Subscription"
# Script
# Provide your Azure admin credentials
Connect-AzAccount
#Provide the subscription Id of the subscription where snapshot is created
Select-AzSubscription -Subscription $AzSubscription
# VM to resize disk of
$VM = Get-AzVm | ? Name -eq $VMName
#Provide the name of your resource group where snapshot is created
$resourceGroupName = $VM.ResourceGroupName
# Get Disk from ID
$Disk = Get-AzDisk | ? Id -eq $DiskID
# Get VM/Disk generation from Disk
$HyperVGen = $Disk.HyperVGeneration
# Get Disk Name from Disk
$DiskName = $Disk.Name
# Get SAS URI for the Managed disk
$SAS = Grant-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $DiskName -Access 'Read' -DurationInSecond 600000;
#Provide the managed disk name
#$managedDiskName = "yourManagedDiskName"
#Provide Shared Access Signature (SAS) expiry duration in seconds e.g. 3600.
#$sasExpiryDuration = "3600"
#Provide storage account name where you want to copy the snapshot - the script will create a new one temporarily
$storageAccountName = "shrink" + [system.guid]::NewGuid().tostring().replace('-','').substring(1,18)
#Name of the storage container where the downloaded snapshot will be stored
$storageContainerName = $storageAccountName
#Provide the key of the storage account where you want to copy snapshot.
#$storageAccountKey = "yourStorageAccountKey"
#Provide the name of the VHD file to which snapshot will be copied.
$destinationVHDFileName = "$($VM.StorageProfile.OsDisk.Name).vhd"
#Generate the SAS for the managed disk
#$sas = Grant-AzureRmDiskAccess -ResourceGroupName $resourceGroupName -DiskName $managedDiskName -Access Read -DurationInSecond $sasExpiryDuration
#Create the context for the storage account which will be used to copy snapshot to the storage account
$StorageAccount = New-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName -SkuName Standard_LRS -Location $VM.Location
$destinationContext = $StorageAccount.Context
$container = New-AzStorageContainer -Name $storageContainerName -Permission Off -Context $destinationContext
#Copy the snapshot to the storage account and wait for it to complete
Start-AzStorageBlobCopy -AbsoluteUri $SAS.AccessSAS -DestContainer $storageContainerName -DestBlob $destinationVHDFileName -DestContext $destinationContext
while(($state = Get-AzStorageBlobCopyState -Context $destinationContext -Blob $destinationVHDFileName -Container $storageContainerName).Status -ne "Success") { $state; Start-Sleep -Seconds 20 }
$state
# Revoke SAS token
Revoke-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $DiskName
# Emtpy disk to get footer from
$emptydiskforfootername = "$($VM.StorageProfile.OsDisk.Name)-empty.vhd"
# Empty disk URI
#$EmptyDiskURI = $container.CloudBlobContainer.Uri.AbsoluteUri + "/" + $emptydiskforfooter
$diskConfig = New-AzDiskConfig `
-Location $VM.Location `
-CreateOption Empty `
-DiskSizeGB $DiskSizeGB `
-HyperVGeneration $HyperVGen
$dataDisk = New-AzDisk `
-ResourceGroupName $resourceGroupName `
-DiskName $emptydiskforfootername `
-Disk $diskConfig
$VM = Add-AzVMDataDisk `
-VM $VM `
-Name $emptydiskforfootername `
-CreateOption Attach `
-ManagedDiskId $dataDisk.Id `
-Lun 63
Update-AzVM -ResourceGroupName $resourceGroupName -VM $VM
$VM | Stop-AzVM -Force
# Get SAS token for the empty disk
$SAS = Grant-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $emptydiskforfootername -Access 'Read' -DurationInSecond 600000;
# Copy the empty disk to blob storage
Start-AzStorageBlobCopy -AbsoluteUri $SAS.AccessSAS -DestContainer $storageContainerName -DestBlob $emptydiskforfootername -DestContext $destinationContext
while(($state = Get-AzStorageBlobCopyState -Context $destinationContext -Blob $emptydiskforfootername -Container $storageContainerName).Status -ne "Success") { $state; Start-Sleep -Seconds 20 }
$state
# Revoke SAS token
Revoke-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $emptydiskforfootername
# Remove temp empty disk
Remove-AzVMDataDisk -VM $VM -DataDiskNames $emptydiskforfootername
Update-AzVM -ResourceGroupName $resourceGroupName -VM $VM
# Delete temp disk
Remove-AzDisk -ResourceGroupName $resourceGroupName -DiskName $emptydiskforfootername -Force;
# Get the blobs
$emptyDiskblob = Get-AzStorageBlob -Context $destinationContext -Container $storageContainerName -Blob $emptydiskforfootername
$osdisk = Get-AzStorageBlob -Context $destinationContext -Container $storageContainerName -Blob $destinationVHDFileName
$footer = New-Object -TypeName byte[] -ArgumentList 512
write-output "Get footer of empty disk"
$downloaded = $emptyDiskblob.ICloudBlob.DownloadRangeToByteArray($footer, 0, $emptyDiskblob.Length - 512, 512)
$osDisk.ICloudBlob.Resize($emptyDiskblob.Length)
$footerStream = New-Object -TypeName System.IO.MemoryStream -ArgumentList (,$footer)
write-output "Write footer of empty disk to OSDisk"
$osDisk.ICloudBlob.WritePages($footerStream, $emptyDiskblob.Length - 512)
Write-Output -InputObject "Removing empty disk blobs"
$emptyDiskblob | Remove-AzStorageBlob -Force
#Provide the name of the Managed Disk
$NewDiskName = "$DiskName" + "-new"
#Create the new disk with the same SKU as the current one
$accountType = $Disk.Sku.Name
# Get the new disk URI
$vhdUri = $osdisk.ICloudBlob.Uri.AbsoluteUri
# Specify the disk options
$diskConfig = New-AzDiskConfig -AccountType $accountType -Location $VM.location -DiskSizeGB $DiskSizeGB -SourceUri $vhdUri -CreateOption Import -StorageAccountId $StorageAccount.Id -HyperVGeneration $HyperVGen
#Create Managed disk
$NewManagedDisk = New-AzDisk -DiskName $NewDiskName -Disk $diskConfig -ResourceGroupName $resourceGroupName
$VM | Stop-AzVM -Force
# Set the VM configuration to point to the new disk
Set-AzVMOSDisk -VM $VM -ManagedDiskId $NewManagedDisk.Id -Name $NewManagedDisk.Name
# Update the VM with the new OS disk
Update-AzVM -ResourceGroupName $resourceGroupName -VM $VM
$VM | Start-AzVM
start-sleep 180
# Please check the VM is running before proceeding with the below tidy-up steps
# Delete old Managed Disk
Remove-AzDisk -ResourceGroupName $resourceGroupName -DiskName $DiskName -Force;
# Delete old blob storage
$osdisk | Remove-AzStorageBlob -Force
# Delete temp storage account
$StorageAccount | Remove-AzStorageAccount -Force
Sapnandu 的解决方案有效。非常感谢! 我仍然不是 100% 确定让它工作的神奇标准是什么,但最后我有一个 vm 运行 减少的磁盘。让它成为 Gen1 绝对是其中之一。 我尝试了很多类似的东西,但它们都在启动时卡住了。
我的方法是:
从图库图像创建虚拟机。您将拥有一个 128Gb OS 磁盘。
根据需要调整虚拟机。您可以在此处 运行 调整大小脚本。所以,你最终会得到 ~90Gb 未分配的 space.
经过几次失败的尝试后,我开始重视配置的虚拟机,我真的不想再次重复配置。
制作此磁盘的快照,然后从快照制作磁盘。这些选项将通过快照和磁盘呈现给您。
然后从磁盘创建一个新的虚拟机。检查它是否启动。启动诊断显示它相当快。
停止新虚拟机后,我查找了 Sapnandu 脚本所需的 3 个(subscriptionID、diskID、vmName)参数(在他的 post 中的第 5 步)并在 azure cloud shell. (header中的图标)
需要时间,大概10分钟左右。 当脚本完成时,新虚拟机是 运行 较小的磁盘。
所以,有一个 vm 设置,脚本可以完美运行。