zoukankan      html  css  js  c++  java
  • 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 .azcopyAzCopyAzCopy.exe /Source:$sourceBlob /Dest:$targetBlob /SourceKey:$sourceStorageKey /DestKey:$destStorageKey /Pattern:$blobName /SyncCopy /v:$azcopylog -ForegroundColor Green
    
        #cd 'C:Program Files (x86)Microsoft SDKsAzureAzCopy'
        #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
  • 相关阅读:
    Vivado2014.3安装破解流程
    Win7、Win8、win10系统USB-Blaster驱动程序无法安装的解决办法
    Quartus II 与ModelSim-Altera联合仿真FFT IP核之FFT IP调用与自产生信号分析-lab2
    Quartus II 与ModelSim-Altera联合仿真FFT IP核之FFT IP调用与例程数据验证-lab1
    Quartus II 与ModelSim-Altera联合仿真FFT IP核之FFT IP核分析
    Quartus II 与ModelSim-SE联合仿真Shift_ram
    Quartus II 与ModelSim-Altera联合仿真PLL
    1st.初识GCC——关于GCC编译器的相关语法与介绍
    5th.NandFlash初接触——反正他说这几节课都是启发一下而已
    4th.关于MMU中的虚拟映射
  • 原文地址:https://www.cnblogs.com/threestone/p/5326575.html
Copyright © 2011-2022 走看看