記憶域スペースダイレクトのボリュームの割り当てを区切ります。Delimit the allocation of volumes in Storage Spaces Direct

適用対象:Windows Server 2019Applies to: Windows Server 2019

Windows Server 2019 では、記憶域スペースダイレクトでボリュームの割り当てを手動で区切るオプションが導入されています。Windows Server 2019 introduces an option to manually delimit the allocation of volumes in Storage Spaces Direct. これにより、特定の条件下でフォールトトレランスを大幅に向上させることができますが、管理上の考慮事項と複雑さが増加します。Doing so can significantly increase fault tolerance under certain conditions, but imposes some added management considerations and complexity. このトピックでは、そのしくみについて説明し、PowerShell の例を示します。This topic explains how it works and gives examples in PowerShell.

重要

この機能は、Windows Server 2019 で新しく追加された機能です。This feature is new in Windows Server 2019. Windows Server 2016 では使用できません。It is not available in Windows Server 2016.

前提条件Prerequisites

緑のチェックマークアイコン。 次の場合に、このオプションの使用を検討してください。Consider using this option if:

  • クラスターには6台以上のサーバーがあります。そしてYour cluster has six or more servers; and
  • クラスターが3 方向ミラー回復性のみを使用しているYour cluster uses only three-way mirror resiliency

赤色の X アイコン。 次の場合は、このオプションを使用しないでください。Do not use this option if:

概要Understand

レビュー: 通常の割り当てReview: regular allocation

通常の3方向ミラーリングでは、ボリュームは多数の小さな "スラブ" に分割され、3回コピーされ、クラスター内のすべてのサーバーのすべてのドライブに均等に分散されます。With regular three-way mirroring, the volume is divided into many small "slabs" that are copied three times and distributed evenly across every drive in every server in the cluster. 詳細については、この詳細なブログを参照してください。For more details, read this deep dive blog.

ボリュームがスラブの3つのスタックに分割され、すべてのサーバーで均等に分散されていることを示す図。

この既定の割り当てにより、並列読み取りと書き込みが最大化され、パフォーマンスが向上します。また、各サーバーが均等にビジー状態になり、すべてのドライブが均等にいっぱいになり、すべてのボリュームがオンラインになるか、同時にオフラインになります。This default allocation maximizes parallel reads and writes, leading to better performance, and is appealing in its simplicity: every server is equally busy, every drive is equally full, and all volumes stay online or go offline together. 各ボリュームは、次の例に示すように、最大2つの同時エラーが発生することが保証されます。Every volume is guaranteed to survive up to two concurrent failures, as these examples illustrate.

ただし、この割り当てでは、ボリュームが同時に3つのエラーを発生させることはできません。However, with this allocation, volumes can't survive three concurrent failures. 3台のサーバーで障害が発生した場合、または3台のサーバーのドライブが一度に失敗した場合、少なくとも一部のスラブ (確率が非常に高い) が、障害が発生した3台のドライブまたはサーバーに割り当てられているため、ボリュームにアクセスできなくなります。If three servers fail at once, or if drives in three servers fail at once, volumes become inaccessible because at least some slabs were (with very high probability) allocated to the exact three drives or servers that failed.

次の例では、サーバー1、3、および5が同時に失敗します。In the example below, servers 1, 3, and 5 fail at the same time. 多くのスラブには残ったコピーがありますが、次のようなものはありません。Although many slabs have surviving copies, some do not:

3台のサーバーが赤で強調表示されていて、全体的なボリュームが赤である図。

ボリュームはオフラインになり、サーバーが回復するまでアクセスできなくなります。The volume goes offline and becomes inaccessible until the servers are recovered.

新規: 区切られた割り当てNew: delimited allocation

区切られた割り当てでは、使用するサーバーのサブセットを指定します (3 方向ミラーの場合は3つ)。With delimited allocation, you specify a subset of servers to use (minimum three for three-way mirror). ボリュームは、以前と同様に3回コピーされるスラブに分割されますが、すべてのサーバーに割り当てられるのではなく、指定したサーバーのサブセットにのみスラブが割り当てられます。The volume is divided into slabs that are copied three times, like before, but instead of allocating across every server, the slabs are allocated only to the subset of servers you specify.

