Délimiter l’allocation de volumes dans les espaces de stockage direct

S’applique à : Windows Server 2022, Windows Server 2019

Windows Server 2019 introduit une option permettant de délimiter manuellement l’allocation de volumes dans espaces de stockage direct. Cela peut augmenter considérablement la tolérance de panne dans certaines conditions, mais impose des considérations de gestion et une complexité supplémentaires. Cette rubrique explique son fonctionnement et fournit des exemples dans PowerShell.

Important

Cette fonctionnalité est une nouveauté dans Windows Server 2019. Elle n’est pas disponible dans Windows Server 2016.

Prérequis

Green checkmark icon. Envisagez d’utiliser cette option si :

  • Votre cluster a au moins six serveurs et
  • Votre cluster utilise uniquement la résilience miroir triple

Red X icon. N’utilisez pas cette option si :

Comprendre

Révision : allocation régulière

Avec la mise en miroir tridirectionnel régulière, le volume est divisé en de nombreuses petites « dalles » qui sont copiées trois fois et distribuées uniformément sur chaque lecteur de chaque serveur du cluster. Pour plus d’informations, consultez ce blog de plongée approfondie.

Diagram showing the volume being divided into three stacks of slabs and distributed evenly across every server.

Cette allocation par défaut optimise les lectures et les écritures parallèles, ce qui améliore les performances et est attrayante par sa simplicité : chaque serveur est également occupé, chaque lecteur est également plein et tous les volumes restent en ligne ou sont mis hors connexion ensemble. Chaque volume est garanti pour survivre jusqu’à deux défaillances simultanées, comme l’illustrent ces exemples.

Toutefois, avec cette allocation, les volumes ne peuvent pas survivre à trois échecs simultanés. Si trois serveurs tombent en panne en même temps, ou si les lecteurs de trois serveurs tombent en panne à la fois, les volumes deviennent inaccessibles, car au moins certaines dalles ont été (avec une probabilité très élevée) allouées aux trois lecteurs ou serveurs qui ont échoué.

Dans l’exemple ci-dessous, les serveurs 1, 3 et 5 échouent en même temps. Bien que de nombreuses dalles aient des copies survivantes, certaines n’en ont pas :

Diagram showing three of six servers highlighted in red, and the overall volume is red.

Le volume passe hors connexion et devient inaccessible jusqu’à ce que les serveurs soient récupérés.

Nouveau : allocation délimitée

Avec l’allocation délimitée, vous spécifiez un sous-ensemble de serveurs à utiliser (au moins quatre). Le volume est divisé en dalles copiées trois fois, comme auparavant, mais au lieu d’allouer sur chaque serveur, les dalles sont allouées uniquement au sous-ensemble de serveurs que vous spécifiez.

Par exemple, si vous avez un cluster à 8 nœuds (nœuds 1 à 8), vous pouvez spécifier un volume à localiser uniquement sur les disques dans les nœuds 1, 2, 3, 4.

Avantages

Avec l’exemple d’allocation, le volume est susceptible de survivre à trois échecs simultanés. Si les nœuds 1, 2 et 6 tombent en panne, seuls 2 des nœuds qui contiennent les 3 copies de données du volume sont en panne et le volume reste en ligne.

La probabilité de survie dépend du nombre de serveurs et d’autres facteurs. Pour plus d’informations, consultez Analyse.

Inconvénients

L’allocation délimitée impose des considérations de gestion et une complexité supplémentaires :

  1. L’administrateur est responsable de la limitation de l’allocation de chaque volume pour équilibrer l’utilisation du stockage sur les serveurs et maintenir une forte probabilité de survie, comme décrit dans la section Meilleures pratiques.

  2. Avec une allocation délimitée, réservez l’équivalent d’un lecteur de capacité par serveur (sans maximum). C’est plus que la recommandation publiée pour l’allocation régulière, qui s’élève à quatre disques de capacité au total.

  3. Si un serveur échoue et doit être remplacé, comme décrit dans Supprimer un serveur et ses lecteurs, l’administrateur est responsable de la mise à jour de la délimitation des volumes affectés en ajoutant le nouveau serveur et en supprimant celui qui a échoué (exemple ci-dessous).

Utilisation dans PowerShell

Vous pouvez utiliser l’applet de commande New-Volume pour créer des volumes dans les espaces de stockage direct.

Par exemple, pour créer un volume miroir tridirectionnel normal :

