Sauvegarder ses VM en dehors de l’infrastructure vSphere, sans logiciel tiers, automatiquement, au format .vmdk

Comment externaliser et automatiser une sauvegarde de machines virtuelles dans le cadre d’une infrastructure vSphere / VMware + baie de stockage avec peu de moyens et sans logiciels particuliers ?

L’objectif est de récupérer, automatiquement et régulièrement, les images de toutes les machines virtuelles alors que celles-ci sont en cour d’exécution dans vSphere, sur, par exemple, un disque dur USB. vSphere est livré avec « Data Protection » mais cette solution est plus contraignante que des images simples de machines virtuelles (car le format des sauvegardes est spécifique). En cas de reprise d’activité en urgence, plus c’est simple, mieux c’est. De plus, dans le cadre d’un archivage de données, une image .vmdk de disque dur sera sans doute plus « simple » à relire dans quelques années. Il faudra évidement s’assurer régulièrement de la rétro compatibilité de produits tels que VMware Converter ou VMware Disk Mount et d’en conserver une copie. Des logiciels tels que VEAM permettent de réaliser très facilement ce genre d’opérations mais ajoutent une couche de complexité, notamment lors de la restauration ou de la relecture, car les machines sont sauvegardées dans un format spécifique au logiciel (format qui permet par exemple la dé-duplication des données).

La solution que je vous propose ici nous rend totalement indépendant du matériel de stockage (et de sa fiabilité !). Enfin, cerise sur le gâteau, nous allons préserver le caractère dynamique des disques virtuels VMware. C’est à dire que si vous utilisez l’option de provisionnement dynamique des disques (ou aussi appelés « Thin HardDisk ») – ce qui est tout de même bien pratique pour économiser l’espace disque de nos baies pour des machines virtuelles où la performance disque est non critique – vos fichiers .vmdk sauvegardés n’occuperont pas plus de place sur les disques durs que dans la baie, même si de prime abord ils ne donneront pas cette impression. Ah, et au fait : pas de bandes ou lecteurs de bande dans l’histoire, vous aurez juste besoin d’un câble USB.

La solution présentée ici n’est pas adaptée à une sauvegarde via un WAN, pour cela il vous faudra utiliser un logiciel qui optimise l’utilisation de la bande passante, type VEAM ou Double Take.

Prérequis :

  • Une licence vSphere autorisant le clonage à chaud des machines virtuelles.
  • Une station de travail robuste ou un petit serveur, avec une distribution Linux disposant d’un serveur NFS et de suffisamment d’espace disque pour accueillir toutes les machines virtuelles que l’on souhaite archiver. Les données n’étant ici pas critiques, nul besoin de raid et autres matériels compliqués. Quelques gros disques SATA est le tour est joué.
  • Une machine sous Windows, virtuelle ou physique, avec Windows PowerShell fonctionnel et VMware vSphere Power CLI installé.

Conditions de mes tests :

  • VMware ESXi 5.0.0
  • Debian Linux 5.0 Lenny noyau 2.6.26 x86 (qui trainait dans un coin et que je n’ai pas souhaité réinstaller, ça fonctionne ! )

1ère étape : configuration du serveur NFS sur le linux :

Pourquoi un serveur NFS ? parce que nous allons pouvoir l’ajouter dans vCenter en tant qu’espace de stockage et y déposer les clones de nos VM.

Sur Debian la configuration du serveur NFS se fait en éditant le fichier /etc/exports. Nous recherchons un maximum de performance pour que les copies soient le plus rapides possible, et la sécurité nous importe peu, voici donc la configuration retenue :

# /data est l’espace qui sera disponible sous vcenter

/data 10.1.1.0/24(rw,async,insecure,no_subtree_check,anonuid=0,anongid=0)

# mes serveurs vcenter sont en 10.1.1.* sur le lan des VMs
# je n'utilise pas le réseau dédié au stockage pour ne pas impacter
# la production et les sauvegardes ont lieu la nuit

Il est possible de spécifier les adresses IP précisément avec cette syntaxe :

directory machine1(option11,option12) machine2(option21,option22)

Il faudra également modifier le fichier /etc/hosts.allow :

mountd: 10.1.1.

ou par IP :

mountd: 10.1.1.10, 10.1.1.11

Pour plus de détails consultez la page man de NFS

2ème étape : ajout de l’espace de stockage dans vCenter :