ボリュームがスラブの3つのスタックに分割され、6台のサーバーにのみ分散していることを示す図。

長所Advantages

この割り当てにより、ボリュームは同時に3つの障害が発生する可能性があります。実際、この場合、継続の確率は 0% (通常の割り当て) から 95% (区切られた割り当て) に増加します。With this allocation, the volume is likely to survive three concurrent failures: in fact, its probability of survival increases from 0% (with regular allocation) to 95% (with delimited allocation) in this case! 直感的に言えば、サーバー4、5、または6に依存しないため、障害の影響を受けません。Intuitively, this is because it does not depend on servers 4, 5, or 6 so it is not affected by their failures.

上記の例では、サーバー1、3、および5は同時に失敗します。In the example from above, servers 1, 3, and 5 fail at the same time. 区切られた割り当てにより、サーバー2にすべてのスラブのコピーが含まれることが保証されるため、すべてのスラブには残ったコピーがあり、ボリュームはオンラインのままでアクセスできます。Because delimited allocation ensured that server 2 contains a copy of every slab, every slab has a surviving copy and the volume stays online and accessible:

6台のサーバーのうちの3台が赤で強調表示されていて、全体的なボリュームが緑であることを示す図。

存続確率は、サーバーの数とその他の要因によって異なります。詳細については、「分析」を参照してください。Survival probability depends on the number of servers and other factors – see Analysis for details.

欠点Disadvantages

区切られた割り当てにより、管理上の考慮事項と複雑さが増加します。Delimited allocation imposes some added management considerations and complexity:

  1. 管理者は、各ボリュームの割り当てを区切ることによって、サーバー間での記憶域使用率のバランスを取るとともに、「ベストプラクティス」セクションで説明されているように、サバイバルの確率を高くします。The administrator is responsible for delimiting the allocation of each volume to balance storage utilization across servers and uphold high probability of survival, as described in the Best practices section.

  2. 区切られた割り当てでは、サーバーごとに1つの容量ドライブに相当するものを予約します (最大値はありません)With delimited allocation, reserve the equivalent of one capacity drive per server (with no maximum). これは、通常の割り当てに関して公開されている推奨事項を超えており、合計4つの容量ドライブを qpu します。This is more than the published recommendation for regular allocation, which maxes out at four capacity drives total.

  3. サーバーとそのドライブの削除に関するページで説明されているように、サーバーで障害が発生し、交換が必要になった場合、管理者は、新しいサーバーを追加して失敗したボリュームの delimitation を削除することで、影響を受けるボリュームの更新を行います。次の例を参照してください。If a server fails and needs to be replaced, as described in Remove a server and its drives, the administrator is responsible for updating the delimitation of affected volumes by adding the new server and removing the failed one – example below.

PowerShell での使用法Usage in PowerShell

コマンドレットを使用New-Volumeして記憶域スペースダイレクトでボリュームを作成できます。You can use the New-Volume cmdlet to create volumes in Storage Spaces Direct.

たとえば、通常の3方向ミラーボリュームを作成するには、次のようにします。For example, to create a regular three-way mirror volume:

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

ボリュームを作成し、その割り当てを区切るCreate a volume and delimit its allocation

3方向ミラーボリュームを作成し、その割り当てを区切るには、次のようにします。To create a three-way mirror volume and delimit its allocation:

  1. まず、クラスター内のサーバーを変数$Serversに割り当てます。First assign the servers in your cluster to the variable $Servers:

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

    ヒント

    記憶域スペースダイレクトでは、"ストレージスケールユニット" という用語は、直接接続されたドライブとドライブを持つ直接接続された外部エンクロージャを含む、1台のサーバーに接続されているすべての未加工のストレージを指します。In Storage Spaces Direct, the term 'Storage Scale Unit' refers to all the raw storage attached to one server, including direct-attached drives and direct-attached external enclosures with drives. このコンテキストでは、' server ' と同じです。In this context, it's the same as 'server'.

  2. 新しい-StorageFaultDomainsToUseパラメーターで使用するサーバーと、に$Serversインデックスを付けることによって、どのサーバーを使用するかを指定します。Specify which servers to use with the new -StorageFaultDomainsToUse parameter and by indexing into $Servers. たとえば、1番目、2番目、および3番目のサーバー (インデックス0、1、および 2) への割り当てを区切るには、次のようにします。For example, to delimit the allocation to the first, second, and third servers (indices 0, 1, and 2):

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

