Dela via


Avgränsa allokeringen av volymer i Lagringsdirigering

Windows Server 2019 introducerar ett alternativ för att manuellt avgränsa allokeringen av volymer i Lagringsdirigering. Detta kan avsevärt öka feltoleransen under vissa förhållanden, men medför vissa extra hanteringsöverväganden och komplexitet. Det här avsnittet förklarar hur det fungerar och ger exempel i PowerShell.

Important

Den här funktionen är ny i Windows Server 2019. Den är inte tillgänglig i Windows Server 2016.

Prerequisites

Grön bockmarkeringsikon. Överväg att använda det här alternativet om:

Röd X-ikon. Använd inte det här alternativet om:

Understand

Översyn: regelbunden tilldelning

Med vanlig trevägsspegling delas volymen in i många små "sektioner" som kopieras tre gånger och distribueras jämnt över varje enhet på varje server i klustret. Mer information finns i den här djupdykningsbloggen.

Diagram som visar volymen som delas in i tre staplar med plattor och distribueras jämnt över varje server.

Den här standardallokeringen maximerar parallella läsningar och skrivningar, vilket leder till bättre prestanda och är tilltalande i sin enkelhet: varje server är lika upptagen, varje enhet är lika full och alla volymer är online eller går offline tillsammans. Varje volym kommer garanterat att överleva upp till två samtidiga fel, vilket illustreras i de här exemplen .

Men med den här allokeringen kan volymerna inte klara sig vid tre samtidiga misslyckanden. Om tre servrar misslyckas samtidigt, eller om enheter på tre servrar misslyckas samtidigt, blir volymerna otillgängliga eftersom åtminstone vissa plattor (med mycket hög sannolikhet) allokerades till exakt tre enheter eller servrar som misslyckades.

I exemplet nedan misslyckas servrarna 1, 3 och 5 samtidigt. Även om många plattor har bevarade kopior, har vissa inte det:

Diagram som visar tre av sex servrar markerade i rött och den totala volymen är röd.

Volymen går offline och blir otillgänglig tills servrarna återställs.

Ny: avgränsad allokering

Med avgränsad allokering anger du en delmängd servrar som ska användas (minst fyra). Volymen är uppdelad i plattor som kopieras tre gånger, som tidigare, men i stället för att allokeras över varje server allokeras plattor endast till den delmängd av servrar som du anger.

Om du till exempel har ett kluster med 8 noder (noder 1 till och med 8) kan du ange att en volym endast ska finnas på diskar i noderna 1, 2, 3, 4.

Advantages

Med exempelallokeringen kommer volymen sannolikt att överleva tre samtidiga fel. Om noderna 1, 2 och 6 går ned är endast 2 av noderna som innehåller de 3 kopiorna av data för volymen nere och volymen är online.

Överlevnadssannolikhet beror på antalet servrar och andra faktorer – mer information finns i Analys .

Disadvantages

Avgränsad allokering medför vissa ytterligare hanteringsöverväganden och komplexitet:

  1. Administratören ansvarar för att avgränsa allokeringen av varje volym för att balansera lagringsanvändningen mellan servrar och upprätthålla hög sannolikhet för överlevnad, enligt beskrivningen i avsnittet Metodtips .

  2. Med avgränsad allokering reserverar du motsvarande en kapacitetsenhet per server (utan maxvärde).. Det här är mer än den publicerade rekommendationen för regelbunden allokering, som maxar till totalt fyra kapacitetsenheter.

  3. Om en server misslyckas och behöver ersättas, enligt beskrivningen i Ta bort en server och dess enheter, ansvarar administratören för att uppdatera avgränsningen av berörda volymer genom att lägga till den nya servern och ta bort den misslyckade - exemplet nedan.

Användning i PowerShell

Du kan använda cmdleten New-Volume för att skapa volymer i Lagringsdirigering.

Om du till exempel vill skapa en standard trevägsspeglingsvolym:

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

Skapa en volym och avgränsa dess allokering

