Windows Azure Virtual Machine (31) 迁移Azure虚拟机

简介:

 《Windows Azure Platform 系列文章目录

 

  为什么要写这篇Blog?

  之前遇到过很多客户提问:

  (1)我之前创建的虚拟机,没有加入虚拟网络。现在需要重新加入虚拟机网络,应该如何操作?

  (2)之前创建的虚拟机,想重新设置DNS。但是又想保留虚拟机里面的内容,应该如何操作?

  (3)我之前部署在订阅A下面的一些虚拟机,现在想迁移到订阅B下面,应该如何操作?

  

  在回答这些问题之前,我们先回顾一下Azure虚拟机可能需要的资源:

  (1)虚拟网络(Azure Virtual Network)

  定义Subnet和IP Rang,Azure虚拟机的内网IP地址是由Azure Virtual Network

  (2)云服务(Cloud Service)

  定义了Azure虚拟机的DNS地址

  (3)VHD文件(Virtual Hard Disk)

  我们在虚拟机安装的任何软件和配置,都是持久化保存在Azure VHD文件里的。

  所以只要能保留VHD,就可以迁移Azure虚拟机,同时保留虚拟机里面的内容

 

  好了,看到这里,各位看官明白了,其实我们只要迁移Azure虚拟机所在的VHD文件即可。

  然后还有一个问题请读者注意:

  如果你的Azure VM所在的DNS Name已经固定的公网IP地址(Reserved IP)

  (Azure China (8) 使用Azure PowerShell创建虚拟机,并设置固定Virtual IP Address和Private IP)

 

  我们在迁移Azure虚拟机的时候需要注意,固定公网IP地址只能属于某一个订阅,无法跨订阅,或者是多个订阅共享同一个公网IP地址。

  所以当我们将某一台虚拟机,从订阅A迁移到订阅B的时候,订阅A下的该虚拟机的公网IP地址,是无法转换到订阅B下的。

 

  当我们跨订阅迁移Azure虚拟机的时候,笔者建议的做法是:先将订阅A下的公网IP地址进行释放。然后再订阅B下申请新的公网IP地址。

  如果客户已经设置了自定义域名的A记录,需要重新设置,指向到订阅B下的公网IP地址。

 

  好了,描述了那么多的内容。我们开始今天的文章吧。

  首先笔者先模拟一个场景,假设我们有两个订阅,Subscription_ASubscription_B

  在订阅Subscription_A下有以下部署:

  -  虚拟网络名称VNetA,有一个子网Subnet-1

  -  有1台虚拟机,虚拟机DNS Name为LeiCloudServiceA

  -  该虚拟机的机器名为LeiVMA,操作系统为Windows Server 2012 中文版

  -  这台虚拟机有2块磁盘

 

  我们需要把上述虚拟机,迁移到订阅Subscription_B

  -  手动创建虚拟网络VNetB

  -  新的DNS Name为LeiCloudServiceB,新的虚拟机的机器名为LeiVMB

  -  需要保留原虚拟机里的磁盘内容

 

  关键步骤有以下几点:

  (1)请在Azure PowerShell下运行

  (2)输入源订阅,和目标订阅的Azure用户名和密码

  (3)手动创建目标订阅下的虚拟机网络和子网

  (4)更新PowerShell下的相关参数

  (5)PowerShell会提示:首先把需要迁移的Azure虚拟机关机

  (6)PowerShell会在目标订阅下,创建新的存储账户

  (7)PowerShell会将源订阅的下的,需要迁移的虚拟机的所有VHD文件,拷贝到目标订阅下的,新的存储账号里

  (8)在目标订阅下,将VHD系统文件创建为虚拟机镜像,将VHD数据文件创建为虚拟机磁盘镜像

 

  (9)如果源订阅和目标订阅是同一个订阅的话,会有提示:Please update the Diskname in the configuration file 

  客户手动修改PowerShell同一目录下的,ExportedVMConfig文件,修改以下XML节点:

  <DataVirtualHardDisks>和<OSVirtualHardDisk>

  

  在DiskName里,增加相应的后缀。

  比如$DiskNameSuffix变量,我们赋值为-prem

  则修改上面的红色部分的DiskName,参数增加后缀-prem。如下图:

  

   修改完毕后,直接按Enter 继续执行PowerShell 

 

 

  PowerShell源代码如下:

复制代码
<#
Modified by Lei Zhang on 2016-04-29
#>

