다음을 통해 공유


저장소 공간 Direct에서 볼륨 할당 구분

Windows Server 2019에는 저장소 공간 Direct에서 볼륨 할당을 수동으로 구분하는 옵션이 도입되었습니다. 이렇게 하면 특정 조건에서 내결함성을 크게 높일 수 있지만 몇 가지 관리 고려 사항 및 복잡성이 추가됩니다. 이 항목에서는 작동 방식을 설명하고 PowerShell의 예제를 제공합니다.

Important

이 기능은 Windows Server 2019의 새로운 기능입니다. Windows Server 2016에서는 사용할 수 없습니다.

필수 조건

녹색 확인 표시 아이콘 입니다. 다음과 같은 경우 이 옵션을 사용하는 것이 좋습니다.

  • 클러스터에는 6개 이상의 서버가 있습니다. 그리고
  • 클러스터는 3방향 미러 복원력만 사용합니다.

빨간색 X 아이콘입니다. 이 경우 이 생성자를 사용하지 마세요.

이해

검토: 일반 할당

일반 3방향 미러링을 사용하면 볼륨이 세 번 복사되고 클러스터의 모든 서버의 모든 드라이브에 균등하게 분산되는 많은 작은 "슬래브"로 나뉩니다. 자세한 내용은 이 딥 다이브 블로그를 참조하세요.

세 개의 슬래브 스택으로 분할되고 모든 서버에 균등하게 분산되는 볼륨을 보여 주는 다이어그램.

이 기본 할당은 병렬 읽기 및 쓰기를 최대화하여 성능이 향상되며, 모든 서버가 동일하게 사용 중이고, 모든 드라이브가 균등하게 꽉 찼으며, 모든 볼륨이 온라인 상태를 유지하거나 함께 오프라인으로 전환되므로 편의상 매력적입니다. 이러한 예제에서 알 수 있듯이 모든 볼륨은 최대 두 번의 동시 오류에서 살아남을 수 있습니다 .

그러나 이 할당을 사용하면 볼륨이 세 번의 동시 실패에서 살아남을 수 없습니다. 세 개의 서버가 한 번에 실패하거나 3대의 서버에서 드라이브가 한 번에 실패하는 경우, 실패한 정확한 3개의 드라이브 또는 서버에 적어도 일부 슬래브가 할당되었기 때문에 볼륨에 액세스할 수 없게 됩니다.

아래 예제에서는 서버 1, 3 및 5가 동시에 실패합니다. 많은 슬래브에는 복사본이 남아 있지만 일부는 다음을 수행하지 않습니다.

6개 서버 중 3개가 빨간색으로 강조 표시되고 전체 볼륨이 빨간색으로 표시된 다이어그램

볼륨이 오프라인 상태가 되고 서버가 복구될 때까지 액세스할 수 없게 됩니다.

새로 만들기: 구분된 할당

구분된 할당을 사용하면 사용할 서버의 하위 집합(최소 4개)을 지정합니다. 볼륨은 이전과 같이 세 번 복사되는 슬래브로 나뉘지만, 모든 서버에 할당하는 대신, 슬래브는 지정한 서버의 하위 집합에만 할당됩니다.

예를 들어 노드 클러스터가 8개(노드 1~8)인 경우 노드 1, 2, 3, 4의 디스크에만 배치할 볼륨을 지정할 수 있습니다.

장점

예제 할당을 사용하면 볼륨이 세 번의 동시 실패에서 살아남을 수 있습니다. 노드 1, 2 및 6이 다운되면 볼륨에 대한 3개의 데이터 복사본을 보유하는 노드 중 2개만 다운되고 볼륨이 온라인 상태로 유지됩니다.

생존 확률은 서버 수 및 기타 요인에 따라 달라집니다. 자세한 내용은 분석을 참조하세요.

단점

구분된 할당은 몇 가지 추가된 관리 고려 사항 및 복잡성을 적용합니다.

  1. 관리자는 모범 사례 섹션에 설명된 대로 서버 간에 스토리지 사용률의 균형을 맞추고 생존 확률이 높도록 각 볼륨의 할당을 구분할 책임이 있습니다.

  2. 구분된 할당을 사용하여 서버당 하나의 용량 드라이브에 해당하는 용량 드라이브(최대값 없음)를 예약합니다. 이는 총 4개의 용량 드라이브에서 최대로 계산되는 일반 할당에 대해 게시된 권장 사항보다 많은 수입니다.

  3. 서버 및 해당 드라이브 제거에 설명된 대로 서버가 실패하고 교체해야 하는 경우 관리자는 새 서버를 추가하고 실패한 서버를 제거하여 영향을 받는 볼륨의 구분을 업데이트할 책임이 있습니다(아래 예).

PowerShell의 사용량

New-Volume cmdlet을 사용하여 저장소 공간 Direct에서 볼륨을 만들 수 있습니다.

예를 들어, 일반 3방향 미러 볼륨을 만들려면:

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

볼륨을 만들고 해당 할당을 구분합니다.

