Sdílet prostřednictvím


Vymezit přidělování svazků ve Storage Spaces Direct

Windows Server 2019 zavádí možnost ručního vymezení přidělení svazků ve Storage Spaces Direct. To může za určitých podmínek výrazně zvýšit odolnost proti chybám, ale přináší některé další aspekty správy a složitost. Toto téma vysvětluje, jak funguje, a poskytuje příklady v PowerShellu.

Important

Tato funkce je nová ve Windows Serveru 2019. Není k dispozici ve Windows Serveru 2016.

Prerequisites

Zelená ikona zaškrtnutí Zvažte použití této možnosti, pokud:

Červená ikona X. Tuto možnost nepoužívejte, pokud:

Understand

Přehled: pravidelné přidělování

S pravidelným trojcestným zrcadlením je svazek rozdělený do mnoha malých "bloků", které se třikrát kopírují a rovnoměrně rozmístěny na každý disk na každém serveru v clusteru. Další podrobnosti najdete v tomto podrobném blogu.

Diagram znázorňující rozdělení objemu do tří vrstev desek a rovnoměrné rozložení mezi všechny servery.

Toto výchozí přidělení maximalizuje paralelní čtení a zápisy, což vede k lepšímu výkonu a je atraktivní ve své jednoduchosti: každý server je stejně zaneprázdněný, každý disk je stejně plný a všechny svazky zůstávají online nebo jsou offline společně. U každého svazku je zaručeno, že přežije až dvě souběžná selhání, jak je znázorněno v těchto příkladech .

S tímto přidělením ale svazky nemohou přežít tři souběžné selhání. Pokud tři servery selže najednou nebo pokud jednotky na třech serverech selže najednou, svazky se stanou nedostupnými, protože alespoň některé desky byly (s velmi vysokou pravděpodobností) přiděleny přesně třem jednotkám nebo serverům, které selhaly.

V následujícím příkladu servery 1, 3 a 5 současně selžou. I když mnoho desek má přeživší kopie, některé ne:

Diagram znázorňující tři ze šesti serverů zvýrazněných červeně a celkový objem je červený.

Svazek přejde do offline režimu a bude nedostupný, dokud se servery neobnoví.

Nové: oddělená alokace

Při omezeném přidělení zadáte podmnožinu serverů, které mají být použity (minimálně čtyři). Svazek je rozdělený na desky, které se kopírují třikrát, stejně jako předtím, ale místo přidělování přes každý server jsou desky přiděleny pouze podmnožině serverů, které zadáte.

Pokud máte například cluster s 8 uzly (uzly 1 až 8), můžete určit svazek, který se má nacházet pouze na discích v uzlech 1, 2, 3, 4.

Advantages

V případě ukázkového přidělení existuje pravděpodobnost, že svazek přežije tři souběžná selhání. Pokud uzly 1, 2 a 6 přestanou fungovat, dojde ke snížení počtu pouze 2 uzlů, které obsahují 3 kopie dat svazku, a svazek zůstane online.

Pravděpodobnost přežití závisí na počtu serverů a dalších faktorech – podrobnosti najdete v části Analýza .

Disadvantages

Vyhrazené přidělení ukládá další úvahy o správě a složitosti:

  1. Správce zodpovídá za oddělení přidělení jednotlivých svazků k vyvážení využití úložiště mezi servery a k zajištění vysoké pravděpodobnosti přežití, jak je popsáno v části Osvědčené postupy .

  2. Při členění přidělování si vyhraďte ekvivalent jednoho kapacitního disku na server (bez omezení). Toto je více než publikované doporučení pro pravidelné přidělení, které stanovuje maximálně čtyři jednotky kapacity celkem.

  3. Pokud server selže a je potřeba ho nahradit, jak je popsáno v části Odebrání serveru a jeho jednotek, je správce zodpovědný za aktualizaci oddělovače ovlivněných svazků přidáním nového serveru a odebráním neúspěšného svazku – příklad níže.

Použití v PowerShellu

Pomocí této New-Volume rutiny můžete vytvářet svazky ve Storage Spaces Direct.

Pokud chcete například vytvořit standardní trojcestný zrcadlový svazek:

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

Vytvoření svazku a omezení jeho přidělení

Pro vytvoření trojcestného zrcadlového svazku a vymezení jeho přidělení:

  1. Nejprve přiřaďte servery v clusteru k proměnné $Servers:

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

    Tip

    V Storage Spaces Direct označuje termín "Jednotka škálování úložiště" veškeré nezpracované úložiště připojené k jednomu serveru, včetně disků s přímým připojením a externích skříní s přímým připojením. V tomto kontextu je to stejné jako "server".

  2. Určete servery, které použijete s novým parametrem -StorageFaultDomainsToUse a indexováním do $Servers. Pokud chcete například oddělovat přidělení na první, druhý, třetí a čtvrtý server (indexy 0, 1, 2 a 3):

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