Param 
(
    #源订阅ID
    [string] $SourceSubscriptionId="e2eaa986-29d9-48c9-8302-1e2900a4504b",

    #源云服务名称
    [string] $SourceCloudServiceName="lei2012chnvm",

    #源虚拟机名称
    [string] $SourceVMName="lei2012chnvm01",

    #源Azure Storage Container Name
    [string] $SourceStorageContainerName="vhds",

    #目标订阅ID
    [string] $DestSubscritpionId="919ae904-1260-4f4b-85a6-8ac9d44d3106",

    #目标云服务名称
    [string] $DestCloudServiceName="LeiNewVM",

    #目标虚拟机名称
    [string] $DestVMName="LeiNewVM01",

    #目标存储账户名称
    [string] $DestStorageAccountName="leinewvmstorage1",

    #目标Azure Storage Container Name    
    [string] $DestStorageContainerName="vhds",

    #目标虚拟机所在数据中心,分别为China North和China East
    [string] $DestLocationName,

    #目标虚拟机所在虚拟网络名称
    [string] $DestVNetName="LeiDesVNet",

    #目标虚拟机所在子网名称
    [string] $DestSubNet="Subnet-1",

    #目标虚拟机磁盘文件后缀
    [string] $DiskNameSuffix="-prem"
)


$IsSameSub = $false

if (($SourceSubscriptionId -eq $DestSubscritpionId) -or ($DestSubscritpionId -eq ""))
{
    Write-Host "VM is copied at the same subscription!" -ForegroundColor Green
    $IsSameSub = $true
    $DestSubscritpionId = $SourceSubscriptionId
}

if ($SourceStorageContainerName -eq "")
{
    Write-Host "Using the default source storage container vhds!" -ForegroundColor Green
    $SourceStorageContainerName = "vhds"
}

if ($DestStorageContainerName -eq "")
{
    Write-Host "Using the default destination storage container vhds!" -ForegroundColor Green
    $DestStorageContainerName = "vhds"
}

if ($DestLocationName -eq "")
{
    $DestLocationName = "China East"
}

if ($DestSubNet -eq "")
{
    $DestSubNet = "Subnet-1"
}

if (($DiskNameSuffix -eq $null) -or ($DiskNameSuffix -eq ""))
{
    $DiskNameSuffix = "-prem"
    Write-Host "Set the copyed Disk Name Suffix as:"+ $DiskNameSuffix -ForegroundColor Green
}

Write-Host "`t================= Migration Setting =======================" -ForegroundColor Green
Write-Host "`t  Source Subscription ID          = $SourceSubscriptionId           " -ForegroundColor Green
Write-Host "`t Source Cloud Service Name      = $SourceCloudServiceName       " -ForegroundColor Green
Write-Host "`t            Source VM Name      = $SourceVMName                 " -ForegroundColor Green
Write-Host "`t      Dest Subscription ID      = $DestSubscritpionId              " -ForegroundColor Green
Write-Host "`t   Dest Cloud Service Name      = $DestCloudServiceName         " -ForegroundColor Green
Write-Host "`t Dest Storage Account Name      = $DestStorageAccountName       " -ForegroundColor Green
Write-Host "`t Source Storage Container Name = $SourceStorageContainerName   " -ForegroundColor Green
Write-Host "`t Dest Storage Container Name      = $DestStorageContainerName   "   -ForegroundColor Green
Write-Host "`t             Dest Location      = $DestLocationName             " -ForegroundColor Green
Write-Host "`t                 Dest VNET = $DestVNetName                      " -ForegroundColor Green
Write-Host "`t               Dest Subnet = $DestSubNet                           " -ForegroundColor Green
Write-Host "`t               Disk Name Prefix = $DiskNameSuffix              " -ForegroundColor Green
Write-Host "`t===============================================================" -ForegroundColor Green

#######################################################################
#  Verify Azure Source Subscription and Azure Desination Subscription
#######################################################################
Write-Host "Please verify the Source Azure Subscription" -ForegroundColor Green
Add-AzureAccount -Environment AzureChinaCloud

Write-Host "Please verify the Destination Azure Subscription" -ForegroundColor Green
Add-AzureAccount -Environment AzureChinaCloud

$ErrorActionPreference = "Stop"

try{ stop-transcript|out-null }
catch [System.InvalidOperationException] { }

