Les VM d’un hôte ESXi ne sont plus à l’heure

Je me suis aperçu d’un dysfonctionnement aujourd’hui alors que j’étais connecté sur deux de mes machines virtuelles sur mon hyperviseur ESXi. En effet, l’heure des deux machines Windows et GNU/Linux étaient en avance de 9 minutes par rapport à l’heure réelle.

Mes machines Windows prennent le temps sur le contrôleur de domaine qui lui même prend le temps sur l’ESX, et mes machines GNU/Linux prennent leur temps sur l’ESX. Etant donné que j’avais le même décalage et qu’une interrogation de w32tm sur ma machine Windows me donnait un retour satisfaisant quant à la synchronisation de l’horloge par rapport à l’un de mes DC, j’en ai déduit que le problème était localisé côté ESX.

En effet, pour une raison inconnue, mes paramètres NTP avaient sauté, et le service était arrêté. J’ai donc ajouté des serveurs NTP sur lesquels se synchroniser, puis j’ai activé le démarrage automatique du service ainsi que le service lui-même :

Mais toujours rien, quelques minutes plus tard je n’obtiens toujours pas d’horloge correcte et le décalage est toujours présent. Je m’interroge donc sur le bon fonctionnement de mes serveurs NTP. J’interroge donc avec watch ntpq mes serveurs de temps, mais cela ne semble pas fonctionner :

En réalité, mon ESXi est incapable de résoudre les noms, ce qui fait que les noms des serveurs NTP ne peuvent être traduits en IP, d’où le dysfonctionnement actuel quant à mes requêtes NTP sur le pool que j’ai choisi. Un coup d’oeil rapide à la liste des règles du firewall me confirme mon impression : le client DNS est bloqué. Une fois le client activé, la résolution DNS se fait bien dans la console.

Une fois la résolution fonctionnelle, je relance par précaution le service NTP avec /etc/init.d/ntpd restart, puis une actualisation dans l’interface web vSphere me confirme que tout est revenu à la normale.

Concernant l’origine de ce dysfonctionnement, j’ai procédé au blocage de quelques règles pare-feu il y a quelques temps, et il est fort probable que je me sois aperçu de la désynchronisation de l’horloge qu’aujourd’hui.

Création d’un routeur et pare-feu pour un serveur ESXi avec l’appliance pfSense

Lorsque je suis passé de Proxmox VE qui est un hyperviseur basé sur Debian à vSphere ESXi, il m’a fallu trouver une nouvelle solution pour faire du routage d’adresses vers mes machines virtuelles car je ne veux pas utiliser une adresse IP par machine virtuelle. Si Proxmox VE permet cela nativement car basé sur Debian il possède iptables, ESXi n’a rien par défaut. Cependant, grâce à pfSense, il est possible d’ajouter cette fonctionnalité, pour peu que l’on soit en mesure d’avoir une deuxième IP différente de celle de l’ESXi à affecter (chez les prestataires louant des serveurs, une telle IP est généralement appelée une IP failover).

pfSense est une appliance faisant office – entre autres – de pare-feu, de routeur, de serveur DHCP, de serveur DNS, etc. basée sur BSD. Il existe une version gratuite que l’on peut récupérer sur le site web officiel. Dans cet article, je vais donc expliquer comment utiliser pfSense pour faire du NAT sur un serveur ESXi.

J’ai réalisé ces manipulations sur un serveur vSphere ESXi de test en version 6.0u2 – avec une licence gratuite. Je pars du principe que vous avez un minimum de connaissances de l’interface web ou du vClient, par conséquent je ne vais pas systématiquement réaliser des captures d’écran ou détailler le chemin à effectuer pour trouver où effectuer les réglages. Les captures d’écran peuvent être agrandies en cliquant dessus pour une meilleure visibilité.

1. Préparation côté vSphere

Le rôle de l’appliance va être de capter le trafic venant de l’internet pour le bloquer ou le rediriger vers les machines virtuelles hébergées. On va donc avoir deux vSwitch : un qui va servir pour le LAN, dans lequel nous placerons toutes les machines virtuelles ainsi que l’appliance pfSense, et un autre vSwitch qui servira pour le WAN, sur lequel seule l’appliance sera connectée.

