减少用于下载/导出的 Azure VM OS 磁盘的大小

问题描述 投票:0回答:4

我想创建一个操作系统磁盘小于默认 127GB 的 Azure VM。我在Azure门户中找不到这样的选项,所以我尝试缩小磁盘。我还没有成功。

我知道我可以修剪(使用碎片整理工具)并缩小卷(使用磁盘管理),但这不会改变硬盘的“物理”大小。也就是说,如果我将磁盘缩小到 40GB,则只有 87GB 未分配,而 Blob 仍会报告 127GB。

我试图实现的是缩小 blob 以匹配分配的空间,从而促进更小的 VM 映像下载/导出(例如 40 与 127gb)。

感谢任何和所有帮助。

azure azure-blob-storage azure-virtual-machine
4个回答
5
投票

在 Azure 中,如果您创建 VM,它将使用某些默认配置进行创建。目前,不支持从 Azure 门户减少/缩小 Azure VM 的操作系统磁盘(托管或非托管)大小(例如从 128Gb 到 32Gb),我们可以使用以下过程对其进行存档,并减少磁盘成本。

步骤 1. 打开虚拟机并转到磁盘管理。 enter image description here

步骤2.打开PowerShell并执行以下命令。 enter image description here

执行成功后可以发现如下 enter image description here

步骤 3. 现在从 Azure 门户取消分配 VM enter image description here

步骤 4. 现在转到磁盘的“属性”边栏选项卡并复制资源 ID enter image description here

步骤 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

4
投票

我已经写了一篇博客文章,详细介绍了这个答案。但这里的主要问题是能够减小 Azure VM 的大小(默认为 127GB),以便实现快速导出/下载。我实现此目的的方法是修剪硬盘驱动器,然后使用 Disk2VHD 创建正在运行的虚拟机的 VHD 文件。 Disk2VHD 将创建一个可扩展磁盘,其大小仅与磁盘上的当前数据一样大,而不是整个可用磁盘。就我而言,40GB vs 127GB。如果将此 VHD 文件保存到附加磁盘(读取:blob 存储),您的整个团队就可以通过 HTTP 轻松下载它。因此,下载量现在为 40GB,而不是 127GB。欲了解更多,请阅读我的详细博文:

http://www.kevinmcloutier.com/?p=263

原始链接不再有效: https://web.archive.org/web/20161027213258/http://kevinmcloutier.com/post/4


1
投票

您必须创建自己的虚拟机映像,然后使用该映像进行部署。此模板向您展示如何使用您自己的映像进行部署。

https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-from-user-image

目前图库中的图像均为127GB。由于 Azure VM 仅使用固定大小的光盘,因此您不能只选择大小。


0
投票

我仍然不是 100% 确定让它工作的神奇标准是什么,但最后,我有一个使用减少的磁盘运行的虚拟机。制作第一代就是其中之一。 我尝试了很多类似的事情,但它们都在启动时卡住了。

我的方法是:

  1. 从图库图像创建虚拟机。例如,Windows Server 2019 - 数据中心。您将拥有 128 GB 操作系统磁盘。注意:不要使用“smalldisk”版本,因为它没有 GUI。

  2. 根据您的需要调整虚拟机。您可以在此处运行调整大小脚本。因此,您最终会得到 ~90 GB 未分配空间。

  3. (可选)为此磁盘创建快照,然后从快照创建磁盘。经过几次失败的尝试后,我开始重视已配置的虚拟机,并且不想重复配置。这些选项将通过快照和磁盘呈现给您。

  4. 从磁盘创建一个新的虚拟机。检查是否启动。启动诊断很快就会显示出来。

  5. 停止新 VM 后,查找 Sapnandu 脚本(其帖子中的步骤 5)所需的 3 个参数(subscriptionID、diskID、vmName),并在 Azure Cloud Shell 中执行该脚本。 (标题中的图标)

需要时间,大约10分钟左右。脚本完成后,新虚拟机将使用较小的磁盘运行。

因此,有一个虚拟机设置可以使脚本完美运行。 Sapnandu 的解决方案有效。非常感谢!

© www.soinside.com 2019 - 2024. All rights reserved.