如何通过PowerShell在Azure订阅间复制捕获镜像(无需创建VM)
当然可以搞定!不用折腾创建VM,就能跨Azure订阅复制你捕获的镜像,我给你整理了两套PowerShell方案,步骤清晰,你跟着来就行:
前提准备
- 确保你安装了最新版的Az PowerShell模块(没装的话跑这个命令:
Install-Module -Name Az -AllowClobber -Scope CurrentUser) - 拥有源订阅和目标订阅的参与者或更高权限
- 提前在目标订阅建好一个资源组,要是用VHD导出法的话还得准备好存储账户(和源镜像同区域最佳)
方法一:利用快照中转(推荐,步骤更高效)
这种方法是先给源镜像的底层托管磁盘打快照,把快照复制到目标订阅,最后从快照生成新的自定义镜像,全程不用导出VHD。
步骤1:登录Azure并切换到源订阅
# 登录Azure账户 Connect-AzAccount # 替换成你的源订阅ID $sourceSubscriptionId = "xxxx-xxxx-xxxx-xxxx" Set-AzContext -Subscription $sourceSubscriptionId
步骤2:获取源镜像的底层磁盘ID
# 替换成你的源镜像名称和资源组 $sourceImageName = "你的捕获镜像名称" $sourceResourceGroupName = "源资源组名称" $sourceImage = Get-AzImage -ResourceGroupName $sourceResourceGroupName -ImageName $sourceImageName $sourceDiskId = $sourceImage.StorageProfile.OsDisk.ManagedDisk.Id
步骤3:在源订阅创建磁盘快照
# 自动生成带时间戳的快照名称,避免重复 $snapshotName = "ImageSnapshot-$(Get-Date -Format 'yyyyMMddHHmmss')" $snapshotResourceGroupName = $sourceResourceGroupName # 创建快照配置并生成快照 $snapshotConfig = New-AzSnapshotConfig -SourceUri $sourceDiskId -Location $sourceImage.Location -CreateOption Copy New-AzSnapshot -Snapshot $snapshotConfig -SnapshotName $snapshotName -ResourceGroupName $snapshotResourceGroupName
步骤4:把快照复制到目标订阅
# 切换到目标订阅 $targetSubscriptionId = "yyyy-yyyy-yyyy-yyyy" Set-AzContext -Subscription $targetSubscriptionId # 替换成你的目标资源组名称(提前建好) $targetResourceGroupName = "目标资源组名称" # 切回源订阅获取快照对象 Set-AzContext -Subscription $sourceSubscriptionId $snapshot = Get-AzSnapshot -ResourceGroupName $snapshotResourceGroupName -SnapshotName $snapshotName # 复制快照到目标订阅 $targetSnapshotName = $snapshotName New-AzSnapshot -ResourceGroupName $targetResourceGroupName -SnapshotName $targetSnapshotName -Location $snapshot.Location -CreateOption Copy -SourceResourceId $snapshot.Id
步骤5:在目标订阅从快照生成自定义镜像
# 切回目标订阅 Set-AzContext -Subscription $targetSubscriptionId # 自动生成带时间戳的目标镜像名称 $targetImageName = "Copied-Image-$(Get-Date -Format 'yyyyMMddHHmmss')" # 先从快照创建临时托管磁盘 $diskConfig = New-AzDiskConfig -Location $snapshot.Location -CreateOption Copy -SourceResourceId (Get-AzSnapshot -ResourceGroupName $targetResourceGroupName -SnapshotName $targetSnapshotName).Id $managedDisk = New-AzDisk -Disk $diskConfig -ResourceGroupName $targetResourceGroupName -DiskName "Temp-Disk-For-Image" # 基于临时磁盘创建自定义镜像 $imageConfig = New-AzImageConfig -Location $snapshot.Location # 如果是Linux镜像,把Windows改成Linux Set-AzImageOsDisk -Image $imageConfig -OsType Windows -OsState Generalized -ManagedDiskId $managedDisk.Id New-AzImage -Image $imageConfig -ImageName $targetImageName -ResourceGroupName $targetResourceGroupName # 可选:删除临时磁盘节省成本 Remove-AzDisk -ResourceGroupName $targetResourceGroupName -DiskName "Temp-Disk-For-Image" -Force
方法二:导出镜像到VHD再导入(适合需要保留VHD备份的场景)
如果需要把VHD单独备份,或者跨区域复制(可以先导出到源区域存储,再复制到目标区域),可以用这套方案。
步骤1:登录并获取源镜像信息
Connect-AzAccount $sourceSubscriptionId = "xxxx-xxxx-xxxx-xxxx" Set-AzContext -Subscription $sourceSubscriptionId $sourceImageName = "你的捕获镜像名称" $sourceResourceGroupName = "源资源组名称" $sourceImage = Get-AzImage -ResourceGroupName $sourceResourceGroupName -ImageName $sourceImageName
步骤2:生成镜像磁盘的SAS访问链接
# 替换成你的源存储账户信息(和镜像同区域) $sourceStorageAccountName = "源存储账户名称" $sourceStorageResourceGroupName = "源存储账户所在资源组" $containerName = "vhds" # 获取存储账户上下文 $storageAccount = Get-AzStorageAccount -ResourceGroupName $sourceStorageResourceGroupName -Name $sourceStorageAccountName $context = $storageAccount.Context # 创建存储容器(如果不存在) if (-not (Get-AzStorageContainer -Name $containerName -Context $context -ErrorAction SilentlyContinue)) { New-AzStorageContainer -Name $containerName -Context $context -Permission Blob } # 生成有效期24小时的SAS链接 $sasUri = Grant-AzDiskAccess -ResourceGroupName $sourceResourceGroupName -DiskId $sourceImage.StorageProfile.OsDisk.ManagedDisk.Id -DurationInSecond (New-TimeSpan -Hours 24).TotalSeconds -Access Read
步骤3:把VHD复制到目标订阅的存储账户
# 切换到目标订阅 $targetSubscriptionId = "yyyy-yyyy-yyyy-yyyy" Set-AzContext -Subscription $targetSubscriptionId # 替换成你的目标存储账户信息 $targetStorageAccountName = "目标存储账户名称" $targetStorageResourceGroupName = "目标存储账户所在资源组" $targetContainerName = "vhds" $targetStorageAccount = Get-AzStorageAccount -ResourceGroupName $targetStorageResourceGroupName -Name $targetStorageAccountName $targetContext = $targetStorageAccount.Context # 创建目标容器(如果不存在) if (-not (Get-AzStorageContainer -Name $targetContainerName -Context $targetContext -ErrorAction SilentlyContinue)) { New-AzStorageContainer -Name $targetContainerName -Context $targetContext -Permission Blob } # 启动VHD复制 $targetVhdName = "Copied-Image.vhd" Start-AzStorageBlobCopy -AbsoluteUri $sasUri.AccessSAS -DestContainer $targetContainerName -DestBlob $targetVhdName -DestContext $targetContext # 等待复制完成(每30秒检查一次状态) while ((Get-AzStorageBlobCopyState -Container $targetContainerName -Blob $targetVhdName -Context $targetContext).Status -eq "Pending") { Write-Host "VHD复制中,请稍等..." Start-Sleep -Seconds 30 } Write-Host "VHD复制完成!"
步骤4:在目标订阅从VHD创建自定义镜像
# 获取目标VHD的访问链接 $targetVhdUri = (Get-AzStorageBlob -Container $targetContainerName -Blob $targetVhdName -Context $targetContext).ICloudBlob.Uri.AbsoluteUri # 创建镜像配置 $imageConfig = New-AzImageConfig -Location $sourceImage.Location # Linux镜像记得改成OsType Linux Set-AzImageOsDisk -Image $imageConfig -OsType Windows -OsState Generalized -BlobUri $targetVhdUri # 生成自定义镜像 $targetImageName = "Imported-Image-$(Get-Date -Format 'yyyyMMddHHmmss')" $targetResourceGroupName = "目标资源组名称" New-AzImage -Image $imageConfig -ImageName $targetImageName -ResourceGroupName $targetResourceGroupName
注意事项
- 所有占位符(订阅ID、资源组名称、镜像名称等)记得替换成你的实际信息
- 如果是Linux镜像,把所有
-OsType Windows改成-OsType Linux - 快照和VHD复制默认要求源和目标资源在同一区域,如果需要跨区域,复制快照时可以指定
-Location参数为目标区域 - 操作完成后,记得删除源订阅的快照、临时VHD等冗余资源,避免不必要的成本
内容的提问来源于stack exchange,提问作者luckygiri
相关产品推荐
相关产品推荐

