Partilhar via


Delimitar a alocação de volumes nos Espaços de Armazenamento Diretos

O Windows Server 2019 apresenta uma opção de delimitar manualmente a alocação de volumes nos Espaços de Armazenamento Diretos. Isso pode aumentar significativamente a tolerância a falhas em determinadas condições, mas impõe algumas considerações adicionais de gerenciamento e complexidade. Este tópico explica como isso funciona e fornece exemplos no PowerShell.

Importante

Este recurso é novo no Windows Server 2019. Ele não está disponível no Windows Server 2016.

Pré-requisitos

Ícone de marca de seleção verde. Considere usar essa opção se:

  • Seu cluster tiver seis ou mais servidores; e
  • Seu cluster usar apenas resiliência de espelho de três vias

Ícone X vermelho. Não use esta opção se:

Entenda

Revisão: alocação regular

Com o espelhamento de três vias regular, o volume é dividido em muitos pequenos "blocos" que são copiados três vezes e distribuídos uniformemente em cada unidade em cada servidor no cluster. Para obter mais detalhes, leia este blog de aprofundamento.

Diagrama mostrando o volume sendo dividido em três pilhas de blocos e distribuído uniformemente em todos os servidores.

Essa alocação padrão maximiza leituras e gravações paralelas, levando a um melhor desempenho e é atraente em sua simplicidade: cada servidor está igualmente ocupado, cada unidade está igualmente cheia e todos os volumes permanecem online ou ficam offline juntos. Cada volume tem a garantia de sobreviver a até duas falhas simultâneas, como ilustram esses exemplos.

No entanto, com essa alocação, os volumes não podem sobreviver a três falhas simultâneas. Se três servidores falharem ao mesmo tempo ou se as unidades em três servidores falharem ao mesmo tempo, os volumes se tornarão inacessíveis porque pelo menos alguns blocos foram (com probabilidade muito alta) alocados para as exatas três unidades ou servidores que falharam.

No exemplo a seguir, os servidores 1, 3 e 5 falham ao mesmo tempo. Embora muitos blocos tenham cópias sobreviventes, alguns não:

Diagrama mostrando três dos seis servidores realçados em vermelho e o volume geral está vermelho.

O volume fica offline e se torna inacessível até que os servidores sejam recuperados.

Novo: alocação delimitada

Com a alocação delimitada, você especifica um subconjunto de servidores a serem usados (no mínimo quatro). O volume é dividido em blocos que são copiados três vezes, como antes, mas em vez de alocar em todos os servidores, os blocos são alocados apenas para o subconjunto de servidores que você especificar.

Por exemplo, se você tiver um cluster de 8 nós (nós de 1 a 8), poderá especificar que um volume seja localizado apenas nos discos dos nós 1, 2, 3 e 4.

Vantagens

Com a alocação de exemplo, é provável que o volume sobreviva a três falhas simultâneas. Se os nós 1, 2 e 6 ficarem inativos, apenas dois dos nós que contêm as três cópias de dados do volume ficarão inativos e o volume permanecerá online.

A probabilidade de sobrevivência depende do número de servidores e de outros fatores. Consulte Análise para obter detalhes.

Desvantagens

A alocação delimitada impõe algumas considerações de gerenciamento e complexidade adicionais:

  1. O administrador é responsável por delimitar a alocação de cada volume para equilibrar a utilização de armazenamento entre servidores e manter a alta probabilidade de sobrevivência, conforme descrito na seção Práticas recomendadas.

  2. Com alocação delimitada, reserve o equivalente a uma unidade de capacidade por servidor (sem máximo). Isso é mais do que a recomendação publicada para alocação regular, que atinge o máximo de quatro unidades de capacidade no total.

  3. Se um servidor falhar e precisar ser substituído, conforme descrito em Remover um servidor e suas unidades, o administrador será responsável por atualizar a delimitação dos volumes afetados adicionando o novo servidor e removendo o servidor com falha – veja o exemplo abaixo.

Uso no PowerShell

Você pode usar o cmdlet New-Volume para criar volumes nos Espaços de Armazenamento Diretos.

Por exemplo, para criar um volume espelho de três vias regular:

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

Criar um volume e delimitar sua alocação