New-Volume -FriendlyName "MyRegularVolume" -Size 100GB

Créer un volume et délimiter son allocation

Pour créer un volume miroir à trois voies et délimiter son allocation :

  1. Affectez d’abord les serveurs de votre cluster à la variable $Servers :

    $Servers = Get-StorageFaultDomain -Type StorageScaleUnit | Sort FriendlyName
    

    Conseil

    Dans espaces de stockage direct, le terme « unité de mise à l’échelle du stockage » fait référence à tout le stockage brut attaché à un serveur, y compris les lecteurs à attachement direct et les boîtiers externes à attachement direct avec lecteurs. Dans ce contexte, il est identique à « serveur ».

  2. Spécifiez les serveurs à utiliser avec le nouveau -StorageFaultDomainsToUse paramètre et en indexant dans $Servers. Par exemple, pour délimiter l’allocation aux premier, deuxième, troisième et quatrième serveurs (index 0, 1, 2 et 3) :

    New-Volume -FriendlyName "MyVolume" -Size 100GB -StorageFaultDomainsToUse $Servers[0,1,2,3]
    

Voir allocation délimitée

Pour voir comment MyVolume est alloué, utilisez le Get-VirtualDiskFootprintBySSU.ps1 script en annexe :

PS C:\> .\Get-VirtualDiskFootprintBySSU.ps1

VirtualDiskFriendlyName TotalFootprint Server1 Server2 Server3 Server4 Server5 Server6
----------------------- -------------- ------- ------- ------- ------- ------- -------
MyVolume                300 GB         100 GB  100 GB  100 GB  100 GB  0       0

Notez que seuls Server1, Server2, Server3 et Server4 contiennent des dalles de MyVolume.

Modifier une allocation délimitée

Utilisez les nouvelles applets de commande Add-StorageFaultDomain et Remove-StorageFaultDomain pour modifier la façon dont l’allocation est délimitée.

Par exemple, pour déplacer MyVolumed’un serveur :

  1. Spécifiez que le cinquième serveur peut stocker des dalles de MyVolume :

    Get-VirtualDisk MyVolume | Add-StorageFaultDomain -StorageFaultDomains $Servers[4]
    
  2. Spécifiez que le premier serveur ne peut pas stocker les dalles de MyVolume :

    Get-VirtualDisk MyVolume | Remove-StorageFaultDomain -StorageFaultDomains $Servers[0]
    
  3. Rééquilibrez le pool de stockage pour que la modification prenne effet :

    Get-StoragePool S2D* | Optimize-StoragePool
    

Vous pouvez surveiller la progression du rééquilibrage avec Get-StorageJob.

Une fois l’opération terminée, vérifiez que MyVolume a été déplacé en ré-exécutant Get-VirtualDiskFootprintBySSU.ps1.

PS C:\> .\Get-VirtualDiskFootprintBySSU.ps1

VirtualDiskFriendlyName TotalFootprint Server1 Server2 Server3 Server4 Server5 Server6
----------------------- -------------- ------- ------- ------- ------- ------- -------
MyVolume                300 GB         0       100 GB  100 GB  100 GB  100 GB  0

Notez que Server1 ne contient plus de dalles de MyVolume, à la place de Server5.

Meilleures pratiques

Voici les meilleures pratiques à suivre lors de l’utilisation de l’allocation de volume délimitée :

Choisir quatre serveurs

Délimitez chaque volume miroir triple à quatre serveurs, pas plus.

Équilibrer le stockage

Équilibrez la quantité de stockage allouée à chaque serveur, en tenant compte de la taille du volume.

Échelonner les volumes d’allocation délimités

Pour optimiser la tolérance de panne, rendez l’allocation de chaque volume unique, ce qui signifie qu’il ne partage pas tous ses serveurs avec un autre volume (certains chevauchements sont acceptables).

Par exemple sur un système à huit nœuds : Volume 1 : Serveurs 1, 2, 3, 4 Volume 2 : Serveurs 5, 6, 7, 8 Volume 3 : Serveurs 3, 4, 5, 6 Volume 4 : Serveurs 1, 2, 7, 8

Analyse

Cette section dérive la probabilité mathématique qu’un volume reste en ligne et accessible (ou, équivalent, la fraction attendue du stockage global qui reste en ligne et accessible) en fonction du nombre d’échecs et de la taille du cluster.

Notes