Etant donné qu’il est évidemment nécessaire que le vSwitch WAN soit celui qui soit relié physiquement à la carte réseau du serveur, celui qui est créé par défaut par vSphere sera le vSwitch WAN. Il faut donc créer un nouveau vSwitch qui sera celui pour le LAN.

On valide en laissant les options par défaut, et on arrive normalement à quelque chose comme ceci – j’ai renommé l’étiquette du WAN afin qu’elle soit plus lisible.

Il faut maintenant récupérer l’ISO de pfSense, téléchargeable sur le site officiel. Une fois le fichier récupéré, on l’envoie sur le datastore puis on crée la machine virtuelle. pfSense occupe très très peu de ressources : 1 vCPU, 512 Mo de RAM et un disque virtuel de 8 Go suffisent. Lors de la création, le type d’OS à sélectionner sera « Free BSD ».

Ne pas oublier d’ajouter une deuxième carte réseau à l’appliance. Sous BSD, em0 sera le WAN et em1 le LAN.

Ensuite, il est nécessaire de modifier les paramètres de la machine virtuelle avant de la démarrer et d’installer le système. En effet, sur la carte WAN, nous allons déclarer l’adresse MAC de l’adresse IP que nous allons affecter à pfSense. Dans le cadre d’un serveur loué chez OVH par exemple, nous allons prendre une IP failover et utiliser l’adresse MAC de celle-ci. La carte LAN gardera une adresse MAC automatique gérée par vSphere.

L’adresse MAC de notre carte WAN sera celle de l’IP failover ou du matériel possédant cette IP.

Ensuite, il suffit de monter l’ISO depuis le datastore et de connecter le lecteur optique virtuel pour pouvoir démarrer la machine et laisser l’autoboot de pfSense agir.

2. Installation de pfSense

En démarrant pfSense, l’installeur va démarrer automatiquement si le mode rescue n’est pas sélectionné. Le premier écran permet de configurer rapidement l’installation.

Les options par défaut vont bien, bien qu’il soit possible de configurer le clavier, cela n’importe peu car une fois le système redémarré, nous allons rebasculer sur un clavier en-us. A l’étape suivante, nous allons choisir la « Quick / Easy Install » et le « Standard Kernel ». Ensuite, nous allons redémarrer. Par défaut, l’accès à l’interface d’administration est 192.168.1.1 et les logins admin / pfsense. Après le premier redémarrage, le système va se préconfigurer, cela peut prendre quelques minutes. A l’issue, il est possible de configurer l’appliance via le web ou via la console. L’installation est terminée lorsque nous arriverons sur cet écran post-boot.

C’est le moment de vérifier que tout est bien configuré. Normalement le WAN ressort sur l’interface em0 (sur VMware, cela doit être la carte WAN, situé sur le vSwitch0, avec l’adresse MAC de l’IP failover, la première carte de la machine) et le LAN ressort sur l’interface em1 (carte LAN, situé sur le vSwitch que nous avons créé au début, avec une MAC automatique, la deuxième carte de la machine).

3. Configuration de base de pfSense

Attention : la console de pfSense utilise un clavier en-us. Il est possible de changer la disposition du clavier en accédant au shell, cependant étant donné le peu de manipulations à faire en console, nous allons rester sur ce type de clavier.

La première chose à faire une fois l’écran accessible est de configurer les deux cartes. Même si l’interface LAN possède la bonne IP, nous allons faire une passe sur les deux. Nous allons donc saisir 1 comme option, et répondre à quelques questions :

  1. Création de VLAN : cela n’est pas important au départ, et peut très bien attendre la configuration par le web. Nous allons donc répondre « No » pour l’instant.
  2. L’interface pour le WAN nous est demandée. Il s’agit donc de notre première carte réseau sur la machine, donc em0 pour pfSense.
  3. L’interface pour le LAN nous est demandée : em1.
  4. Nous n’avons pas d’autres interfaces, nous laissons le champ vide et validons.
  5. Une confirmation est demandée : il suffit de valider.

