Voilà un cas client qui m’a occupé un certain temps. Mon client déploie une application basée sur des services IaaS à l’aide d’images préalablement générées. Mes images « sources » sont localisées dans la région Azure France Central et doivent être mise à disposition dans la région Brazil South. Voilà pour le besoin de base.
Mon premier réflexe a été de rechercher si un service de réplication d’images n’existait pas. On a bien un repository pour les images pour les conteneurs (Azure Contrainer Registry), on doit donc avoir le même type de service pour le IaaS. C’est effectivement le cas, cela se nomme Shared Image Gallery. Mais, j’ai tout de suite exclu ce choix car :
- Service actuellement en Preview
- Pas encore disponible dans les régions Azure qui me concernent
Second réflexe, Azure Site Recovery. Cela fait quelques temps que l’on peut utiliser le service pour « cloner » une machine virtuelle existante pour assurer un DRP vers une autre région Azure. Très rapidement, j’ai dû abandonner cette option car les régions Azure source et destination ne dépendent pas du même cluster géographique.
Source : https://docs.microsoft.com/en-us/azure/site-recovery/azure-to-azure-support-matrix
Pire, le cas de la région Azure Brazil South est un peu particulier car au sein de son Géo, il n’a pas de région Azure associée. Bref, pas la bonne solution.
En dernier ressort, je suis tombé sur cet article : Synchronously copy all managed disks of an Azure Virtual Machine to Azure Storage Accounts in multiple Azure regions. C’est presque ce qu’il me faut car il faudra reconstruire une image après. A mes yeux, la démarche proposée avait quelques défauts :
- On paie une VM pour faire la copie avec AZCopy alors qu’on peut faire un job de copie
- Elle est un peu salée la VM en SKU E pour de la copie de fichiers
- Les opérations sont réalisées en séquentielle alors qu’on se contente de suivre un job.
J’avais déjà publié un billet pour cloner des machines virtuelles dans Azure. J’ai donc juste poussé la logique d’industrialisation jusqu’au bout. Cela va se dérouler en plusieurs étapes :
- Etape n°1 : Initialisation
- Etape n°2 : Génération des clés SAS pour les VHD
- Etape n°3 : Initialisation des opérations de copie
- Etape n°4 : Suivi des opérations de copie
- Etape n°5 : Reconstruction des Managed Disks
Etape n°1 : Initialisation
Avant de commencer, on va poser quelques bases. J’ai déployé une machine virtuelle en utilisant mon image dans le groupe de ressources « FranceCentral ». L’objectif est d’obtenir des Managed Disks dans le groupe de ressources « BrazilSouth » dans lequel on va préalablement avoir créé un Storage Account qui va être utilisé pour réceptionner les VHD à copier.
$SourceResourceGroup = « FranceCentral » $SourceVMName = « MASTER » $dataDiskNames = New-Object System.Collections.ArrayList $dataDiskSASes = New-Object System.Collections.ArrayList $SasKeyDuration = 36000 $DestinationResourceGroup = « BrazilSouth » $DestinationStorageAccount = « brazilreplication » $Accounttype = ‘Standard_LRS’ $VM = Get-AzureRmVM -ResourceGroupName $SourceResourceGroup -Name $SourceVMName -Verbose |
Etape n°2 : Génération des clés SAS pour les VHD
Pour chaque disque composant notre machine virtuelle, nous devons générer une clé SAS. J’ai volontairement configuré une durée de vie assez longue, ne voulant pas tomber dans une situation ou les clés SAS auraient échouées pour cause d’une copie beaucoup trop longue.
$osDiskName = $VM.StorageProfile.OsDisk.Name $osDiskSAS = (Grant-AzureRmDiskAccess -Access Read -DiskName $osDiskName -ResourceGroupName $SourceResourceGroup -DurationInSecond $SasKeyDuration -Verbose).AccessSAS foreach($dataDisk in $VM.StorageProfile.DataDisks) { $dataDiskNames.Add($dataDisk.Name) | Out-Null } foreach($dataDiskName in $dataDiskNames) { $dataDiskSASes.Add((Grant-AzureRmDiskAccess -Access Read -DiskName $dataDiskName -ResourceGroupName $SourceResourceGroup -DurationInSecond $SasKeyDuration -Verbose).AccessSAS) | Out-Null } |
A ce stade, si on observe un des objets Managed Disks dans le portail, on peut constater qu’une clé SAS a bien été générée pour chacun d’eux.
Etape n°3 : Initialisation des opérations de copie
C’est en ce point que je me suis différencié de l’article Synchronously copy all managed disks of an Azure Virtual Machine to Azure Storage Accounts in multiple Azure regions. Mon besoin n’étant pas de répliquer mes disques dans de multiples régions, pas besoin d’autant d’instance de la machine virtuelle Ubuntu pour réaliser les opérations de copies. En plus, on n’a pas besoin d’attendre. Ça fait bien longtemps qu’AZCopy.EXE supporte la notion de job pour les opérations de copies. En PowerShell, AZCOPY.EXE, c’est Start-AzureStorageBlobCopy. A ce stade, du contenu va commencer à apparaître dans le contenu prévu à cet effet dans le Storage Account localisé dans la région cible.
$DestStorageAccountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $DestinationResourceGroup -Name $DestinationStorageAccount $DestStorageContext = New-AzureStorageContext -StorageAccountName $DestinationStorageAccount -StorageAccountKey $DestStorageAccountKeys[0].Value Start-AzureStorageBlobCopy -AbsoluteUri $osDiskSAS -DestContainer $SourceVMName.ToLower() -DestContext $DestStorageContext -DestBlob $($osDiskName + « .VHD ») $DatadiskCount = 0 foreach($dataDiskSAS in $dataDiskSASes) { Start-AzureStorageBlobCopy -AbsoluteUri $dataDiskSAS -DestContainer $SourceVMName.ToLower() -DestContext $DestStorageContext -DestBlob $(« datadisk-$DatadiskCount » + « .VHD ») $DatadiskCount +=1 } |
Etape n°4 : Suivi des opérations de copie
La commande PowerShell Start-AzureStorageBlobCopy initié un job que l’on va suivre. Avantage, on va paralléliser toutes les opérations de copie. Pour suivre cela, on dispose de la commande PowerShell Get-AzureStorageBlobCopyState. La durée des opérations de copie dépendra principalement de la volumétrie de données à répliquer. Pour mes tests, quarante-neuf minutes étaient nécessaires pour répliquer un Managed Disk SATA de 127Go et un autre de 1To.
$StartTime = Get-Date $StorageOperations = Get-AzureStorageBlob -Container master -Context $DestStorageContext | Get-AzureStorageBlobCopyState While ($StorageOperations | Where-Object {$_.status -eq « Pending »}) { $StorageOperations | select-Object Copyid, Status Start-Sleep -Seconds 10 $StorageOperations = Get-AzureStorageBlob -Container master -Context $DestStorageContext | Get-AzureStorageBlobCopyState } $CopyTimeSpan = New-TimeSpan -Start $StartTime -End (Get-Date) $Totalcopyoperations ='{0:N0}’ -f $($CopyTimeSpan.TotalMinutes) Write-Host « Copy operation completed in $Totalcopyoperations minutes. » |
Etape n°5 : Reconstruction des Managed Disks
Il ne nous reste plus qu’à reconstruire des Managed Disks en commençant par construire un objet de type Managed Disk à l’aide de la commande PowerShell New-AzureRmDiskConfig. De, là, il n’y a plus qu’à créer la ressource Azure à l’aide de la commande PowerShell New-AzureRmDisk.
$Container = Get-AzureStorageContainer -Container master -Context $DestStorageContext $ContainerBaseURI = ($Container.CloudBlobContainer).uri.absoluteuri $ListVHDs = Get-AzureStorageBlob -Container master -Context $DestStorageContext ForEach ($VHD in $ListVHDs) { $Disksize = ($vhd.Length/1GB) +1 $Vhduri = $ContainerBaseURI + « / » + $vhd.name $diskName = ($vhd.name).Substring(0, ($vhd.name).lastindexof(« . »)) Write-Host « Creating Managed Disk $diskName in Resource Group $DestinationResourceGroup. » $diskConfig = New-AzureRmDiskConfig -AccountType $Accounttype -Location ((get-azurermresourcegroup -Name $DestinationResourceGroup).location) -DiskSizeGB $Disksize -SourceUri $vhdUri -CreateOption Import New-AzureRmDisk -DiskName $diskName -Disk $diskConfig -ResourceGroupName $DestinationResourceGroup } |
Maintenant, il y a plus qu’à reconstruire l’image de référence au brésil et supprimer les fichiers VHD.
Conclusion
La solution n’est pas parfaite, elle peut encore être améliorée. Si vous être plus de culture Linux, allez lire ce billet : Copy custom vm images on azure. L’approche est sensiblement identique.
Benoît – Simple and Secure by design but Business compliant.