Migrandos VMs entre regiões do Microsoft Azure

worksonmymachine

Olá pessoal,

Com o recente anúncio do GA (General Availability) da região sul do Brasil, muitos clientes estão me perguntando como podem migrar suas máquinas virtuais das outras regiões para a região brasileira. A realidade é que não existe um procedimento automatizado para que esta migração ocorra, sendo necessário passos manuais para a migração ocorrer.

Em linhas gerais, os principais passos são os seguintes:

  1. Listar as VMs de um determinado Cloud Service
  2. Para cada VM
    1. Desligar a VM se ela estiver rodando
    2. Criar um snapshot para o disco do sistema operacional
    3. Criar um snapshot para cada data disk
    4. Ligar a VM se ela estivesse rodando
  3. Para cada snapshot criado, copiar o Blob uma outra conta de storge
  4. Esperar a cópia de todos os Blobs
  5. Importar a configuração das VMs existentes
  6. Substituir os discos, tanto do sistema operacional quanto de dados, pelos novos Blobs
  7. Criar as novas VMs em um outro Cloud Service

Ufa!!! São vários passos, mas para facilitar podemos utilizar os Cmdlets PowerShell de gerenciamento do Azure. Vamos detalhar cada um dos passos acima.

Listar as VMs de um determinado Cloud Service:

Para listar as VMs de um Cloud Service basta utilizar o Cmdlet Get-AzureVM, passando o nome do Cloud Service como parâmetro:

$vms = Get-AzureVM -ServiceName $sourceCloudServiceName

Desligar a VM se ela estiver rodando

Antes de criarmos os snapshots dos discos é importante que a VM esteja desligada, pois isso irá garantir que todos os dados que eventualmente estão em algum cache foram efetivamente gravados em disco, minimizando a perda de alguma informação e garantindo a integridade das informações.

Nesta etapa, primeiro é necessário verificar se a VM está rodando. Isso é feito verificando a propriedade InstanceStatus da VM. Se ela for ReadyRole significa que ela está no ar.

Para desligar a VM, basta utilizar o Cmdlet Stop-AzureVM, conforme abaixo:

Stop-AzureVM -ServiceName $sourceCloudServiceName -Name $vmName –StayProvisioned

O parâmetro StayProvisioned é importante para mantermos o endereço IP da VM e permitir que ela seja religada de maneira mais rápida nos próximos passos.

Criar um snapshot para o disco do sistema operacional

A tarefa de criar um snapshot do disco do sistema operacional é um pouco complexa. O primeiro passo é ter acesso ao disco, isso é feito através do Cmdlet Get-AzureOSDisk:

$osDisk = $vm | Get-AzureOSDisk

Em seguida, é necessário acessar o Blob que o disco está utilizando. A propriedade MediaLink do disco contém o endereço deste Blob. O acesso ao Blob pode ser feito com o Cmdlet Get-AzureStorageBlob.

Utilizando o objeto de Blob retornado, é possível criar o snapshot através da interface ICloudBlob da API .NET, conforme abaixo:

$snapshot = $blob.ICloudBlob.CreateSnapshot()

Criar um snapshot para cada data disk

Para criar um snapshot para cada data disk, o primeiro passo é ter acesso aos data disks. Isso é feito pelo Cmdlet Get-AzureDataDisk:

$dataDisks = $vm | Get-AzureDataDisk

A principal diferença dos passos acima, é que o Get-AzureDataDisk retorna uma coleção de discos, sendo necessário trata-los individualmente, o que pode ser feito com um foreach. Os outros passos são muitos similares ao que foi apontado acima.

Ligar a VM se ela estivesse rodando

Para ligar a VM, basta utilizar o Cmdlet Start-AzureVM:

Start-AzureVM -ServiceName $sourceCloudServiceName -Name $vmName

Para cada snapshot criado, copiar o Blob uma outra conta de storage

Para facilitar a cópia de arquivos grandes, caso dos discos das VMs, o Azure possui uma API de cópia assíncrona em background que ocorre do lado do servidor. O time do Azure storage fez um post chamado Introducing Asynchronous Cross-Account Copy Blob detalhando essa API.

O PowerShell possui o Cmdlet Start-AzureStorageBlobCopy que utiliza essa API, conforme abaixo:

Start-AzureStorageBlobCopy -ICloudBlob $snapshot -DestContext $destinationStorageAccountContext -DestContainer "vhds" -DestBlob $snapshot.Name

Esperar a cópia de todos os Blobs

Para esperar que a cópia dos Blobs ocorra, o PowerShell possui um Cmdlet chamado Get-AzureStorageBlobCopyState, que retorna informações sobre a situação da cópia.

Importar a configuração das VMs existentes

Depois que os discos foram copiados, o próximo passo seria configurar as novas VMs. Para isso é necessário realizar dois passos: exportar a configuração atual e depois importar esta configuração:

$vmSource | Export-AzureVM -Path $env:TEMP\$($vmSource.Name).xml
$vmDestination = Import-AzureVM -Path $env:TEMP\$($vmSource.Name).xml

Substituir os discos, tanto do sistema operacional quanto de dados, pelos novos Blobs

Nesta etapa são vários passos. Primeiro é necessário encontrar o novo Blob copiado que está relacionado com o disco da configuração atual, isso é feito da seguinte maneira:

$osDisk = Get-AzureDisk -DiskName $vmSource.VM.OSVirtualHardDisk.DiskName
$blob = $blobs | Where-Object {$_.Name -eq $osDisk.MediaLink.Segments[2]}

Depois criar um novo disco e substituir o disco da nova VM:

$newOSDisk = Add-AzureDisk -DiskName ($destinationCloudServiceName + "-" + $osDisk.DiskName) -MediaLocation $blob.ICloudBlob.Uri.AbsoluteUri -OS $osDisk.OS

$vmDestination.OSVirtualHardDisk.DiskName = $newOSDisk.DiskName

Para os Data Disks o procedimento é muito parecido, com algumas pequenas diferenças:

  • Uma VM pode ter vários Data Disks, então isso deve ser tratado em um loop
  • Utilizar a propriedade DataVirtualHardDisks da VM, ao invés da propriedade OSVirtualHardDisk
  • Ao criar o disco com o Cmdlet Add-AzureDisk, não informar o parâmetro –OS

Criar as novas VMs em um outro Cloud Service

A criação das novas VMs é um passo bastante simples, basta utilizar o Cmdlet New-AzureVM. Este comando recebe uma coleção de configurações de VMs, então todas podem ser criadas em um único passo:

New-AzureVM -ServiceName $destinationCloudServiceName -VMs $vmDestination

Se as VMs originais estiverem configuradas em uma Virtual Network, também é possível especificar esse parâmetro na criação das VMs:

New-AzureVM -ServiceName $destinationCloudServiceName -VMs $vmDestination -VNetName $vnetName

Script

Para facilitar, criei um script PowerShell que faz os passos acima e um pouco mais. O download pode ser feito aqui.

Para o script funcionar, são necessários os seguintes requisitos:

  1. O Cloud Service de destino deve existir
  2. A conta de storage de destino deve existir
  3. Um container chamado vhds deve existir no storage de destino
  4. Tanto os Cloud Services de origem e destino, quanto as contas de storage de origem e destino devem estar na mesma assinatura do Azure
  5. Se uma rede virtual está sendo utilizada, é necessário que a rede de destino tenha as mesmas configurações de sub rede da rede de origem

Para rodar o script, utilize a seguinte sintaxe:

Copy-AzureVM $sourceCloudServiceName $destinationCloudServiceName $destinationStorageAccountName $vnetName

Abs.,

RG