区切られた割り当てを表示するSee a delimited allocation

Myvolumeがどのように割り当てられてGet-VirtualDiskFootprintBySSU.ps1いるかを確認するには、付録のスクリプトを使用します。To see how MyVolume is allocated, use the Get-VirtualDiskFootprintBySSU.ps1 script in Appendix:

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

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

Server1、Server2、および Server3 にのみ、 Myvolumeのスラブが含まれていることに注意してください。Note that only Server1, Server2, and Server3 contains slabs of MyVolume.

区切られた割り当てを変更するChange a delimited allocation

新しいAdd-StorageFaultDomainコマンドレットとRemove-StorageFaultDomainコマンドレットを使用して、割り当ての区切り方法を変更します。Use the new Add-StorageFaultDomain and Remove-StorageFaultDomain cmdlets to change how the allocation is delimited.

たとえば、1台のサーバーでMyvolumeを移動するには、次のようにします。For example, to move MyVolume over by one server:

  1. 4番目のサーバーがスラブMyvolumeを格納できることを指定します。Specify that the fourth server can store slabs of MyVolume:

    Get-VirtualDisk MyVolume | Add-StorageFaultDomain -StorageFaultDomains $Servers[3]
    
  2. 最初のサーバーがスラブのMyvolumeを格納できないことを指定します。Specify that the first server cannot store slabs of MyVolume:

    Get-VirtualDisk MyVolume | Remove-StorageFaultDomain -StorageFaultDomains $Servers[0]
    
  3. 変更を有効にするために、記憶域プールを再調整します。Rebalance the storage pool for the change to take effect:

    Get-StoragePool S2D* | Optimize-StoragePool
    

サーバー1、2、および3からサーバー2、3、および4へのスラブの移行を示す図

Get-StorageJobは、再調整の進行状況を監視できます。You can monitor the progress of the rebalance with Get-StorageJob.

完了したら、をもう一度実行Get-VirtualDiskFootprintBySSU.ps1して、 myvolumeが移動したことを確認します。Once it is complete, verify that MyVolume has moved by running Get-VirtualDiskFootprintBySSU.ps1 again.

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

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

Server1 にはMyvolumeのスラブがなく、代わりに Server04 が使用することに注意してください。Note that Server1 does not contain slabs of MyVolume anymore – instead, Server04 does.

ベスト プラクティスBest practices

区切られたボリューム割り当てを使用する場合のベストプラクティスを次に示します。Here are the best practices to follow when using delimited volume allocation:

3台のサーバーを選択するChoose three servers

3方向ミラーボリュームを3台のサーバーに区切ります。Delimit each three-way mirror volume to three servers, not more.

ストレージのバランスを取るBalance storage

各サーバーに割り当てられる記憶域の量を調整します。ボリュームのサイズについては考慮します。Balance how much storage is allocated to each server, accounting for volume size.

区切られた割り当てごとに一意Every delimited allocation unique

フォールトトレランスを最大化するには、各ボリュームの割り当てを一意にします。つまり、すべてのサーバーが別のボリュームと共有されることはありません (重複は問題ありません)。To maximize fault tolerance, make each volume's allocation unique, meaning it does not share all its servers with another volume (some overlap is okay). N 台のサーバーでは、"N choose 3" という一意の組み合わせがあります。これは、いくつかの一般的なクラスターサイズの意味です。With N servers, there are "N choose 3" unique combinations – here's what that means for some common cluster sizes:

サーバーの数 (N)Number of servers (N) 一意に区切られた割り当ての数 (N 選択 3)Number of unique delimited allocations (N choose 3)
66 2020
88 5656
1212 220220
1616 560560

ヒント

ここでは、連結の方法について説明し、記法を選択します。Consider this helpful review of combinatorics and choose notation.

フォールトトレランスを最大化する例を次に示します。各ボリュームには、一意の区切られた割り当てがあります。Here's an example that maximizes fault tolerance – every volume has a unique delimited allocation:

一意の割り当て