A partir du client vSphere allez sur chacun de vos hôtes esx, onglet « Configuration » rubrique « Stockage », cliquez sur « ajouter stockage » :

nfs01et choisissez « système de fichier réseau ».

Indiquez :  l’adresse IP ou le nom de votre serveur NFS, le chemin complet du dossier partagé tel que défini dans /etc/exports et un nom convivial :

nfs02

Cliquez sur suivant et terminer.

nfs03

Nous avons maintenant une nouvelle banque de données que nous allons pouvoir utiliser. Et en principe elle ne nous a pas couté cher. Cela donne quelque chose comme ça :

nfs04

Testez cette banque de données en clonant quelques VM dessus pour vérifier son bon fonctionnement.

3ème étape : Scripter et planifier le backup des VMs en PowerShell

Tout d’abord quelques commandes à lancer, si ça n’a pas déjà été fait, sur la machine Windows qui va exécuter le script planifié. Ouvrez VMware vSphere PowerCLI  en tant qu’administrateur et tapez les commandes suivantes :

Set-PowerCLIConfiguration -InvalidCertificateAction ignore
Set-ExecutionPolicy RemoteSigned

Juste pour rappel, pour invoquer un script PowerShell depuis un .cmd :

powershell -file %userprofile%\Desktop\backup_vm_vsphere.ps1

Et c’est ce .cmd que l’on indiquera dans la planificateur de tâche de la machine Windows.

Bien, entrons dans le vif du sujet. Voici le script, commenté, permettant de sauvegarder les machines :

# Initialisation des objets VMware dans la session PowerShell
Add-PSSnapin VMware.VimAutomation.Core

# Connexion et authentification à l'ESX
Connect-VIServer vcenter.domaine.local -user domaine\login -pass password

# Si quelqu'un a une solution pour ne pas laisser le password en clair
# je suis preneur, en attendant faites en sorte que le fichier ne soit
# lisible que par l’utilisateur qui lance le script.

# On récupère la date
$date = (Get-Date -Format "yyyy-MM-dd")
# Date formatée pour les emails
$timestart = Get-Date -f "HH:mm"
# Préparation et envoi du mail
# (car on aime recevoir un email indiquant que tout se passe bien...)
$emailFrom = "script-backup-vsphere@mydom.com"
$emailTo = "moi@mydom.com, lui@mydom.com"
$subject = "Départ backup"
$smtpServer = "10.1.1.13"
# Préparation du corps de l'email
$body = "Bonjour, Backup vSphere en cours,
---------------
date de départ : "
,$date,"
heure de départ : "
, $timestart,"
---------------"

$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom,$emailTo,$subject,$body)
# Le mail est envoyé.

# datastore / banque de données d'origine des machines virtuelles
$myDatastore = "VMFS01"
# datastore de destination des sauvegardes
$myDatastore_backup = "serveur_NFS_pour_backups"

# Hôte sur lequel seront inventoriées les machines sauvegardées (mais pas exécutées)
$vmhost = "esx3.domaine.local"

# On récupère les objets PowerShell des banques de données...
$datastoreprod = get-datastore $myDatastore
$datastorebckp = get-datastore $myDatastore_backup

# ... à partir desquels nous allons créer des lecteurs PowerShell pour
# pouvoir manipuler (copie / suppression) des objets seuls
# (sans passer par le clonage des machines).
new-psdrive -Location $datastoreprod -Name proddrive  -PSProvider VimDatastore -Root ""
new-psdrive -Location $datastorebckp -Name backup_drive  -PSProvider VimDatastore -Root ""

# Fonction de sauvegarde d'une vm par clonage vers le serveur NFS
function backupvm ($nom_vm)
{
# Définition du nom de la machine sauvegardée
$nom_vm_backup = $nom_vm + ".backup"

# Ajout informations logs avec les dates de début et de fin de sauvegarde
# utile pour estimer l'impact de ces clonages
$time1 = Get-Date -f "HH:mm"

# On modifie la variable 'globale' $body en ajoutant $script: devant $body
$script:body = $script:body + "
"
+ $nom_vm +" de ", $time1

# Suppression de la version précédente, on écrase donc une éventuelle version
# précédente de la VM, vous pouvez modifier le script en modifiant le nom
# de la VM en fonction de la date.
Remove-VM $nom_vm_backup -DeletePermanently -confirm:$false

# Suppression des résidus de répertoire, car "parfois"
# le dossier n'est pas supprimé (d'où l'intérêt d'avoir défini un lecteur)
Remove-item backup_drive:\$nom_vm_backup  -force -recurse

# Clonage de la VM (à chaud)
New-VM -Name $nom_vm_backup -VM $nom_vm -Datastore $myDatastore_backup -VMHost $vmhost

# et on ajoute l'heure de fin aux logs
$time2 = Get-Date -f "HH:mm"
$script:body = $script:body + " à " ,$time2,"
---------------"

}