$workingDir = (Get-Location).Path
$log = $workingDir + "\VM-" + $SourceCloudServiceName + "-" + $SourceVMName + ".log"
Start-Transcript -Path $log -Append -Force

Select-AzureSubscription -SubscriptionId $SourceSubscriptionId

#######################################################################
#  Check if the VM is shut down 
#  Stopping the VM is a required step so that the file system is consistent when you do the copy operation. 
#  Azure does not support live migration at this time.. 
#######################################################################
$sourceVM = Get-AzureVM –ServiceName $SourceCloudServiceName –Name $SourceVMName
if ( $sourceVM -eq $null )
{
    Write-Host "[ERROR] - The source VM doesn't exist. Exiting." -ForegroundColor Red
    Exit
}

# check if VM is shut down
if ( $sourceVM.Status -notmatch "Stopped" )
{
    Write-Host "[Warning] - Stopping the VM is a required step so that the file system is consistent when you do the copy operation. Azure does not support live migration at this time. If you’d like to create a VM from a generalized image, sys-prep the Virtual Machine before stopping it." -ForegroundColor Yellow
    $ContinueAnswer = Read-Host "`n`tDo you wish to stop $SourceVMName now? (Y/N)"
    If ($ContinueAnswer -ne "Y") { Write-Host "`n Exiting." -ForegroundColor Red; Exit }
    $sourceVM | Stop-AzureVM  -StayProvisioned

    # wait until the VM is shut down
    $sourceVMStatus = (Get-AzureVM –ServiceName $SourceCloudServiceName –Name $SourceVMName).Status
    while ($sourceVMStatus -notmatch "Stopped") 
    {
        Write-Host "Waiting VM $vmName to shut down, current status is $sourceVMStatus" -ForegroundColor Green
        Sleep -Seconds 5
        $sourceVMStatus = (Get-AzureVM –ServiceName $SourceCloudServiceName –Name $SourceVMName).Status
    } 
}

# exporting the source vm to a configuration file, you can restore the original VM by importing this config file
# see more information for Import-AzureVM
$vmConfigurationPath = $workingDir + "\ExportedVMConfig-" + $SourceCloudServiceName + "-" + $SourceVMName +".xml"
Write-Host "Exporting VM configuration to $vmConfigurationPath" -ForegroundColor Green
$sourceVM | Export-AzureVM -Path $vmConfigurationPath

#######################################################################
#  Copy the vhds of the source vm 
#  You can choose to copy all disks including os and data disks by specifying the
#  parameter -DataDiskOnly to be $false. The default is to copy only data disk vhds
#  and the new VM will boot from the original os disk. 
#######################################################################

$sourceOSDisk = $sourceVM.VM.OSVirtualHardDisk
$sourceDataDisks = $sourceVM.VM.DataVirtualHardDisks

# Get source storage account information, not considering the data disks and os disks are in different accounts
$sourceStorageAccountName = $sourceOSDisk.MediaLink.Host -split "\." | select -First 1
$sourceStorageAccount = Get-AzureStorageAccount –StorageAccountName $sourceStorageAccountName
$sourceStorageKey = (Get-AzureStorageKey -StorageAccountName $sourceStorageAccountName).Primary 

Select-AzureSubscription -SubscriptionId $DestSubscritpionId
# Create destination context
$destStorageAccount = Get-AzureStorageAccount | ? {$_.StorageAccountName -eq $DestStorageAccountName} | select -first 1
if ($destStorageAccount -eq $null)
{
    New-AzureStorageAccount -StorageAccountName $DestStorageAccountName -Location $DestLocationName
    $destStorageAccount = Get-AzureStorageAccount -StorageAccountName $DestStorageAccountName
}
$DestStorageAccountName = $destStorageAccount.StorageAccountName
$destStorageKey = (Get-AzureStorageKey -StorageAccountName $DestStorageAccountName).Primary

$sourceContext = New-AzureStorageContext  –StorageAccountName $sourceStorageAccountName -StorageAccountKey $sourceStorageKey -Environment AzureChinaCloud
$destContext = New-AzureStorageContext  –StorageAccountName $DestStorageAccountName -StorageAccountKey $destStorageKey

# Create a container of vhds if it doesn't exist
Set-AzureSubscription -CurrentStorageAccountName $DestStorageAccountName -SubscriptionId $DestSubscritpionId
#if ((Get-AzureStorageContainer -Context $destContext -Name vhds -ErrorAction SilentlyContinue) -eq $null)
if ((Get-AzureStorageContainer -Name $DestStorageContainerName -ErrorAction SilentlyContinue) -eq $null)
{
    Write-Host "Creating a container vhds in the destination storage account." -ForegroundColor Green
#    New-AzureStorageContainer -Context $destContext -Name vhds
    New-AzureStorageContainer -Name $DestStorageContainerName     
}