Så här skapar du en trevägsspeglingsvolym och avgränsar dess allokering:

  1. Tilldela först servrarna i klustret till variabeln $Servers:

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

    Tip

    I Storage Spaces Direct avser termen "Lagringsskalningsenhet" all rålagring ansluten till en server, inklusive direktanslutna diskar och direktanslutna externa kapslingar med diskar. I det här sammanhanget är det samma som "server".

  2. Ange vilka servrar som ska användas med den nya -StorageFaultDomainsToUse parametern och genom att indexera till $Servers. Om du till exempel vill avgränsa allokeringen till den första, andra, tredje och fjärde servern (index 0, 1, 2 och 3):

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

Se en avgränsad allokering

Om du vill se hur MyVolume allokeras använder du skriptet Get-VirtualDiskFootprintBySSU.ps1 i bilaga:

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

Observera att endast Server1, Server2, Server3 och Server4 innehåller plattor av MyVolume.

Ändra en avgränsad allokering

Använd de nya Add-StorageFaultDomain cmdletarna och Remove-StorageFaultDomain för att ändra hur allokeringen avgränsas.

Om du till exempel vill flytta MyVolume via en server:

  1. Ange att den femte servern kan lagra plattor i MyVolume:

    Get-VirtualDisk MyVolume | Add-StorageFaultDomain -StorageFaultDomains $Servers[4]
    
  2. Ange att den första servern inte kan lagra plattor i MyVolume:

    Get-VirtualDisk MyVolume | Remove-StorageFaultDomain -StorageFaultDomains $Servers[0]
    
  3. Balansera om lagringspoolen så att ändringen börjar gälla:

    Get-StoragePool S2D* | Optimize-StoragePool
    

Du kan övervaka förloppet för ombalanseringen med Get-StorageJob.

När det är klart kontrollerar du att MyVolume har flyttats genom att köra Get-VirtualDiskFootprintBySSU.ps1 igen.

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

Observera att Server1 inte längre innehåller plattor av MyVolume – i stället gör Server5 det.

Metodtips

Här följer metodtipsen när du använder avgränsad volymallokering:

Välj fyra servrar

Avgränsa varje trevägsspeglingsvolym till fyra servrar, inte mer.

Balansera lagring

Balansera hur mycket lagringsutrymme som allokeras till varje server, med hänsyn till volymstorleken.

Avgränsade volymer för stegvis allokering

För att maximera feltoleransen gör du varje volyms allokering unik, vilket innebär att den inte delar alla sina servrar med en annan volym (viss överlappning är okej).

Exempel på ett system med åtta noder: Volym 1: Servrar 1, 2, 3, 4 Volym 2: Servrar 5, 6, 7, 8 Volym 3: Servrar 3, 4, 5, 6 Volym 4: Servrar 1, 2, 7, 8

Analysis

Det här avsnittet härleder den matematiska sannolikheten att en volym förblir online och tillgänglig (eller motsvarande den förväntade delen av den totala lagringen som är online och tillgänglig) som en funktion av antalet fel och klusterstorleken.

Note

Det här avsnittet är valfri läsning. Om du är angelägen om att se matematiken, läs vidare! Men om inte, oroa dig inte: Användning i PowerShell och metodtips är allt du behöver för att implementera avgränsad allokering.

Upp till två fel är alltid okej

Varje trevägsspeglingsvolym kan klara av upp till två fel samtidigt, oavsett allokering. Om två enheter misslyckas, eller om två servrar misslyckas, eller en av varje, förblir varje trevägsspeglingsvolym online och tillgänglig, även med vanlig allokering.

Mer än hälften av klustrets misslyckanden är aldrig okej

I det extrema fallet att mer än hälften av servrarna eller diskarna i klustret misslyckas samtidigt förloras kvorumet och varje trevägsspeglingsvolym stängs av och blir otillgänglig, oavsett dess allokering.

Hur är det däremellan?

Om tre eller fler fel inträffar samtidigt, men minst hälften av servrarna och enheterna fortfarande är igång, kan volymer med avgränsad allokering förbli online och tillgängliga, beroende på vilka servrar som har fel.

Vanliga frågor

Kan jag avgränsa vissa volymer men inte andra?

Yes. Du kan välja per volym om du vill avgränsa allokeringen eller inte.

Påverkar begränsad allokering hur byte av enhet sker?

Nej, det är samma som med vanlig allokering.

Ytterligare referenser

Appendix

Det här skriptet hjälper dig att se hur dina volymer allokeras.

Om du vill använda det enligt beskrivningen ovan kopierar/klistrar du in och sparar som 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