Cette section est facultative. Si vous avez envie de voir les données mathématiques, poursuivez votre lecture ! Mais si ce n’est pas le cas, ne vous inquiétez pas : l’utilisation dans PowerShell et les Meilleures pratiques sont tout ce dont vous avez besoin pour implémenter une allocation délimitée avec succès.

Jusqu’à deux échecs est toujours acceptable

Chaque volume miroir triple peut survivre jusqu’à deux défaillances en même temps, quelle que soit son allocation. Si deux lecteurs échouent, ou si deux serveurs tombent en panne, ou un de chacun, chaque volume miroir triple reste en ligne et accessible, même avec une allocation régulière.

Plus de la moitié des échecs du cluster ne sont jamais acceptables

À l’inverse, dans le cas extrême où plus de la moitié des serveurs ou lecteurs du cluster échouent en même temps, le quorum est perdu et chaque volume miroir triple passe hors connexion et devient inaccessible, quelle que soit son allocation.

Qu’en est-il entre les deux ?

Si au moins trois défaillances se produisent à la fois, mais qu’au moins la moitié des serveurs et des lecteurs sont toujours en place, les volumes avec une allocation délimitée peuvent rester en ligne et accessibles, selon les serveurs qui présentent des défaillances.

Forum aux questions

Puis-je délimiter certains volumes, mais pas d’autres ?

Oui. Vous pouvez choisir par volume de délimiter ou non l’allocation.

L'allocation délimitée modifie-t-elle le fonctionnement du remplacement des disques ?

Non, c’est la même chose qu’avec l’allocation régulière.

Références supplémentaires

Annexe

Ce script vous aide à voir comment vos volumes sont alloués.

Pour l’utiliser comme décrit ci-dessus, copiez/collez et enregistrez en tant que Get-VirtualDiskFootprintBySSU.ps1.