Un petit temps de traitement est nécessaire et on retombe normalement sur l’écran principal. Nous allons maintenant configurer les adresses des deux interfaces.

En premier, l’interface WAN.

Il nous faut renseigner l’adresse IP WAN (l’IP failover, ou celle reliée à l’adresse MAC que nous avons saisi auparavant), le masque de sous-réseau et enfin la passerelle. Dans le cas d’une IP failover, il est fort probable que la passerelle soit l’IP en .254 à la fin. Ensuite, à moins d’avoir une IPv6, la seconde partie peut être passée – sinon, le même raisonnement que pour l’IPv4 est à appliquer. Ensuite, il est demandé si l’on veut basculer l’interface web sur du HTTP au lieu du HTTPS.

On revient ensuite à l’écran de base et nous allons répéter cette configuration mais pour la deuxième interface.

La configuration de la carte LAN est plus simple. 192.168.1.1 devient la passerelle pour les autres VM.

Il est possible d’activer le DHCP sur l’interface LAN à la fin de la configuration. Etant donné que nous allons installer une seule machine virtuelle sur la plateforme, cela a peu d’importance. Si l’option est sélectionnée, alors la plage d’adresses que le serveur pourra attribuer est demandée. La configuration de base est terminée, pfSense fonctionne.

4. Pour aller un peu plus loin

Nous allons déployer une machine virtuelle toute simple afin de tester le bon fonctionnement de pfSense et accéder à l’interface web bien plus pratique que le shell BSD. Une machine virtuelle fonctionnant sous Debian GNU/Linux fera parfaitement l’affaire. La petite image « netinst » pèse moins de 300 Mo et nécessite une connexion internet pour s’installer : le test idéal.

Une seule carte réseau pour la VM, celle du LAN.

Je ne vais pas faire une passe sur l’installation d’un système Debian. Cependant, l’installateur a bien pu configurer la machine virtuelle automatiquement grâce au DHCP que j’ai activé – sans cela, il aurait fallu saisir une adresse IP – par exemple 192.168.1.2 – et pfSense offre bien internet à la VM qui a pour IP de sortie notre IP failover, car les paquets sont téléchargés depuis les miroirs de Debian au fil de l’installation :

L’image « netinst » de Debian a besoin d’internet pour récupérer les paquets qui ne font pas partie du système de base. La machine a donc bien accès au net.

pfSense fonctionne donc très bien, puisqu’il est accessible et que l’appliance a fourni une adresse IP à ma machine virtuelle. On peut donc désormais se connecter à l’interface d’administration et passer par le petit assistant de configuration. Normalement, tout a été configuré par nos soins via la console – rien n’est à modifier pour l’instant. Enfin, à la fin, il est conseillé de changer le mot de passe d’administration.

Une fois libre, il est possible d’accéder à tout un tas de paramètres différents, mais nous allons seulement nous intéresser à la partie NAT dans ce billet, car les possibilités de pfSense sont très larges (sur mon infra perso, je m’en sers également comme serveur DHCP et DNS, par exemple). En allant dans Firewall > NAT, il est possible de créer des règles de redirection de ports. Par exemple, si je veux accéder en RDP à une machine VM Windows, il me suffit de créer une règle et de demander la redirection des bons ports :

Si 192.168.1.12 est l’IP de ma machine Windows, tout ce qui arrive sur le port 3389 de l’interface WAN (donc l’IP failover) est redirigé vers le port 3389 de ma machine Windows. Une fois la règle enregistrée, la configuration de pfSense doit être validée pour qu’elle rentre en action.

Pour faire un test de bon fonctionnement, je vais ouvrir le port 22 et le rediriger vers la VM.

L’écran de NAT de pfSense. Il est possible de catégoriser et de trier toutes les règles.

Une fois la configuration appliquée, il ne me reste plus qu’à ouvrir un client SSH et à tenter de me connecter.

La connexion est ouverte, je suis bien connecté en SSH sur ma VM depuis une machine extérieure.