Podívat se na oddělené přidělení

Pokud chcete zjistit, jak je myVolume přidělen, použijte Get-VirtualDiskFootprintBySSU.ps1 skript v dodatku:

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

Všimněte si, že pouze Server1, Server2, Server3 a Server4 obsahují desky MyVolume.

Změna přidělení s oddělovači

Použijte nové cmdlety Add-StorageFaultDomain a Remove-StorageFaultDomain ke změně způsobu, jakým je alokace ohraničena.

Pokud chcete například přesunout MyVolume o jeden server:

  1. Určete, že pátý server může ukládat v blocích MyVolume:

    Get-VirtualDisk MyVolume | Add-StorageFaultDomain -StorageFaultDomains $Servers[4]
    
  2. Určete, že první server nemůže uložit slaby MyVolume:

    Get-VirtualDisk MyVolume | Remove-StorageFaultDomain -StorageFaultDomains $Servers[0]
    
  3. Změna rovnováhy fondu úložiště, aby se změna projevila:

    Get-StoragePool S2D* | Optimize-StoragePool
    

Můžete sledovat průběh vyrovnávání s Get-StorageJob.

Po dokončení ověřte, že MyVolume byl přesunut, tím, že spustíte Get-VirtualDiskFootprintBySSU.ps1 znovu.

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

Všimněte si, že Server1 už neobsahuje části MyVolume – naopak, Server5 ano.

Osvědčené postupy

Tady jsou osvědčené postupy pro použití přidělování svazků s definovanými hranicemi:

Výběr čtyř serverů

Omezte každý třícestný zrcadlený svazek na čtyři servery, ne více.

Vyvážené úložiště

Vyvažte, kolik úložiště je přiděleno jednotlivým serverům, s ohledem na velikost svazku.

Postupné rozdělení přidělených objemů s vymezenými hranicemi

Pokud chcete maximalizovat odolnost proti chybám, udělte každému svazku jedinečnou alokaci, což znamená, že nesdílí všechny servery s jiným svazkem (některé překrytí jsou v pořádku).

Například v systému s osmi uzly: Svazek 1: Servery 1, 2, 3, 4 Svazek 2: Servery 5, 6, 7, 8 Svazky 3: Servery 3, 4, 5, 6 Svazek 4: Servery 1, 2, 7, 8

Analysis

Tato část odvozuje matematickou pravděpodobnost, že svazek zůstává online a přístupný (neboli ekvivalentní, očekávaný zlomek celkového úložiště, který zůstane online a přístupný) jako funkce počtu selhání a velikosti clusteru.

Note

Tato část je volitelná pro čtení. Pokud se chcete podívat na matematiku, čtěte dál! Pokud ne, nemějte obavy: Použití v PowerShellu a osvědčené postupy jsou všechno, co potřebujete k úspěšné implementaci přidělení s oddělovači.

Maximálně dvě selhání jsou vždy v pořádku.

Každý trojcestný zrcadlový svazek dokáže přežít až dvě selhání najednou bez ohledu na přidělení. Pokud selžou dva disky, nebo dva servery, nebo jeden z každého, zůstane každý trojcestný zrcadlový svazek online a přístupný i s běžným přidělením.

Selhává-li více než polovina clusteru, to není nikdy v pořádku.

Oproti tomu v krajním případě, kdy více než polovina serverů nebo jednotek v clusteru náhle selže, dojde ke ztrátě kvora a každý trojcestný zrcadlový svazek přejde do režimu offline a stane se nepřístupným, bez ohledu na jeho přidělení.

Co mezi tím?

Pokud najednou dojde ke třem nebo více selháním, ale alespoň polovina serverů a jednotek je stále funkční, svazky s vymezenou alokací mohou zůstat online a přístupné v závislosti na tom, které servery selhaly.

Nejčastější dotazy

Můžu některé svazky oddělovat, ale ne jiné?

Yes. Pro jednotlivé svazky můžete zvolit, zda chcete omezit přidělené zdroje.

Mění alokace s omezením způsob, jak funguje výměna disků?

Ne, je to stejné jako s pravidelným přidělováním.

Další odkazy

Appendix

Tento skript vám pomůže zobrazit, jak se vaše objemové disky přidělují.

Chcete-li jej použít, jak je popsáno výše, zkopírujte a vložte a uložte jako 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