Function ConvertTo-PrettyCapacity {
    Param (
        [Parameter(
            Mandatory = $True,
            ValueFromPipeline = $True
            )
        ]
    [Int64]$Bytes,
    [Int64]$RoundTo = 0
    )
    If ($Bytes -Gt 0) {
        $Base = 1024
        $Labels = ("bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
        $Order = [Math]::Floor( [Math]::Log($Bytes, $Base) )
        $Rounded = [Math]::Round($Bytes/( [Math]::Pow($Base, $Order) ), $RoundTo)
        [String]($Rounded) + " " + $Labels[$Order]
    }
    Else {
        "0"
    }
    Return
}

Function Get-VirtualDiskFootprintByStorageFaultDomain {

    ################################################
    ### Step 1: Gather Configuration Information ###
    ################################################

    Write-Progress -Activity "Get-VirtualDiskFootprintByStorageFaultDomain" -CurrentOperation "Gathering configuration information..." -Status "Step 1/4" -PercentComplete 00

    $ErrorCannotGetCluster = "Cannot proceed because 'Get-Cluster' failed."
    $ErrorNotS2DEnabled = "Cannot proceed because the cluster is not running Storage Spaces Direct."
    $ErrorCannotGetClusterNode = "Cannot proceed because 'Get-ClusterNode' failed."
    $ErrorClusterNodeDown = "Cannot proceed because one or more cluster nodes is not Up."
    $ErrorCannotGetStoragePool = "Cannot proceed because 'Get-StoragePool' failed."
    $ErrorPhysicalDiskFaultDomainAwareness = "Cannot proceed because the storage pool is set to 'PhysicalDisk' fault domain awareness. This cmdlet only supports 'StorageScaleUnit', 'StorageChassis', or 'StorageRack' fault domain awareness."

    Try  {
        $GetCluster = Get-Cluster -ErrorAction Stop
    }
    Catch {
        throw $ErrorCannotGetCluster
    }

    If ($GetCluster.S2DEnabled -Ne 1) {
        throw $ErrorNotS2DEnabled
    }

    Try  {
        $GetClusterNode = Get-ClusterNode -ErrorAction Stop
    }
    Catch {
        throw $ErrorCannotGetClusterNode
    }

    If ($GetClusterNode | Where State -Ne Up) {
        throw $ErrorClusterNodeDown
    }

    Try {
        $GetStoragePool = Get-StoragePool -IsPrimordial $False -ErrorAction Stop
    }
    Catch {
        throw $ErrorCannotGetStoragePool
    }

    If ($GetStoragePool.FaultDomainAwarenessDefault -Eq "PhysicalDisk") {
        throw $ErrorPhysicalDiskFaultDomainAwareness
    }

    ###########################################################
    ### Step 2: Create SfdList[] and PhysicalDiskToSfdMap{} ###
    ###########################################################

    Write-Progress -Activity "Get-VirtualDiskFootprintByStorageFaultDomain" -CurrentOperation "Analyzing physical disk information..." -Status "Step 2/4" -PercentComplete 25

    $SfdList = Get-StorageFaultDomain -Type ($GetStoragePool.FaultDomainAwarenessDefault) | Sort FriendlyName # StorageScaleUnit, StorageChassis, or StorageRack

    $PhysicalDiskToSfdMap = @{} # Map of PhysicalDisk.UniqueId -> StorageFaultDomain.FriendlyName
    $SfdList | ForEach {
        $StorageFaultDomain = $_
        $_ | Get-StorageFaultDomain -Type PhysicalDisk | ForEach {
            $PhysicalDiskToSfdMap[$_.UniqueId] = $StorageFaultDomain.FriendlyName
        }
    }

    ##################################################################################################
    ### Step 3: Create VirtualDisk.FriendlyName -> { StorageFaultDomain.FriendlyName -> Size } Map ###
    ##################################################################################################

    Write-Progress -Activity "Get-VirtualDiskFootprintByStorageFaultDomain" -CurrentOperation "Analyzing virtual disk information..." -Status "Step 3/4" -PercentComplete 50

    $GetVirtualDisk = Get-VirtualDisk | Sort FriendlyName

    $VirtualDiskMap = @{}

    $GetVirtualDisk | ForEach {
        # Map of PhysicalDisk.UniqueId -> Size for THIS virtual disk
        $PhysicalDiskToSizeMap = @{}
        $_ | Get-PhysicalExtent | ForEach {
            $PhysicalDiskToSizeMap[$_.PhysicalDiskUniqueId] += $_.Size
        }
        # Map of StorageFaultDomain.FriendlyName -> Size for THIS virtual disk
        $SfdToSizeMap = @{}
        $PhysicalDiskToSizeMap.keys | ForEach {
            $SfdToSizeMap[$PhysicalDiskToSfdMap[$_]] += $PhysicalDiskToSizeMap[$_]
        }
        # Store
        $VirtualDiskMap[$_.FriendlyName] = $SfdToSizeMap
    }

    #########################
    ### Step 4: Write-Out ###
    #########################

    Write-Progress -Activity "Get-VirtualDiskFootprintByStorageFaultDomain" -CurrentOperation "Formatting output..." -Status "Step 4/4" -PercentComplete 75

    $Output = $GetVirtualDisk | ForEach {
        $Row = [PsCustomObject]@{}

        $VirtualDiskFriendlyName = $_.FriendlyName
        $Row | Add-Member -MemberType NoteProperty "VirtualDiskFriendlyName" $VirtualDiskFriendlyName

        $TotalFootprint = $_.FootprintOnPool | ConvertTo-PrettyCapacity
        $Row | Add-Member -MemberType NoteProperty "TotalFootprint" $TotalFootprint

        $SfdList | ForEach {
            $Size = $VirtualDiskMap[$VirtualDiskFriendlyName][$_.FriendlyName] | ConvertTo-PrettyCapacity
            $Row | Add-Member -MemberType NoteProperty $_.FriendlyName $Size
        }

        $Row
    }

    # Calculate width, in characters, required to Format-Table
    $RequiredWindowWidth = ("TotalFootprint").length + 1 + ("VirtualDiskFriendlyName").length + 1
    $SfdList | ForEach {
        $RequiredWindowWidth += $_.FriendlyName.Length + 1
    }

    $ActualWindowWidth = (Get-Host).UI.RawUI.WindowSize.Width

    If (!($ActualWindowWidth)) {
        # Cannot get window width, probably ISE, Format-List
        Write-Warning "Could not determine window width. For the best experience, use a Powershell window instead of ISE"
        $Output | Format-Table
    }
    ElseIf ($ActualWindowWidth -Lt $RequiredWindowWidth) {
        # Narrower window, Format-List
        Write-Warning "For the best experience, try making your PowerShell window at least $RequiredWindowWidth characters wide. Current width is $ActualWindowWidth characters."
        $Output | Format-List
    }
    Else {
        # Wider window, Format-Table
        $Output | Format-Table
    }
}

Get-VirtualDiskFootprintByStorageFaultDomain