3방향 미러 볼륨을 만들고 할당을 구분하려면 다음을 수행합니다.

  1. 먼저 클러스터의 서버를 변수 $Servers에 할당합니다.

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

    저장소 공간 Direct에서 '스토리지 배율 단위'라는 용어는 직접 연결된 드라이브와 드라이브가 있는 직접 연결된 외부 엔클로저를 포함하여 하나의 서버에 연결된 모든 원시 스토리지를 의미합니다. 이 컨텍스트에서는 '서버'와 동일합니다.

  2. -StorageFaultDomainsToUse 매개 변수를 $Servers에 인덱싱하여 사용할 서버를 지정합니다. 예를 들어 할당을 첫 번째, 두 번째, 세 번째 및 네 번째 서버(인덱스 0, 1, 2 및 3)로 구분합니다.

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

구분된 할당 참조

MyVolume이 할당되는 방법을 확인하려면 부록Get-VirtualDiskFootprintBySSU.ps1스크립트를 사용합니다.

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

Server1, Server2, Server3 및 Server4에만 MyVolume의 슬래브가 포함되어 있습니다.

구분된 할당 변경

Add-StorageFaultDomainRemove-StorageFaultDomain cmdlet을 사용하여 할당이 구분되는 방식을 변경합니다.

예를 들어 MyVolume을 한 서버로 이동하려면 다음을 수행합니다.

  1. 다섯 번째 서버가 MyVolume의 슬래브를 저장할 수 있도록 지정합니다.

    Get-VirtualDisk MyVolume | Add-StorageFaultDomain -StorageFaultDomains $Servers[4]
    
  2. 첫번째 서버가 MyVolume의 슬래브를 저장할 수 없도록 지정합니다.

    Get-VirtualDisk MyVolume | Remove-StorageFaultDomain -StorageFaultDomains $Servers[0]
    
  3. 변경 내용이 적용되도록 스토리지 풀의 균형을 다시 조정합니다.

    Get-StoragePool S2D* | Optimize-StoragePool
    

Get-StorageJob를 사용한 재조정의 진행률을 모니터링할 수 있습니다.

완료되면 MyVolumeGet-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

Server1에는 MyVolume의 슬래브가 더 이상 포함되어 있지 않습니다. 대신 Server5가 작업을 수행합니다.

모범 사례

구분된 볼륨 할당을 사용할 때 따라야 할 모범 사례는 다음과 같습니다.

서버 4개 선택

각 3방향 미러 볼륨을 4개의 서버로 구분합니다.

스토리지 균형 조정

볼륨 크기를 고려하여 각 서버에 할당되는 스토리지의 양과 균형을 유지합니다.

분리된 할당 볼륨 스태거

내결함성을 최대화하려면 각 볼륨의 할당을 고유하게 지정합니다. 즉, 모든 서버를 다른 볼륨과 공유하지는 않습니다(일부 겹치는 것은 괜찮습니다).

예를 들어 8노드 시스템의 경우: 볼륨 1: 서버 1, 2, 3, 4 볼륨 2: 서버 5, 6, 7, 8 볼륨 3: 서버 3, 4, 5, 6 볼륨 4: 서버 1, 2, 7, 8

분석

이 섹션에서는 볼륨이 온라인 상태로 유지되고 액세스할 수 있는 수학적 확률(또는 온라인 상태로 유지되고 액세스할 수 있는 전체 스토리지의 예상 비율)을 오류 수 및 클러스터 크기의 함수로 파생합니다.

참고 항목

이 섹션은 선택 읽기 사항입니다. 수학을 보고 싶다면 계속 읽으세요! 그렇지 않은 경우 걱정하지 마세요. PowerShell에서의 사용법모범 사례가 구분된 할당을 성공적으로 구현하는 데 필요한 전부입니다.

최대 두 번의 실패는 항상 괜찮습니다.

모든 3방향 미러 볼륨은 할당에 관계없이 동시에 최대 두 번의 오류에서 살아남을 수 있습니다. 2개의 드라이브가 실패하거나 두 개의 서버가 실패하거나 각 서버 중 하나가 실패하는 경우 3방향 미러 볼륨은 정기적으로 할당되더라도 온라인 상태로 유지되고 액세스할 수 있습니다.

클러스터 실패의 절반 이상이 정상이 아닌 경우

반대로 클러스터에 있는 서버 또는 드라이브의 절반 이상이 한 번에 실패하는 극단적인 경우 쿼럼이 손실 되고 모든 3방향 미러 볼륨이 오프라인 상태가 되고 할당에 관계없이 액세스할 수 없게 됩니다.

그 사이에는 어떤 것이 있을까요?

한 번에 3개 이상의 오류가 발생하지만 서버와 드라이브의 절반 이상이 계속 가동되면 오류가 발생한 서버에 따라 구분된 할당이 있는 볼륨이 온라인 상태로 유지되고 액세스할 수 있습니다.

자주 묻는 질문

일부 볼륨은 구분할 수 있지만 다른 볼륨은 구분할 수 없나요?

예. 할당을 구분할지 여부를 볼륨별로 선택할 수 있습니다.

구분된 할당은 드라이브 교체의 작동 방식을 변경하나요?

아니요, 일반 할당과 동일합니다.

추가 참조

부록

이 스크립트는 볼륨이 할당되는 방법을 확인하는 데 도움이 됩니다.

위에서 설명한 대로 사용하려면 복사/붙여넣고 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