I. Introduction

Les dernières versions de Windows Server 2016 Technical Preview permettent de réaliser de la virtualisation imbriquée.

Le but est donc d'avoir un hôte Hyper-V, contenant une VM, avec elle aussi Hyper-V, contenant encore là une VM.

II. Prérequis

Afin de pouvoir utiliser la « Nested Virtualization », il faut :

  • Windows 2016 Build 10565 minimum ;
  • 4 GB de RAM minimum par VM + la RAM pour l'hôte physique ;
  • Intel VT-x activé dans le bios.

Image non disponible

III. Environnement de test

L'environnement de test pour cet article est simplement constitué d'un serveur DELL PowerEdge R210 avec un Intel Xeon X3440 possédant 8 GB de RAM nommé PHY2016TP5

IV. Réalisation

La réalisation est simple. Tout d'abord nous installons Windows Server 2016 Technical Preview 5 sur notre machine physique.

Nous installons ensuite le rôle Hyper-V et le configurons selon nos besoins. Rien de particulier ici.

Nous allons ensuite créer une VM elle aussi installée en 2016 TP 5 (dans notre exemple VM2016TP5).

Cette VM doit avoir un minimum de 4 Go de RAM et on doit activer le MAC spoofing sur sa carte réseau si on veut qu'elle puisse avoir un accès au réseau.

Une fois la VM installée en 2016 TP5, si on tente d'installer le rôle Hyper-V, on aura une erreur, ce qui est normal, car il détecte qu'il est sur une machine virtuelle et non sur un serveur physique.

On éteint la VM.

On récupère le script de Microsoft, puis on le lance en administrateur dans une fenêtre PowerShell sur l'hôte physique :

 
Sélectionnez
Invoke-WebRequest https://raw.githubusercontent.com/Microsoft/Virtualization-Documentation/master/hyperv-tools/Nested/Enable-NestedVm.ps1 -OutFile ~/Enable-NestedVm.ps1

~/Enable-NestedVm.ps1 -VmName “VM2016TP5”

On peut ensuite rallumer la VM et cette fois nous pouvons installer le rôle Hyper-V et créer une autre VM dessus.

Image non disponible

V. Informations complémentaires

Cette technologie n'est qu'un début, c'est de la preview. Elle possède d'ailleurs quelques limitations qu'il faut connaître :

  • pas de mémoire dynamique pour la VM-host (dans notre exemple VM2016TP5) ;
  • pas de modification de la mémoire à chaud pour la VM-Host ;
  • pas de checkpoint pour la VM-Host ;
  • pas de live migration pour la VM-Host ;
  • pas de Save/Restore pour la VM-Host.

Cela ne fonctionne pas ? Vérifiez que votre hôte et votre VM sont capables de faire de la virtualisation imbriquée une fois le premier script appliqué.

Téléchargez simplement ce script et lancez-le :

 
Sélectionnez
Invoke-WebRequest https://raw.githubusercontent.com/Microsoft/Virtualization-Documentation/master/hyperv-tools/Nested/Get-NestedVirtStatus.ps1 -OutFile ~/Get-NestedVirtStatus.ps1

~/Get-NestedVirtStatus.ps1

Image non disponible

VI. Conclusion

En conclusion, Microsoft a rendu possible la virtualisation de la virtualisation avec Hyper-V au sein de Windows Server 2016. On peut maintenant créer un serveur physique avec Hyper-V, y faire une VM, avec Hyper-V, dans laquelle on fait une autre VM, avec elle aussi Hyper-V, sur laquelle on fait une VM et ainsi de suite.

Cette technologie, combinée à celle du docker sous Windows 2016 (voir notre article IIS sous Docker grâce à Windows server 2016) nous entraîne vers une nouvelle forme de virtualisation.

VII. Virtualisation imbriquée

Source : Microsoft

Cette fonctionnalité préliminaire anticipée est uniquement disponible pour les Windows Insiders qui exécutent la Build 10565 ou version ultérieure. Elle n'inclut aucune garantie de performances ou de stabilité.

La virtualisation imbriquée exécute la virtualisation dans un environnement virtualisé. En d'autres termes, l'imbrication vous permet d'exécuter le rôle serveur Hyper-V au sein d'une machine virtuelle.

Image non disponible

Hyper-V s'appuie sur la prise en charge de la virtualisation matérielle (par ex., Intel VT-x et AMD-V) pour exécuter des machines virtuelles. En règle générale, une fois qu'Hyper-V est installé, l'hyperviseur masque cette fonction sur les machines virtuelles invitées. Cela empêche les machines virtuelles invitées d'exécuter le rôle serveur Hyper-V sur d'autres hyperviseurs.