# Préparation du mail de rapport de fin de backup
$subject = "Rapport de fin de Backup vSphere"
$body = "Backup terminé
---------------
date de départ : "
,$date,"
heure de départ : "
, $timestart,"
---------------"


# Ici liste des machines à sauvegarder avec un If éventuel concernant la date

# Tous les jours
backupvm intranet
backupvm controleurad

# le lundi seulement, etc...
if ((get-date -uFormat %A) -eq "lundi")
{
backupvm extranet
}

# Et on prépare l'envoi du mail
$timefin = Get-Date -f "HH:mm"
$body = $body + "
date de fin : "
, (Get-Date -Format "yyyy-MM-dd") , "
heure de fin : "
, $timefin,"
---------------"


$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom,$emailTo,$subject,$body)

Ayant retranscrit et adapté ce script avec des noms génériques et à titre d’exemple, il n’est pas improbable que, n’ayant pu le tester, des coquilles se soient glissées. N’hésitez pas à me les signaler. Néanmoins j’utilise cette méthode quotidiennement : et ça fonctionne !

Télécharger le fichier backup_vm_vsphere.ps1

On peut ajouter une variante. En effet, parfois, on a besoin de ne sauvegarder qu’une partie d’une VM, par exemple le fichier de configuration et le disque système, mais pas les disques additionnels contenant les données. Ou bien on peut préférer sauvegarder la machine à froid (machine éteinte donc).

Dans ce cas on peut utiliser une fonction différente, que voici, et qu’il suffira d’adapter à ses usages :

function backup_items_of_vm ($nom_vm)
{
# définition du nom de la machine sauvegardée
$nom_vm_backup = $nom_vm + ".backup"
# ajout informations logs
$time1 = Get-Date -f "HH:mm"
$script:body = $script:body + "
"
+ $nom_vm +" de ", $time1

# Extinction de la VM
Get-vm -Name $nom_vm |  Shutdown-VMGuest -confirm:$false
# On attend que la VM soit bien éteinte
$i=0
WHILE (Get-VM -name $nom_vm | Where { ($_.PowerState -eq "PoweredOn")  })
{
$i += 5
# Cette affichage est visible dans la console qui exécute le script
write-output "Extinction en cours $i secondes"
sleep 5
}

#Suppression de la version précédente
Remove-VM $nom_vm_backup -DeletePermanently -confirm:$false
#Suppression des résidus de répertoire
Remove-item backup_drive:\$nom_vm_backup  -force -recurse
# Création du répertoire
mkdir backup_drive:\$nom_vm_backup

# Copie du fichier de configuration :  attention, je pars du principe, que la VM,
# son dossier de stockage, son fichier de configuration, et son disque dur
# système ont tous le même nom, ce qui est le cas par défaut.
# Si ce n'est pas le cas il vous faudra renommer ou adapter le script
Copy-DatastoreItem -item "proddrive:\$nom_vm\$nom_vm.vmx" "backup_drive:\$nom_vm_backup\$nom_vm_backup.vmx" -Force

# Copie du disque dur, il est important d'utiliser cette fonction, car elle garantie la conservation du format du disque
Get-HardDisk -VM $nom_vm -disktype flat | Copy-HardDisk -DestinationPath  "[$myDatastore_backup] /$nom_vm_backup/" -Force

# Optionnel : on ajoute la VM ainsi créée à l'inventaire des machines
New-VM -VMHost $vmhost -Name $nom_vm_backup -VMFilePath "[$myDatastore_backup] /$nom_vm_backup/$nom_vm_backup.vmx"

# On rallume la VM
Get-vm -Name $nom_vm | Start-VM

# Fin des infos pour le mail
$time2 = Get-Date -f "HH:mm"
$script:body = $script:body + " à " ,$time2,"
---------------"

}