Para criar um volume espelho de três vias e delimitar sua alocação:

  1. Primeiro, atribua os servidores no cluster à variável $Servers:

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

    Dica

    Nos Espaços de Armazenamento Diretos, o termo "Unidade de Escala de Armazenamento" refere-se a todo o armazenamento bruto anexado a um servidor, incluindo unidades conectadas diretas e compartimentos externos conectados diretamente com unidades. Nesse contexto, é o mesmo que "servidor".

  2. Especifique quais servidores usar com o novo parâmetro -StorageFaultDomainsToUse e indexando em $Servers. Por exemplo, para delimitar a alocação para o primeiro, segundo, terceiro e quarto servidores (índices 0, 1, 2 e 3):

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

Ver uma alocação delimitada

Para ver como MyVolume está alocado, use o script Get-VirtualDiskFootprintBySSU.ps1 no Apêndice:

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

Observe que somente Server1, Server2, Server3 e Server4 contêm blocos de MyVolume.

Alterar uma alocação delimitada

Use os novos cmdlets Add-StorageFaultDomain e Remove-StorageFaultDomain para alterar a forma como a alocação é delimitada.

Por exemplo, para mover MyVolume por um servidor:

  1. Especifique que o quinto servidor pode armazenar blocos de MyVolume:

    Get-VirtualDisk MyVolume | Add-StorageFaultDomain -StorageFaultDomains $Servers[4]
    
  2. Especifique que o primeiro servidor não pode armazenar blocos de MyVolume:

    Get-VirtualDisk MyVolume | Remove-StorageFaultDomain -StorageFaultDomains $Servers[0]
    
  3. Redistribuir o pool de armazenamento para que a alteração entre em vigor:

    Get-StoragePool S2D* | Optimize-StoragePool
    

Você pode monitorar o progresso da redistribuição com Get-StorageJob.

Depois de concluído, verifique se MyVolume foi movido executando Get-VirtualDiskFootprintBySSU.ps1 novamente.

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

Observe que Server1 não contém mais blocos de MyVolume – em vez disso, o Server5 passa a conter os blocos.

Práticas recomendadas

Estas são as práticas recomendadas a serem seguidas ao usar a alocação de volume delimitada:

Escolha quatro servidores

Delimite cada volume espelho de três vias para quatro servidores, não mais do que isso.

Balanceie o armazenamento

Balanceie a quantidade de armazenamento alocada para cada servidor, contabilizando o tamanho do volume.

Escalone volumes de alocação delimitados

Para maximizar a tolerância a falhas, torne a alocação de cada volume exclusiva, o que significa que ele não compartilha todos os seus servidores com outro volume (alguma sobreposição é aceitável).

Por exemplo, em um sistema de oito nós: Volume 1: Servidores 1, 2, 3, 4 Volume 2: Servidores 5, 6, 7, 8 Volume 3: Servidores 3, 4, 5, 6 Volume 4: Servidores 1, 2, 7, 8

Análise

Esta seção deriva a probabilidade matemática de que um volume permaneça online e acessível (ou, de forma equivalente, a fração esperada do armazenamento geral que permanece online e acessível) como uma função do número de falhas e do tamanho do cluster.

Observação

Esta seção é uma leitura opcional. Se você está ansioso para ver a matemática, continue! Mas, caso contrário, não se preocupe: o uso no PowerShell e as práticas recomendadas são tudo o que você precisa para implementar a alocação delimitada com êxito.

Até duas falhas é sempre aceitável

Cada volume espelho de três vias pode sobreviver a até duas falhas ao mesmo tempo, independentemente de sua alocação. Se duas unidades falharem, ou dois servidores falharem, ou um de cada, cada volume espelho de três vias permanecerá online e acessível, mesmo com alocação regular.

Mais da metade do cluster com falha nunca é aceitável

Por outro lado, no caso extremo de que mais da metade dos servidores ou unidades no cluster falham ao mesmo tempo, o quorum é perdido e cada volume espelho de três vias fica offline e se torna inacessível, independentemente de sua alocação.

E quanto ao meio termo?

Se três ou mais falhas ocorrerem ao mesmo tempo, mas pelo menos metade dos servidores e as unidades ainda estiverem ativas, os volumes com alocação delimitada poderão permanecer online e acessíveis, dependendo de quais servidores tiverem falhas.

Perguntas frequentes

Posso delimitar alguns volumes, mas não outros?

Sim. Você pode escolher por volume se deseja ou não delimitar a alocação.

A alocação delimitada altera o funcionamento da substituição de unidade?

Não, é o mesmo que com alocação regular.

Referências adicionais

Apêndice

Esse script ajuda você a ver como os volumes estão alocados.

Para usá-lo conforme descrito acima, copie/cole e salve como 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