$allDisks = @($sourceOSDisk) + $sourceDataDisks
$destDataDisks = @()
# Copy all data disk vhds
# Start all async copy requests in parallel.
foreach($disk in $allDisks)
{
    $blobName = $disk.MediaLink.Segments[2]
    # copy all data disks 
    Write-Host "Starting copying data disk $($disk.DiskName) at $(get-date)." -ForegroundColor Green
    $sourceBlob = "https://" + $disk.MediaLink.Host + "/" + $SourceStorageContainerName + "/"
    $targetBlob = $destStorageAccount.Endpoints[0] + $DestStorageContainerName + "/"
    $azcopylog = "azcopy-" + $SourceCloudServiceName + "-" + $SourceVMName +".log"

    Write-Host "Start copy vhd to destination storage account"  -ForegroundColor Green
    #Write-Host .\azcopy\AzCopy\AzCopy.exe /Source:$sourceBlob /Dest:$targetBlob /SourceKey:$sourceStorageKey /DestKey:$destStorageKey /Pattern:$blobName /SyncCopy /v:$azcopylog -ForegroundColor Green

    #cd 'C:\Program Files (x86)\Microsoft SDKs\Azure\AzCopy'
    #AzCopy.exe /Source:$sourceBlob /Dest:$targetBlob /SourceKey:$sourceStorageKey /DestKey:$destStorageKey /Pattern:$blobName /SyncCopy /v:$azcopylog
     
    #cd D:\AzCopy
    #.\AzCopy.exe /Source:$sourceBlob /Dest:$targetBlob /SourceKey:$sourceStorageKey /DestKey:$destStorageKey /Pattern:$blobName /SyncCopy /v:$azcopylog 

    #Start-AzureStorageBlobCopy is too slow
    Start-AzureStorageBlobCopy -SrcContainer $SourceStorageContainerName -SrcBlob $blobName -DestContainer $DestStorageContainerName -DestBlob $blobName -Context $sourceContext -DestContext $destContext -Force

    if ($disk –eq $sourceOSDisk)
    {
        $destOSDisk = $targetBlob + $blobName
    }
    else
    {
        $destDataDisks += $targetBlob + $blobName
    }
}


# Wait until all vhd files are copied.
$CopyStatusReportInterval = 15
$diskComplete = @()
do
{
    Write-Host "`n[WORKITEM] - Waiting for all disk copy to complete. Checking status every $CopyStatusReportInterval seconds." -ForegroundColor Yellow
    # check status every 30 seconds
    Sleep -Seconds $CopyStatusReportInterval
    foreach ( $disk in $allDisks)
    {
        if ($diskComplete -contains $disk)
        {
            Continue
        }
        $blobName = $disk.MediaLink.Segments[2]
        $copyState = Get-AzureStorageBlobCopyState -Blob $blobName -Container vhds -Context $destContext
        if ($copyState.Status -eq "Success")
        {
            Write-Host "`n[Status] - Success for disk copy $($disk.DiskName) at $($copyState.CompletionTime)" -ForegroundColor Green
            $diskComplete += $disk
        }
        else
        {
            if ($copyState.TotalBytes -gt 0)
            {
                $percent = ($copyState.BytesCopied / $copyState.TotalBytes) * 100
                Write-Host "`n[Status] - $('{0:N2}' -f $percent)% Complete for disk copy $($disk.DiskName)" -ForegroundColor Green
            }
        }
    }
} 
while($diskComplete.Count -lt $allDisks.Count)



# Create OS and data disks 
Write-Host "Add VM OS Disk. OS "+ $sourceOSDisk.OS +"diskName:" + $sourceOSDisk.DiskName + "Medialink:"+ $destOSDisk  -ForegroundColor Green

# 设置源VM的Disk Name和目标VM的Disk Name
$disknameOS = $sourceOSDisk.DiskName
if($IsSameSub)
{
    #OSDisk, 如果在同一个订阅下,则增加后缀以区分VHD文件名
    $disknameOS = $sourceOSDisk.DiskName + $DiskNameSuffix
}