反対に、次の例では、最初の3つのボリュームで同じ区切られた割り当て (サーバー1、2、3) が使用され、最後の3つのボリュームでは、同じ区切られた割り当て (サーバー4、5、および 6) が使用されます。Conversely, in the next example, the first three volumes use the same delimited allocation (to servers 1, 2, and 3) and the last three volumes use the same delimited allocation (to servers 4, 5, and 6). フォールトトレランスを最大にすることはできません。3台のサーバーで障害が発生した場合、複数のボリュームがオフラインになり、一度にアクセスできなくなる可能性があります。This doesn't maximize fault tolerance: if three servers fail, multiple volumes could go offline and become inaccessible at once.

一意でない割り当て

分析Analysis

このセクションでは、障害の数とクラスターサイズの機能として、ボリュームがオンラインでアクセス可能である (または、オンラインでアクセス可能なストレージ全体の予想される割合) ことを示す算術確率を導き出します。This section derives the mathematical probability that a volume stays online and accessible (or equivalently, the expected fraction of overall storage that stays online and accessible) as a function of the number of failures and the cluster size.

注意

このセクションは省略可能です。This section is optional reading. 数値演算の場合は、「」を参照してください。If you're keen to see the math, read on! そうでない場合は、心配しないでください。PowerShell の使用方法ベストプラクティスは、区切られた割り当てを正常に実装するために必要な作業です。But if not, don't worry: Usage in PowerShell and Best practices is all you need to implement delimited allocation successfully.

常に最大2つのエラーが発生するUp to two failures is always okay

3方向ミラーボリュームは、割り当てに関係なく、これらの例が示しているように、同時に最大2つの障害に対応できます。Every three-way mirror volume can survive up to two failures at the same time, as these examples illustrate, regardless of its allocation. 2つのドライブに障害が発生した場合、または2台のサーバーで障害が発生した場合、またはいずれかの場合は、通常の割り当てであっても、3方向ミラーボリュームはオンラインになり、アクセスできます。If two drives fail, or two servers fail, or one of each, every three-way mirror volume stays online and accessible, even with regular allocation.

クラスターの障害が半分を超えると、問題ありません。More than half the cluster failing is never okay

逆に、クラスター内の半分以上のサーバーまたはドライブが一度に失敗した場合は、割り当てに関係なく、クォーラムが失われ、3方向ミラーボリュームがすべてオフラインになり、アクセスできなくなります。Conversely, in the extreme case that more than half of servers or drives in the cluster fail at once, quorum is lost and every three-way mirror volume goes offline and becomes inaccessible, regardless of its allocation.

の間には何があるでしょうか。What about in between?

3回以上の障害が発生しても、少なくとも半数のサーバーとドライブが稼働状態になっている場合、障害が発生しているサーバーによっては、区切られた割り当てを持つボリュームがオンラインでアクセス可能な状態になることがあります。If three or more failures occur at once but at least half of servers and drives are still up, volumes with delimited allocation may stay online and accessible, depending on which servers have failures. 数値を実行して、正確な確率を調べてみましょう。Let's run the numbers to determine the precise odds.

わかりやすくするために、上記のベストプラクティスに従って、ボリュームが独立して均等に分散 (IID) されることを想定しています。また、ボリュームの割り当てごとに一意の組み合わせを使用できます。For simplicity, assume volumes are independently and identically distributed (IID) according to the best practices above, and that enough unique combinations are available for every volume's allocation to be unique. 特定のボリュームが存続する確率は、予測の直線性によって最終的には、ストレージ全体の予想される割合でもあります。The probability that any given volume survives is also the expected fraction of overall storage that survives by linearity of expectation.

N 個のサーバーで障害が発生した場合、そのうちの3に割り当てられたボリュームは、-との場合にはオフラインになります。 3 つすべてのエラーが発生している場合は、Given N servers of which F have failures, a volume allocated to 3 of them goes offline if-and-only-if all 3 are among the F with failures. Fの失敗を発生させる (N choose f) 方法があります。 (f choose 3) は、ボリュームがオフラインになり、アクセスできなくなる可能性があります。There are (N choose F) ways for F failures to occur, of which (F choose 3) result in the volume going offline and becoming inaccessible. 確率は次のように表すことができます。The probability can be expressed as:

P_offline = Fc3/NcF