Et voilà 😉

Afin de clore cet article, deux autres petites choses :

  • Il existe un paquet BSD pour les vmtools afin que la machine s’interface mieux avec ESXi. Dans System > Package Manager, il suffit de rechercher Open-VM-Tools et d’installer le paquet.
  • Dans Diagnostics > Backup & Restore, il est possible de faire un export XML de toute la configuration de pfSense. Cette sauvegarde est importante car en cas de crash, il est possible depuis l’install de pfSense de lui donner ce fichier XML pour que toute la configuration soit restaurée à l’identique.
L’écran des baux DHCP (Status > DHCP Leases), à partir duquel on peut transformer un bail temporaire en une réservation.

VMware et Powershell : contrôle de l’état des vmtools et des disques orphelins

Suite à quelques cas de vmtools qui tombaient en carafe sur des serveurs Windows en clientèle, j’ai eu l’idée de réaliser un petit script personnel afin de contrôler l’état des vmtools sur un ESXi ou un vCenter, et de remonter une alerte par email si jamais ils ne sont pas dans leur état normal.

On reçoit donc un courriel si les vmtools ne sont pas : en cours d’exécution, à jour ou installés. Par défaut, le script renvoie comme vmtools en erreur les machines qui sont éteintes car le serveur ne peut les joindre. C’est pourquoi il est nécessaire lors du contrôle d’exclure les machines éteintes.

 

Add-PSSnapin VMware.VimAutomation.Core
Add-PSSnapin VMware.PowerCLI
$From = "admin-vmw@localhost"
$To = "supervision@localhost"
$Smtp = "smtp.localdomain"
$ESXServer = "esxi.localdomain"
$ESXUser = "service"
$ESXPwd = "P@ssw0rd"

Connect-VIServer $ESXserver -User $ESXUser -Password $ESXPwd

$VMArray = Get-VM
foreach ($VM in $VMArray)
    {
    $VMPoweredOn = $VM.PowerState
    $toolsStatus = $VM.ExtensionData.Guest.ToolsStatus
    if ($toolsStatus -ne "toolsOK" -and $VMPoweredOn -eq "PoweredOn")
        {
        $MailString = "Bonjour, les vmtools sur la machine '$VM' remontent avec le statut inhabituel suivant : '$toolsStatus'."
        Send-MailMessage -From $From -To $To -Subject "vmtools en statut anormal sur $VM" -SmtpServer $Smtp -Body $MailString
        }
    }

Cela permet alors de pouvoir être plus réactif sur le bon fonctionnement des vmtools et d’éviter d’avoir des soucis de drivers réseau ou d’interface avec d’autres applications. Ce script est disponible dans une version commentée en cliquant sur mon miroir de téléchargement. A noter que pour ce script comme pour le suivant, un seul module Powershell est nécessaire mais en fonction de la version de PowerCLI installée, le nom de celui-ci peut changer.

Le deuxième script que j’ai écrit permet de trouver les VMDK orphelins présents sur les datastores d’un vCenter ou d’un ESX. Il prend la liste des VMDK sur les datastore puis récupère la liste des disques rattachés à une machine virtuelle. Il fait ensuite la différence des deux disques et affiche la liste des différences. Avant de procéder à une suppression, tout de même vérifier si le VMDK n’a pas été désolidarisé pour une raison X ou Y, ou qu’il ne s’agit pas d’un snapshot.

Add-PSSnapin VMware.VimAutomation.Core
Add-PSSnapin VMware.PowerCLI

$vmdkds=@()
$vmdkvm=@()
Write-Host "Parsing all datastores and VMDKs. This might take a while.`r`n"
$dslist = Get-View -ViewType Datastore | select Name
foreach($ds in $dslist) {
	$vmdks = Get-HardDisk -Datastore $ds.Name
        foreach($vmdk in $vmdks) {
            $vmdkfilename = @{Filename = $vmdk.Filename}
            $vmdkentry = New-Object PSObject -Property $vmdkfilename
            $vmdkds+=$vmdkentry
        }
	}
    $vmlist = Get-View -ViewType VirtualMachine | select Name
    foreach($vm in $vmlist) {
        $vmdks = Get-HardDisk -VM $vm.Name
        foreach($vmdk in $vmdks) {
            $vmdkfilename = @{Filename = $vmdk.Filename}
            $vmdkentry = New-Object PSObject -Property $vmdkfilename
            $vmdkvm+=$vmdkentry 
        }
    }