Add-AzureDisk -OS $sourceOSDisk.OS -DiskName $disknameOS -MediaLocation $destOSDisk
# Attached the copied data disks to the new VM
foreach($currenDataDisk in $destDataDisks)
{
    $diskName = ($sourceDataDisks | ? {$currenDataDisk.EndsWith($_.MediaLink.Segments[2])}).DiskName
    if($IsSameSub)
    {
        #DataDisk, 如果在同一个订阅下,则增加后缀以区分VHD文件名
        $diskName = ($sourceDataDisks | ? {$currenDataDisk.EndsWith($_.MediaLink.Segments[2])}).DiskName + $DiskNameSuffix
    }
    Write-Host "Add VM Data Disk $diskName" -ForegroundColor Green
    Add-AzureDisk -DiskName $diskName -MediaLocation $currenDataDisk
}

Write-Host "Import VM from " $vmConfigurationPath -ForegroundColor Green
Set-AzureSubscription -SubscriptionId $DestSubscritpionId -CurrentStorageAccountName $DestStorageAccountName


# Manually change the data diskname in the same subscription coz it can't be same
if($IsSameSub)
{
    $ContinueAnswer = Read-Host "`n`tPlease update the Diskname in the configuration file "+ $vmConfigurationPath +", just add your suffix $DiskNameSuffix to the filename! Then press ENTER to continue.."
}
# Import VM from previous exported configuration plus vnet info
if (( Get-AzureService | Where { $_.ServiceName -eq $DestCloudServiceName } ).Count -eq 0 )
{
    New-AzureService -ServiceName $DestCloudServiceName -Location $DestLocationName
}

Write-Host "`n import-AzureVM -Path $vmConfigurationPath | Set-AzureSubnet -SubnetNames $DestSubNet | New-AzureVM -ServiceName $DestCloudServiceName -VNetName $DestVNetName -WaitForBoot" -ForegroundColor Green

Import-AzureVM -Path $vmConfigurationPath | Set-AzureSubnet -SubnetNames $DestSubNet | New-AzureVM -ServiceName $DestCloudServiceName -VNetName $DestVNetName -WaitForBoot
复制代码

 

本文转自Lei Zhang博客园博客,原文链接:http://www.cnblogs.com/threestone/p/5326575.html,如需转载请自行联系原作者


目录
相关文章
|
3月前
|
存储 弹性计算 运维
阿里云国际Windows操作系统迁移教程
阿里云国际Windows操作系统迁移教程
|
5月前
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
2月前
|
安全 Windows
【Azure Cloud Service】在Windows系统中抓取网络包 ( 不需要另外安全抓包工具)
通常,在生产环境中,为了保证系统环境的安全和纯粹,是不建议安装其它软件或排查工具(如果可以安装,也是需要走审批流程)。 本文将介绍一种,不用安装Wireshark / tcpdump 等工具,使用Windows系统自带的 netsh trace 命令来获取网络包的步骤
72 32
|
2月前
|
C# Windows
【Azure App Service】在App Service for Windows上验证能占用的内存最大值
根据以上测验,当使用App Service内存没有达到预期的值,且应用异常日志出现OutOfMemory时,就需要检查Platform的设置是否位64bit。
45 11
|
4月前
|
KVM 虚拟化
KVM虚拟机的热迁移
这篇文章详细介绍了KVM虚拟机的热迁移过程,包括临时迁移和永久迁移的步骤,以及可能遇到的故障和解决方案。
164 1
KVM虚拟机的热迁移
|
4月前
|
存储 虚拟化
使用DiskGenius工具来实现物理机迁移虚拟机,实现虚拟化
【9月更文挑战第1天】使用 DiskGenius 工具可将物理机迁移到虚拟机,实现系统与数据的虚拟化。此过程包括:安装 DiskGenius 和准备虚拟化平台;备份物理机数据;使用 DiskGenius 备份磁盘;在虚拟化软件中创建新虚拟机并导入磁盘备份;配置及调整虚拟机设置;测试性能并优化资源分配。这有助于测试、开发及系统管理。
521 5
|
5月前
|
PHP Windows
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
|
5月前
|
PHP 开发工具 git
【Azure 应用服务】在 App Service for Windows 中自定义 PHP 版本的方法
【Azure 应用服务】在 App Service for Windows 中自定义 PHP 版本的方法
|
5月前
|
网络安全 API 数据安全/隐私保护
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
|
5月前
|
Shell PHP Windows
【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.
【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.