La virtualisation imbriquée expose les composants de prise en charge de la virtualisation matérielle à la machine virtuelle invitée.

Le diagramme ci-dessous illustre Hyper-V sans imbrication. L'hyperviseur Hyper-V prend le contrôle total des extensions de virtualisation matérielle (flèche orange) et ne les expose pas au système d'exploitation invité.

Image non disponible

En revanche, le diagramme ci-dessous illustre Hyper-V avec imbrication. Dans ce cas, Hyper-V expose les extensions de virtualisation matérielle à ses machines virtuelles. Quand l'imbrication est activée, une machine virtuelle invitée peut installer son propre hyperviseur et exécuter ses propres machines virtuelles invitées.

Image non disponible

VII-A. Configuration requise de la virtualisation imbriquée

Avant d'activer la virtualisation imbriquée, notez qu'il s'agit d'une version préliminaire. N'utilisez pas l'imbrication dans des environnements de production.

Configuration requise :

  • 4 Go de RAM disponible au minimum. La virtualisation imbriquée nécessite une quantité de mémoire importante ;
  • les deux hyperviseurs doivent être la dernière Build de Windows Insider (10565 ou supérieure). Les autres hyperviseurs ne fonctionnent pas ;
  • cette fonctionnalité est actuellement exclusivement Intel. Intel VT-x est nécessaire.