Write-Host "Done. Now processing. Please wait.`r`n"
Compare-Object $vmdkvm $vmdkds -Property Filename | Where-Object { $_.SideIndicator -eq "=>" } | foreach-object { Write-Host $_.InputObject }

Vous pouvez également trouver ce script dans une version commentée sur ce lien provenant de mon miroir de téléchargement.

VMware et Powershell : détection de snapshots anciens et surveillance de l’espace libre

PowerCli est un excellent outil pour faciliter l’administration et la maintenance d’une infrastructure VMware. Il m’arrive d’écrire des scripts pour un client ou pour moi-même en fonction de tâches que j’ai à réaliser. Dans ce billet, je vais partager aujourd’hui deux petits scripts tout simples.

Le premier permet de scanner les VM présentes sur l’ESX ou le vCenter et d’envoyer un courriel si un snapshot est plus ancien qu’un certain nombre de jours. Par défaut, si un snapshot existe sur une machine virtuelle, un mail est tout de même envoyé.

Add-PSSnapin VMware.VimAutomation.Core
$From = "admin-vmw@localhost"
$To = "supervision@localhost"
$Smtp = "smtp.localdomain"
$Delay = 7

Connect-VIServer $ESXserver -User $ESXUser -Password $ESXPwd

$VMNamesArray = Get-VM | select Name
foreach ($VMName in $VMNamesArray)
    {
    $VMSnaps = Get-Snapshot $VMName.name
    foreach ($Snap in $VMSnaps)
        {
        $now = Get-Date
        if ($Snap.Created.AddDays($Delay) -gt $now -eq $false)
            {
            $SnapVM = $Snap.VM
            $MailString = "Bonjour, le snapshot '$Snap' de la machine '$SnapVM' existe depuis plus de $Delay jours."
            Send-MailMessage -From $From -To $To -Subject "Alerte snapshot" -SmtpServer $Smtp -Body $MailString
            }
        else
            {
            $MailString = "Aucun snapshot datant de plus de $Delay jours existant."
            Send-MailMessage -From $From -To $To -Subject "Rapport snapshot" -SmtpServer $Smtp -Body $MailString
            }
        }
    }

Le second script analyse les datastore de l’ESX ou du vCenter et envoie un mail si jamais il y a dépassement du seuil prédéfini. Il me semble que les préconisations VMware font état d’un besoin minimal de 20% de libre sur un datastore pour assurer le fonctionnement optimal de celui-ci. Le script va envoyer un courriel si jamais un datastore tombe à moins de 25% d’espace libre.

Add-PSSnapin VMware.VimAutomation.Core
$From = "admin-vmw@localhost"
$To = "supervision@localhost"
$Smtp = "smtp.localdomain"
$SeuilAlerte = 25

Connect-VIServer $ESXserver -User $ESXUser -Password $ESXPwd

$DatastoreArray = Get-Datastore
foreach ($Datastore in $DatastoreArray)
    {
    $MBAvail = $Datastore.FreeSpaceMB
    $MBTotal = $Datastore.CapacityMB
    $FreeProp = ($MBAvail/$MBTotal) * 100
    if ($FreeProp -lt $SeuilAlerte)
        {
        $FreeProp = [math]::Round($FreeProp,1)
        $MailString = "Bonjour, le datastore '$Datastore' n'a plus que $FreeProp % de libre."
        Send-MailMessage -From $From -To $To -Subject "Alerte occupation Datastore" -SmtpServer $Smtp -Body $MailString
        }
    }

Vous pouvez récupérer les scripts depuis mon miroir de téléchargement dans des versions commentées :
Script d’alerte snapshot
Script d’alerte datastore