Nous disposons maintenant d’une copie de nos VMs régulièrement effectuée sur un simple stockage, par exemple au format ext3.

Télécharger le fichier backup_vm_vsphere2.ps1

A ce stade il est intéressant de noter comment les fichiers de la VM sont stockés :

# ls -shl
total 37G
37G -rw------- 1 root root 160G jui  6 00:20 intranet2.backup-flat.vmdk
12K -rw------- 1 root root 8,5K jui  6 00:07 intranet2.backup.nvram
4,0K -rw------- 1 root root  684 jui  6 00:20 intranet2.backup.vmdk
0 -rw-rw-rw- 1 root root    0 jui  6 00:20 intranet2.backup.vmsd
4,0K -rwxrwxrwx 1 root root 2,8K jui  6 00:20 intranet2.backup.vmx
4,0K -rw-rw-rw- 1 root root  271 jui  6 00:20 intranet2.backup.vmxf
116K -rw------- 1 root root 109K jui  6 00:07 vmware-1.log
148K -rw------- 1 root root 144K jui  6 00:07 vmware-2.log
760K -rw------- 1 root root 754K jui  6 00:07 vmware.log

Notez l’option -sh appliquée à ls, qui permet d’afficher de manière conviviale le nombre de blocks réellement utilisés par chaque fichier. Comme mon système de fichier est formaté avec des blocks d’une taille de 4ko, les petits fichiers de quelques octets apparaissent avec une taille (première colonne) de 4ko.

En revanche vous pouvez observer que le fichier intranet2.backup-flat.vmdk occupe 37 Go alors qu’il est indiqué comme étant un fichier de 160 Go. L’espace disque réellement utilisé n’est que de 37 Go.

Ok, mais ce n’est pas terminé. Si maintenant on veut copier ces fichiers sur un disque dur USB, monté par exemple dans /mnt/usb, il va falloir prendre quelques précautions.

En effet, par défaut, cp ou rsync ne vont pas traiter correctement ce type de fichiers, appelés « sparse file » ou fichiers creux.

L’option –sparse de rsync ne fonctionne pas :  on se retrouve avec un fichier ayant une taille indiquée incorrecte, et le fichier n’est pas lisible. Même résultat si on utilise la commande cp.

Solution : utiliser cp –sparse=always

Ce qui nous donne au final un petit script à mettre en crontab pour copier les VM sauvegardées sur disque dur USB (NB. : le disque doit être formatté au format ext3 – je n’ai pas testé ext4 / XFS / ReiserFS etc… mais si vous avez fait l’expérience n’hésitez pas à nous en faire profiter).

Attention évidement à n’exécuter ce script de recopie que si les sauvegardes sont terminées (soit en prévoyant une grosse marge – dangereux – ou bien en testant la présence d’un fichier témoin) et les VM éteintes ! Puisqu’il est possible de les rallumer directement.

mount /dev/sdb1 /mnt/usb
rm -r -f /mnt/usb/backupvm/*
cp --sparse=always -f -r  /data/* /mnt/usb/backupvm/
umount /mnt/usb

Bien sûr, testez vos copies régulièrement, un bug est vite arrivé !


Ampli à tubes – 6 – Sélecteur de source à relais

Rien de très compliqué dans ce schéma. Nous avons 6 sources / entrées disponibles. Pour les sélectionner nous utilisons un switch rotatif qui alimente des relais référence Takamisawa RY-05W-K (doc disponible en cliquant) , relais qui peuvent commuter deux signaux, ce qui nous permet de gérer la stéréo avec un seul relai. On disposera 6 relais en tout sur des plaques permettant d’en positionner deux pour des raisons pratiques. Ces plaques PCB sont disponibles chez Tube-Town. Les relais sont alimentés par du + 5V continu généré par notre alimentation (cf. schéma des alimentations). Si vous jetez un œil à la documentation vous verrez que les caractéristiques des capacités entre les bornes des relais restent très bonnes, avec des fréquences de coupure loin du spectre sonore audible (page 3 : capacité de l’ordre du picofarad entre les contacts).

Les relais sont protégés par des diodes 1n4148 (ou plutôt le reste du circuit est protégé par les diodes) qui court-circuiterons toute décharge électrique générée par les relais lors de leur extinction (la bobine enverra une surtension lors de la coupure et on ne veut pas griller nos leds).

Cliquez sur le schéma pour l’agrandir.

selecteur_dentrees_a_relais