VII-B. Activer la virtualisation imbriquée

  1. Créez une machine virtuelle exécutant la même Build que celle de votre hôte. Instructions ici.
  2. Exécutez ce script en tant qu'administrateur sur l'hôte Hyper-V :

     
    Sélectionnez
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9.
    10.
    11.
    12.
    13.
    14.
    15.
    16.
    17.
    18.
    19.
    20.
    21.
    22.
    23.
    24.
    25.
    26.
    27.
    28.
    29.
    30.
    31.
    32.
    33.
    34.
    35.
    36.
    37.
    38.
    39.
    40.
    41.
    42.
    43.
    44.
    45.
    46.
    47.
    48.
    49.
    50.
    51.
    52.
    53.
    54.
    55.
    56.
    57.
    58.
    59.
    60.
    61.
    62.
    63.
    64.
    65.
    66.
    67.
    68.
    69.
    70.
    71.
    72.
    73.
    74.
    75.
    76.
    77.
    78.
    79.
    80.
    81.
    82.
    83.
    84.
    85.
    86.
    87.
    88.
    89.
    90.
    91.
    92.
    93.
    94.
    95.
    96.
    97.
    98.
    99.
    100.
    101.
    102.
    103.
    104.
    105.
    106.
    107.
    108.
    109.
    110.
    111.
    112.
    113.
    114.
    115.
    116.
    117.
    118.
    119.
    120.
    121.
    122.
    123.
    124.
    125.
    126.
    127.
    128.
    129.
    130.
    131.
    132.
    133.
    134.
    135.
    136.
    137.
    138.
    139.
    140.
    141.
    142.
    143.
    144.
    145.
    146.
    147.
    148.
    149.
    150.
    151.
    152.
    153.
    154.
    155.
    156.
    157.
    158.
    159.
    160.
    161.
    162.
    163.
    164.
    165.
    166.
    param([string]$vmName)
    #
    # Enable-NestedVm.ps1
    #
    # Checks VM for nesting comatability and configures if not properly setup.
    #
    # Author: Drew Cross
    
    if([string]::IsNullOrEmpty($vmName)) {
        Write-Host "No VM name passed"
        Exit;
    }
    
    # Constants
    $4GB = 4294967296
    
    #
    # Need to run elevated.  Do that here.
    #
    
    # Get the ID and security principal of the current user account
    $myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent();
    $myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($myWindowsID);
    
    # Get the security principal for the administrator role
    $adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator;
    
    # Check to see if we are currently running as an administrator
    if ($myWindowsPrincipal.IsInRole($adminRole)) {
        # We are running as an administrator, so change the title and background colour to indicate this
        $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)";
    
        } else {
        # We are not running as an administrator, so relaunch as administrator
    
        # Create a new process object that starts PowerShell
        $newProcess = New-Object System.Diagnostics.ProcessStartInfo "PowerShell";
    
        # Specify the current script path and name as a parameter with added scope and support for scripts with spaces in it's path
        $newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"
    
        # Indicate that the process should be elevated
        $newProcess.Verb = "runas";
    
        # Start the new process
        [System.Diagnostics.Process]::Start($newProcess) | Out-Null;
    
        # Exit from the current, unelevated, process
        Exit;
        }
    
    #
    # Get Vm Information
    #
    
    $vm = Get-VM -Name $vmName
    
    $vmInfo = New-Object PSObject
        
    # VM info
    Add-Member -InputObject $vmInfo NoteProperty -Name "ExposeVirtualizationExtensions" -Value $false
    Add-Member -InputObject $vmInfo NoteProperty -Name "DynamicMemoryEnabled" -Value $vm.DynamicMemoryEnabled
    Add-Member -InputObject $vmInfo NoteProperty -Name "SnapshotEnabled" -Value $false
    Add-Member -InputObject $vmInfo NoteProperty -Name "State" -Value $vm.State
    Add-Member -InputObject $vmInfo NoteProperty -Name "MacAddressSpoofing" -Value ((Get-VmNetworkAdapter -VmName $vmName).MacAddressSpoofing)
    Add-Member -InputObject $vmInfo NoteProperty -Name "MemorySize" -Value (Get-VMMemory -VmName $vmName).Startup
    
    
    # is nested enabled on this VM?
    $vmInfo.ExposeVirtualizationExtensions = (Get-VMProcessor -VM $vm).ExposeVirtualizationExtensions
    
    Write-Host "This script will set the following for $vmName in order to enable nesting:"
        
    $prompt = $false;
    
    # Output text for proposed actions
    if ($vmInfo.State -eq 'Saved') {
        Write-Host "\tSaved state will be removed"
        $prompt = $true
    }
    if ($vmInfo.State -ne 'Off' -or $vmInfo.State -eq 'Saved') {
        Write-Host "Vm State:" $vmInfo.State
        Write-Host "    $vmName will be turned off"
        $prompt = $true         
    }
    if ($vmInfo.ExposeVirtualizationExtensions -eq $false) {
        Write-Host "    Virtualization extensions will be enabled"
        $prompt = $true
    }
    if ($vmInfo.DynamicMemoryEnabled -eq $true) {
        Write-Host "    Dynamic memory will be disabled"
        $prompt = $true
    }
    if($vmInfo.MacAddressSpoofing -eq 'Off'){
        Write-Host "    Optionally enable mac address spoofing"
        $prompt = $true
    }
    if($vmInfo.MemorySize -lt $4GB) {
        Write-Host "    Optionally set vm memory to 4GB"
        $prompt = $true
    }
    
    if(-not $prompt) {
        Write-Host "    None, vm is already setup for nesting"
        Exit;
    }
    
    Write-Host "Input Y to accept or N to cancel:" -NoNewline
    
    $char = Read-Host
    
    while(-not ($char.StartsWith('Y') -or $char.StartsWith('N'))) {
        Write-Host "Invalid Input, Y or N" 
        $char = Read-Host
    }
    
    
    if($char.StartsWith('Y')) {
        if ($vmInfo.State -eq 'Saved') {
            Remove-VMSavedState -VMName $vmName
        }
        if ($vmInfo.State -ne 'Off' -or $vmInfo.State -eq 'Saved') {
            Stop-VM -VMName $vmName
        }
        if ($vmInfo.ExposeVirtualizationExtensions -eq $false) {
            Set-VMProcessor -VMName $vmName -ExposeVirtualizationExtensions $true
        }
        if ($vmInfo.DynamicMemoryEnabled -eq $true) {
            Set-VMMemory -VMName $vmName -DynamicMemoryEnabled $false
        }
    
        # Optionally turn on mac spoofing
        if($vmInfo.MacAddressSpoofing -eq 'Off') {
            Write-Host "Mac Address Spoofing isn't enabled (nested guests won't have network)." -ForegroundColor Yellow 
            Write-Host "Would you like to enable MAC address spoofing? (Y/N)" -NoNewline
            $input = Read-Host
    
            if($input -eq 'Y') {
                Set-VMNetworkAdapter -VMName $vmName -MacAddressSpoofing on
            }
            else {
                Write-Host "Not enabling Mac address spoofing."
            }
    
        }
    
        if($vmInfo.MemorySize -lt $4GB) {
            Write-Host "VM memory is set less than 4GB, without 4GB or more, you may not be able to start VMs." -ForegroundColor Yellow
            Write-Host "Would you like to set Vm memory to 4GB? (Y/N)" -NoNewline
            $input = Read-Host 
    
            if($input -eq 'Y') {
                Set-VMMemory -VMName $vmName -StartupBytes $4GB
            }
            else {
                Write-Host "Not setting Vm Memory to 4GB."
            }
        }
        Exit;
    }
    
    if($char.StartsWith('N')) {
        Write-Host "Exiting..."
        Exit;
    }
    Write-Host 'Invalid input'
    

    Dans cette version préliminaire, l'imbrication inclut quelques exigences de configuration. Pour faciliter les choses, ce script PowerShell vérifie votre configuration, remplace tout ce qui est incorrect, puis active la virtualisation imbriquée pour la machine virtuelle spécifiée.

     
    Sélectionnez
    Invoke-WebRequest https://raw.githubusercontent.com/Microsoft/Virtualization-Documentation/master/hyperv-tools/Nested/Enable-NestedVm.ps1 -OutFile ~/Enable-NestedVm.ps1 
    ~/Enable-NestedVm.ps1 -VmName "DemoVM"
  3. Installez Hyper-V dans la machine virtuelle.

     
    Sélectionnez
    Invoke-Command -VMName "DemoVM" -ScriptBlock { Enable-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V -Online; Restart-Computer }
  4. Créez des machines virtuelles imbriquées.

