Windows Server 2012: Storage Pooling

Windows Server 2012: Storage Pooling

Windows Server 2012 includes a new storage model.  It follows in the footsteps of ZFS and btrfs, in that it uses a pooled disk model, and attempts to combine all of the functionality of RAID, LVM, and the file system.  Now this looks like a 1.0 from the perspective of integration, however I am quite impressed by the implementation from the usability perspective.  While it is not as polished and integrated the flow is consistent and when using the GUI it is very simple to actually configure your storage.  That said this feels like multiple layers.

Usability Comparison to ZFS

To give you an idea of what I would expect lets look at how it works in ZFS.

In ZFS you configure a pool of disks, where we have disk0-4 and want to name the pool tank.

# zpool create tank mirror disk0 disk1 mirror disk2 disk3

Then you configure file systems on top of that, in this case fs1 on tank with a size of 10G.

# zfs create 10G tank/fs1

Regardless of which camp you are in the above commands are simple to understand and can be easily modified to suit my use case.

Interpretation of What is Being Done

Now as far as I can tell Microsoft has integrated VHD files into the solution in order to expose this functionality.  I don’t have a technical problem with this, however at this point there is a lot of manual work that has to be done in order to get to the point where I have a usable file system.  So you create your pool with your disks (this is no different from ZFS, however in ZFS this is where your RAID is performed.  Whereas in the Storage Pool/Spaces implementation they are doing that on the file system level (I suspect with software RAID on top of VHD files).  Once the pool is up and configured you create a Virtual Disk, where you will assign your resiliency (RAID level), then initialize the Virtual Disk, create a partition on the Virtual Disk, and finally format the Virtual Disk.  Now I am not saying that you shouldn’t have to technically do all of these things, however for this to have the seamless experience that they are trying to go for, they will need to put a bit more polish on this.

Find Our Physical Disks

As you can see we have a 25GB disk for our OS, which has the “CanPool” as False, this is because it is the system disk, and it is already being used.  We also have 2 10GB disks and 6 5GB disks.  I am doing this testing on my Virtualbox Windows 2012, so the disks are simple to scale out.  So the goal is to get them all in the same pool.  But in order to be more thorough we will be creating the pool with ONLY the 5GB disks, and then adding the 10GB disk, just to prove that we can.

PS> Get-PhysicalDisk

FriendlyName        CanPool             OperationalStatus   HealthStatus        Usage                              Size
------------        -------             -----------------   ------------        -----                              ----
PhysicalDisk0       False               OK                  Healthy             Auto-Select                       25 GB
PhysicalDisk1       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk2       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk3       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk4       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk5       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk6       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk7       True                OK                  Healthy             Auto-Select                       10 GB
PhysicalDisk8       True                OK                  Healthy             Auto-Select                       10 GB

Assign our Disks to a Variable

PS> $disk = Get-PhysicalDisk | where {$_.size -eq "5GB"}
PS> $disk

FriendlyName        CanPool             OperationalStatus   HealthStatus        Usage                              Size
------------        -------             -----------------   ------------        -----                              ----
PhysicalDisk1       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk2       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk3       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk4       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk5       True                OK                  Healthy             Auto-Select                        5 GB
PhysicalDisk6       True                OK                  Healthy             Auto-Select                        5 GB

Check the Name of the Storage SubSystem

I am assuming that you could wildcard this to your PC name or to Storage Spaces, but I didn’t want to document it that way since I am not sure how it would behave if you have multiple pools.

PS> Get-StorageSubSystem

FriendlyName                            HealthStatus                            OperationalStatus
------------                            ------------                            -----------------
Storage Spaces on WIN-PTP6J8CKQNG       Healthy                                 OK

Create the New Storage Pool

Here we are going to combine the variable we assigned earlier, with the name of the Storage SubSystem to create our new pool.  Then we will check the pools on the machine.  You might have noticed this before, but there is a Primordial pool, which holds disks which have not been assigned.  Sounds like someone at Microsoft has a sense of humor.  It is the goo from which your pool rises.

PS> New-StoragePool -StorageSubSystemFriendlyName "Storage Spaces on WIN-PTP6J8CKQNG" -FriendlyName pool0 -PhysicalDisks $disk

FriendlyName            OperationalStatus       HealthStatus            IsPrimordial            IsReadOnly
------------            -----------------       ------------            ------------            ----------
pool0                   OK                      Healthy                 False                   False
PS> Get-StoragePool

FriendlyName            OperationalStatus       HealthStatus            IsPrimordial            IsReadOnly
------------            -----------------       ------------            ------------            ----------
Primordial              OK                      Healthy                 True                    False
pool0                   OK                      Healthy                 False                   False

Add Additional Disks to the Pool

Assign the new disks to a variable, the same way we did before.

PS> $newdisk = Get-PhysicalDisk | where {$_.size -eq "10GB"}
PS> $newdisk

FriendlyName        CanPool             OperationalStatus   HealthStatus        Usage                              Size
------------        -------             -----------------   ------------        -----                              ----
PhysicalDisk7       True                OK                  Healthy             Auto-Select                       10 GB
PhysicalDisk8       True                OK                  Healthy             Auto-Select                       10 GB

Here we use the Add-PhysicalDisks cmdlet to add them to the Pool.  Now from a user experience this command is hard to find.  It should probably be a Modify-StoragePool or Add-StoragePoolMembers or similar.

PS> Add-PhysicalDisk -PhysicalDisks $newdisk -StoragePoolFriendlyName pool0

Create Virtual Disk (vdisk0)

This is pretty straight forward.  We are just creating a disk.

PS>  New-VirtualDisk -StoragePoolFriendlyName pool0 -FriendlyName vdisk0 -ResiliencySettingName mirror -ProvisioningType Thin -Size 30GB

FriendlyName        ResiliencySettingNa OperationalStatus   HealthStatus        IsManualAttach                     Size
me
------------        ------------------- -----------------   ------------        --------------                     ----
vdisk0              Mirror              OK                  Healthy             False                             30 GB

Initialize Disk (vdisk0)

The next step is to initialize it.

PS> Get-VirtualDisk vdisk0 | Initialize-Disk -PartitionStyle GPT

Create and Initialize Virtual Disk (vdisk1)

I combined the above two steps into one, via some powershell magic.  Functionally the same things are happening though.

PS>  New-VirtualDisk -StoragePoolFriendlyName pool0 -FriendlyName vdisk1 -ResiliencySettingName mirror -ProvisioningType Thin -Size 30GB | Initialize-Disk -PartitionStyle GPT

Partition and Format the Virtual Disk

Here is where it gets interesting.  I have combined everything into one step, but we have two distinct actions, the creation of the partition, and the formatting of the volume that is created (via the partitioning).  In the formatting, you have your choice of file system (of course the FAT’s but also NTFS and ReFS which is the interesting one).  If you are logged into the GUI this step will also result in a Windows Explorer pop-up asking if you want to format the disk, you can cancel that you are formatting via the command line.

PS>  get-disk | where {$_.uniqueid -eq ((Get-VirtualDisk vdisk0).UniqueId)} | New-Partition -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem NTFS

Confirm
Are you sure you want to perform this action?
Warning, all data on the volume will be lost!
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):

DriveLetter       FileSystemLabel  FileSystem       DriveType        HealthStatus        SizeRemaining             Size
-----------       ---------------  ----------       ---------        ------------        -------------             ----
E                                  NTFS             Fixed            Healthy                  29.78 GB         29.87 GB

Also if you’d like to do the above without having to confirm your action, pass Format-Volume with -Confirm:$false to avoid that confirmation.

PS>  get-disk | where {$_.uniqueid -eq ((Get-VirtualDisk vdisk0).UniqueId)} | New-Partition -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem NTFS -Confirm:$false

Well there you have it.  All and all I think it is an interesting concept, though it definitely needs some work around integrating the components.