それ以外の場合、ボリュームはオンラインのままで、アクセスできます。In all other cases, the volume stays online and accessible:

P_online = 1 – (Fc3/NcF)

次の表は、いくつかの一般的なクラスターサイズと最大5つの障害の確率を評価し、区切られた割り当てにより、すべてのケースでの通常の割り当てと比較してフォールトトレランスが向上することを明らかにします。The following tables evaluate the probability for some common cluster sizes and up to 5 failures, revealing that delimited allocation increases fault tolerance compared to regular allocation in every case considered.

6台のサーバーWith 6 servers

割り当てAllocation 残存の1件のエラーの確率Probability of surviving 1 failure 残存の2つのエラーの確率Probability of surviving 2 failures 残りの3つのエラーの確率Probability of surviving 3 failures 残っている4つのエラーの確率Probability of surviving 4 failures 残っている5つのエラーの確率Probability of surviving 5 failures
標準、すべての6台のサーバーに分散Regular, spread across all 6 servers 100%100% 100%100% 00% 00% 00%
3台のサーバーのみに区切られます。Delimited to 3 servers only 100%100% 100%100% 95.0%95.0% 00% 00%

注意

サーバーの合計6個を超える障害が発生すると、クラスターはクォーラムを失います。After more than 3 failures out of 6 total servers, the cluster loses quorum.

8台のサーバーWith 8 servers

割り当てAllocation 残存の1件のエラーの確率Probability of surviving 1 failure 残存の2つのエラーの確率Probability of surviving 2 failures 残りの3つのエラーの確率Probability of surviving 3 failures 残っている4つのエラーの確率Probability of surviving 4 failures 残っている5つのエラーの確率Probability of surviving 5 failures
標準、すべての8台のサーバーに分散Regular, spread across all 8 servers 100%100% 100%100% 00% 00% 00%
3台のサーバーのみに区切られます。Delimited to 3 servers only 100%100% 100%100% 98.2%98.2% 94.3%94.3% 00%

注意

合計で8台のサーバーの障害が発生すると、クラスターはクォーラムを失います。After more than 4 failures out of 8 total servers, the cluster loses quorum.

12台のサーバーWith 12 servers

割り当てAllocation 残存の1件のエラーの確率Probability of surviving 1 failure 残存の2つのエラーの確率Probability of surviving 2 failures 残りの3つのエラーの確率Probability of surviving 3 failures 残っている4つのエラーの確率Probability of surviving 4 failures 残っている5つのエラーの確率Probability of surviving 5 failures
標準、12のすべてのサーバーに分散Regular, spread across all 12 servers 100%100% 100%100% 00% 00% 00%
3台のサーバーのみに区切られます。Delimited to 3 servers only 100%100% 100%100% 99.5%99.5% 99.2%99.2% 98.7%98.7%

16台のサーバーWith 16 servers

割り当てAllocation 残存の1件のエラーの確率Probability of surviving 1 failure 残存の2つのエラーの確率Probability of surviving 2 failures 残りの3つのエラーの確率Probability of surviving 3 failures 残っている4つのエラーの確率Probability of surviving 4 failures 残っている5つのエラーの確率Probability of surviving 5 failures
標準、16台すべてのサーバーにまたがるRegular, spread across all 16 servers 100%100% 100%100% 00% 00% 00%
3台のサーバーのみに区切られます。Delimited to 3 servers only 100%100% 100%100% 99.8%99.8% 99.8%99.8% 99.8%99.8%

よく寄せられる質問Frequently asked questions

いくつかのボリュームを区切ることはできますか。Can I delimit some volumes but not others?

可能。Yes. 割り当てを区切るかどうかによって、ボリュームごとに選択できます。You can choose per-volume whether or not to delimit allocation.

区切られた割り当てはドライブ置換の動作を変更しますか。Does delimited allocation change how drive replacement works?

いいえ。通常の割り当てと同じです。No, it's the same as with regular allocation.

関連項目See also

付録Appendix

このスクリプトは、ボリュームがどのように割り当てられているかを確認するのに役立ちます。This script helps you see how your volumes are allocated.

前述のとおりに使用するには、コピー/貼り付けGet-VirtualDiskFootprintBySSU.ps1を行って、名前を付けて保存します。To use it as described above, copy/paste and save as 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