VII-C. Problèmes connus

Voici une liste des problèmes connus :

  • les hôtes sur lesquels la fonctionnalité Device Guard est activée ne peuvent pas exposer les extensions de virtualisation aux invités ;
  • les hôtes sur lesquels la sécurité basée sur la virtualisation est activée ne peuvent pas exposer les extensions de virtualisation aux invités. Vous devez d'abord désactiver la sécurité basée sur la virtualisation pour pouvoir afficher un aperçu de la virtualisation imbriquée ;
  • une fois la virtualisation imbriquée activée sur une machine virtuelle, les fonctionnalités suivantes ne sont plus compatibles avec cette machine virtuelle ;

ces actions échouent ou empêchent la machine virtuelle de démarrer si elle héberge d'autres machines virtuelles :

  • la mémoire dynamique doit être désactivée. Sinon la machine virtuelle ne peut pas démarrer,
  • le redimensionnement de la mémoire d'exécution échoue,
  • l'application de points de contrôle à une machine virtuelle en cours d'exécution échoue,
  • la migration dynamique échoue. En d'autres termes, une machine virtuelle qui héberge d'autres machines virtuelles ne peut pas être migrée dynamiquement,
  • la sauvegarde/restauration échoue ;

Ces fonctionnalités fonctionnent toujours dans la machine virtuelle invitée la « plus interne ». Les restrictions s'appliquent uniquement à la première couche de machines virtuelles.

  • une fois la virtualisation imbriquée activée, l'usurpation MAC doit être activée sur la machine virtuelle pour que la mise en réseau fonctionne sur les invités les « plus internes ».

VII-D. FAQ et résolution des problèmes

VII-D-1. Ma machine virtuelle ne démarre pas, que dois-je faire ?

  1. Assurez-vous que la mémoire dynamique est désactivée.
  2. Exécutez ce script PowerShell sur votre ordinateur hôte à partir d'une invite de commandes avec élévation de privilèges.

Ce script indique si votre hôte et les machines virtuelles sont configurés correctement pour l'imbrication.

 
Sélectionnez
Invoke-WebRequest https://raw.githubusercontent.com/Microsoft/Virtualization-Documentation/master/hyperv-tools/Nested/Get-NestedVirtStatus.ps1 -OutFile ~/Get-NestedVirtStatus.ps1 
~/Get-NestedVirtStatus.ps1

VII-D-2. La connexion à une machine virtuelle n'est pas rétablie

Si vous utilisez un mot de passe vide, il s'agit d'un problème connu. Modifiez votre mot de passe pour résoudre le problème.

VII-D-3. Mon problème n'est pas indiqué ici

Votre problème n'est pas indiqué ? Vous avez des commentaires ? Contactez-nous.

Indiquez-les dans l'application Commentaires sur Windows, les forums sur la virtualisation ou sur GitHub.

VIII. Remerciements

Nous tenons à remercier Claude Leloup pour sa relecture orthographique et Malick SECK pour la mise au gabarit.

Nous tenons également à remercier Microsoft France pour leur autorisation d'intégration de leur page https://msdn.microsoft.com/fr-fr/virtualization/hyperv_on_windows/user_guide/nesting.