Windows Server Storage Solutions: Storage Spaces Direct and Advanced Storage
Introduction
Windows Server delivers enterprise storage capabilities for modern datacenters. This guide covers Storage Spaces Direct for hyper-converged infrastructure, ReFS for data integrity, deduplication for space savings, storage tiering, iSCSI for SAN storage, Storage Replica for replication, and DFS for distributed storage.
Storage Spaces Direct (S2D)
Hardware Requirements
# Minimum hardware requirements for S2D:
# - 2-16 servers (recommended 4+)
# - Windows Server Datacenter edition
# - RDMA-capable network adapters (10 Gbps+)
# - NVMe, SSD, or HDD drives (minimum 4 drives per server)
# - Identical hardware across nodes
# Check hardware compatibility
Get-PhysicalDisk | Select-Object FriendlyName, MediaType, Size, HealthStatus
# Verify RDMA capability
Get-NetAdapterRdma
Deploying Storage Spaces Direct
# Install required features on all nodes
Invoke-Command -ComputerName "S2D-Node01", "S2D-Node02", "S2D-Node03", "S2D-Node04" -ScriptBlock {
Install-WindowsFeature -Name File-Services, Failover-Clustering, Hyper-V, RSAT-Clustering-PowerShell, Hyper-V-PowerShell
Restart-Computer
}
# Test cluster configuration
Test-Cluster -Node "S2D-Node01", "S2D-Node02", "S2D-Node03", "S2D-Node04" `
-Include "Storage Spaces Direct", "Inventory", "Network", "System Configuration" `
-ReportName "C:\Reports\ClusterValidation.html"
# Create failover cluster
New-Cluster -Name "S2D-Cluster" `
-Node "S2D-Node01", "S2D-Node02", "S2D-Node03", "S2D-Node04" `
-StaticAddress "192.168.1.100" `
-NoStorage
# Enable Storage Spaces Direct
Enable-ClusterStorageSpacesDirect -PoolFriendlyName "S2D-Pool" `
-CacheState Enabled `
-AutoConfig:$true `
-Confirm:$false
# View storage pool
Get-StoragePool -FriendlyName "S2D-Pool" | Get-StoragePoolPhysicalDisk
Get-StoragePool -FriendlyName "S2D-Pool" | Get-PhysicalDisk | Group-Object Usage
Creating Virtual Disks
# Create mirror virtual disk (2-way mirror)
New-Volume -FriendlyName "VM-Storage" `
-FileSystem CSVFS_ReFS `
-StoragePoolFriendlyName "S2D-Pool" `
-Size 1TB `
-ResiliencySettingName Mirror `
-PhysicalDiskRedundancy 1
# Create 3-way mirror (higher resilience)
New-Volume -FriendlyName "Critical-VMs" `
-FileSystem CSVFS_ReFS `
-StoragePoolFriendlyName "S2D-Pool" `
-Size 500GB `
-ResiliencySettingName Mirror `
-PhysicalDiskRedundancy 2
# Create parity volume (space-efficient)
New-Volume -FriendlyName "Archive-Storage" `
-FileSystem CSVFS_ReFS `
-StoragePoolFriendlyName "S2D-Pool" `
-Size 10TB `
-ResiliencySettingName Parity
# Create mirror-accelerated parity (balanced)
New-Volume -FriendlyName "Hybrid-Storage" `
-FileSystem CSVFS_ReFS `
-StoragePoolFriendlyName "S2D-Pool" `
-Size 5TB `
-ResiliencySettingName Parity `
-MediaType HDD `
-StorageTiers @(
@{FriendlyName="Performance";Size=1TB;ResiliencySettingName="Mirror"}
@{FriendlyName="Capacity";Size=4TB;ResiliencySettingName="Parity"}
)
# View virtual disks
Get-VirtualDisk | Select-Object FriendlyName, Size, HealthStatus, OperationalStatus, ResiliencySettingName
Get-ClusterSharedVolume
Monitoring S2D Health
# Check overall health
Get-StorageSubSystem Cluster* | Get-StorageHealthReport
# View physical disk status
Get-StoragePool -FriendlyName "S2D-Pool" | Get-PhysicalDisk |
Select-Object FriendlyName, MediaType, Size, HealthStatus, OperationalStatus
# Monitor capacity
Get-StoragePool -FriendlyName "S2D-Pool" |
Select-Object FriendlyName, @{N="Size(GB)";E={$_.Size/1GB}}, @{N="AllocatedSize(GB)";E={$_.AllocatedSize/1GB}}
# Check storage jobs
Get-StorageJob
# Automated health monitoring script
$s2dMonitor = @"
`$report = @()
# Storage pool health
`$pool = Get-StoragePool -FriendlyName 'S2D-Pool'
`$report += [PSCustomObject]@{
Component = 'Storage Pool'
Status = `$pool.HealthStatus
OperationalStatus = `$pool.OperationalStatus
FreeCapacity = ([math]::Round((`$pool.Size - `$pool.AllocatedSize)/1GB, 2)).ToString() + ' GB'
}
# Virtual disks health
Get-VirtualDisk | ForEach-Object {
`$report += [PSCustomObject]@{
Component = "Virtual Disk: `$(`$_.FriendlyName)"
Status = `$_.HealthStatus
OperationalStatus = `$_.OperationalStatus
FreeCapacity = 'N/A'
}
}
# Physical disks with issues
Get-PhysicalDisk | Where-Object { `$_.HealthStatus -ne 'Healthy' } | ForEach-Object {
`$report += [PSCustomObject]@{
Component = "Physical Disk: `$(`$_.FriendlyName)"
Status = `$_.HealthStatus
OperationalStatus = `$_.OperationalStatus
FreeCapacity = 'N/A'
}
}
`$report | Format-Table -AutoSize
if (`$report | Where-Object { `$_.Status -ne 'Healthy' }) {
Send-MailMessage ``
-To 'storage-admin@contoso.com' ``
-From 's2d-monitor@contoso.com' ``
-Subject 'S2D Health Alert' ``
-Body (`$report | Format-Table | Out-String) ``
-SmtpServer 'smtp.contoso.com'
}
"@
$s2dMonitor | Out-File "C:\Scripts\S2D-Monitor.ps1"
Resilient File System (ReFS)
ReFS vs NTFS Comparison
# ReFS advantages:
# - Integrity streams for corruption detection
# - Block cloning for instant copies
# - Sparse VDL for efficient virtual disk creation
# - Mirror-accelerated parity for balanced performance/capacity
# - No need for chkdsk (self-healing)
# - Maximum volume size 4.7 ZB
# - Optimized for Storage Spaces Direct
# NTFS advantages:
# - File compression
# - Disk quotas
# - EFS encryption
# - Named streams
# - Smaller volume support (< 100 GB)
Creating ReFS Volumes
# Format volume with ReFS
Format-Volume -DriveLetter E -FileSystem ReFS -NewFileSystemLabel "Data" -Confirm:$false
# Create ReFS volume on Storage Spaces
New-Volume -FriendlyName "ReFS-Volume" `
-FileSystem ReFS `
-StoragePoolFriendlyName "S2D-Pool" `
-Size 2TB `
-ResiliencySettingName Mirror
# Enable integrity streams
Set-FileIntegrity -FileName "E:\ImportantData" -Enable $true
# Verify integrity
Get-FileIntegrity -FileName "E:\ImportantData"
# View ReFS volume properties
Get-Volume -DriveLetter E | Format-List *
Block Cloning on ReFS
# Block cloning creates instant copies by referencing existing blocks
# Requires Windows Server 2016+ and ReFS
# Enable block cloning
# Already enabled by default on ReFS volumes
# Example: Clone file using Windows API
# PowerShell doesn't have native cmdlet, but you can use Robocopy with /B flag
# or use Storage Replica for volume-level cloning
# Clone virtual disk efficiently
# When creating new VM from template on ReFS, block cloning is automatic
Data Deduplication
Enabling Deduplication
# Install deduplication feature
Install-WindowsFeature -Name FS-Data-Deduplication -IncludeManagementTools
# Enable deduplication on volume
Enable-DedupVolume -Volume "E:" -UsageType Default
# Usage types:
# - Default: General purpose file server (files older than 5 days)
# - HyperV: Hyper-V VDI (files older than 3 days)
# - Backup: Backup target (all files)
# Enable for Hyper-V workload
Enable-DedupVolume -Volume "V:" -UsageType HyperV
# Set deduplication schedule
Set-DedupVolume -Volume "E:" -MinimumFileAgeDays 3
# View deduplication settings
Get-DedupVolume -Volume "E:"
Monitoring Deduplication
# View deduplication status
Get-DedupStatus -Volume "E:" | Format-List
# View savings
$dedupStats = Get-DedupStatus -Volume "E:"
$savedSpace = $dedupStats.SavedSpace / 1GB
$savingsRate = $dedupStats.SavingsRate
Write-Host "Deduplication Savings:" -ForegroundColor Cyan
Write-Host "Space Saved: $([math]::Round($savedSpace, 2)) GB" -ForegroundColor Green
Write-Host "Savings Rate: $([math]::Round($savingsRate, 2))%" -ForegroundColor Green
# View deduplication jobs
Get-DedupJob
# Start manual optimization
Start-DedupJob -Volume "E:" -Type Optimization
# Start garbage collection
Start-DedupJob -Volume "E:" -Type GarbageCollection
# Start scrubbing (integrity check)
Start-DedupJob -Volume "E:" -Type Scrubbing
Deduplication Best Practices
# Schedule optimization during off-hours
Set-DedupSchedule -Name "NightlyOptimization" `
-Type Optimization `
-DaysOfWeek Monday, Tuesday, Wednesday, Thursday, Friday `
-Start 02:00 `
-DurationHours 6 `
-Priority Normal `
-Memory 50
# Schedule garbage collection weekly
Set-DedupSchedule -Name "WeeklyGC" `
-Type GarbageCollection `
-DaysOfWeek Saturday `
-Start 02:00 `
-DurationHours 4
# Schedule scrubbing monthly
Set-DedupSchedule -Name "MonthlyScrub" `
-Type Scrubbing `
-DaysOfWeek Sunday `
-Start 02:00 `
-DurationHours 8
# View schedules
Get-DedupSchedule
Storage Tiering
Configuring Storage Tiers
# Storage tiering automatically moves hot data to SSD and cold data to HDD
# Create tiered storage space
New-StorageTier -StoragePoolFriendlyName "Storage-Pool" `
-FriendlyName "SSD-Tier" `
-MediaType SSD `
-ResiliencySettingName Simple
New-StorageTier -StoragePoolFriendlyName "Storage-Pool" `
-FriendlyName "HDD-Tier" `
-MediaType HDD `
-ResiliencySettingName Simple
# Create virtual disk with tiers
$ssdTier = Get-StorageTier -FriendlyName "SSD-Tier"
$hddTier = Get-StorageTier -FriendlyName "HDD-Tier"
New-VirtualDisk -StoragePoolFriendlyName "Storage-Pool" `
-FriendlyName "Tiered-Disk" `
-StorageTiers $ssdTier, $hddTier `
-StorageTierSizes 100GB, 900GB `
-WriteCacheSize 1GB
# Format and assign drive letter
Get-VirtualDisk -FriendlyName "Tiered-Disk" | Get-Disk |
Initialize-Disk -PartitionStyle GPT -PassThru |
New-Partition -AssignDriveLetter -UseMaximumSize |
Format-Volume -FileSystem NTFS -NewFileSystemLabel "Tiered Storage" -Confirm:$false
Managing File Tiering
# Pin file to SSD tier
Set-FileStorageTier -FilePath "E:\HotData\Database.mdf" -DesiredStorageTierFriendlyName "SSD-Tier"
# View file storage tier
Get-FileStorageTier -FilePath "E:\HotData\Database.mdf"
# Clear pinning (allow automatic tiering)
Clear-FileStorageTier -FilePath "E:\HotData\Database.mdf"
# View tier optimization status
Get-StorageTierSupportedSize -FriendlyName "Tiered-Disk" -TierSizeMin
iSCSI Target Server
Deploying iSCSI Target
# Install iSCSI Target Server
Install-WindowsFeature -Name FS-iSCSITarget-Server -IncludeManagementTools
# Create iSCSI virtual disk
New-IscsiVirtualDisk -Path "C:\iSCSI\Disk01.vhdx" -Size 100GB
# Create iSCSI target
New-IscsiServerTarget -TargetName "Target01" -InitiatorIds "IQN:iqn.1991-05.com.microsoft:client01"
# Add virtual disk to target
Add-IscsiVirtualDiskTargetMapping -TargetName "Target01" -Path "C:\iSCSI\Disk01.vhdx"
# View iSCSI configuration
Get-IscsiServerTarget
Get-IscsiVirtualDisk
Configuring iSCSI Initiator (Client)
# Start iSCSI initiator service
Start-Service MSiSCSI
Set-Service MSiSCSI -StartupType Automatic
# Configure iSCSI initiator
Set-Service MSiSCSI -Status Running
# Discover iSCSI target
New-IscsiTargetPortal -TargetPortalAddress "192.168.1.10"
# Connect to iSCSI target
Get-IscsiTarget | Connect-IscsiTarget -IsPersistent $true
# View connected targets
Get-IscsiSession
# Initialize and format iSCSI disk
Get-Disk | Where-Object { $_.PartitionStyle -eq 'RAW' } |
Initialize-Disk -PartitionStyle GPT -PassThru |
New-Partition -AssignDriveLetter -UseMaximumSize |
Format-Volume -FileSystem NTFS -NewFileSystemLabel "iSCSI Storage" -Confirm:$false
iSCSI MPIO Configuration
# Install MPIO feature
Install-WindowsFeature -Name Multipath-IO -IncludeManagementTools -Restart
# Add iSCSI support to MPIO
New-MSDSMSupportedHW -VendorId "MSFT2005" -ProductId "iSCSIBusType_0x9"
# Configure MPIO policy
Set-MSDSMGlobalDefaultLoadBalancePolicy -Policy RR # Round Robin
# Connect to target with multiple paths
Connect-IscsiTarget -NodeAddress "iqn.1991-05.com.microsoft:target01" -IsPersistent $true -IsMultipathEnabled $true
# View MPIO configuration
Get-MSDSMGlobalDefaultLoadBalancePolicy
Get-MPIOAvailableHW
Storage Replica
Configuring Storage Replica
# Install Storage Replica feature (requires Datacenter edition)
Install-WindowsFeature -Name Storage-Replica, RSAT-Storage-Replica -IncludeManagementTools
# Test replication prerequisites
Test-SRTopology -SourceComputerName "SRV01" -SourceVolumeName "E:" -SourceLogVolumeName "L:" `
-DestinationComputerName "SRV02" -DestinationVolumeName "E:" -DestinationLogVolumeName "L:" `
-DurationInMinutes 5 -ResultPath "C:\Reports"
# Create server-to-server replication
New-SRPartnership -SourceComputerName "SRV01" -SourceRGName "RG01" `
-SourceVolumeName "E:" -SourceLogVolumeName "L:" `
-DestinationComputerName "SRV02" -DestinationRGName "RG02" `
-DestinationVolumeName "E:" -DestinationLogVolumeName "L:" `
-ReplicationMode Synchronous
# View replication status
Get-SRGroup
Get-SRPartnership | Format-List *
# Monitor replication
(Get-SRGroup).Replicas | Select-Object ReplicatedSize, ReplicationStatus
# Reverse replication direction (for failover)
Set-SRPartnership -NewSourceComputerName "SRV02" -SourceRGName "RG02" `
-DestinationComputerName "SRV01" -DestinationRGName "RG01"
Distributed File System (DFS)
DFS Namespaces
# Install DFS Namespaces
Install-WindowsFeature -Name FS-DFS-Namespace -IncludeManagementTools
# Create DFS namespace
New-DfsnRoot -Path "\\contoso.com\Files" -TargetPath "\\FileServer01\Files" -Type DomainV2
# Add folder to namespace
New-DfsnFolder -Path "\\contoso.com\Files\Departments" -TargetPath "\\FileServer01\Departments"
# Add folder target (for redundancy)
New-DfsnFolderTarget -Path "\\contoso.com\Files\Departments" -TargetPath "\\FileServer02\Departments"
# View DFS namespace
Get-DfsnRoot
Get-DfsnFolder -Path "\\contoso.com\Files\*"
DFS Replication
# Install DFS Replication
Install-WindowsFeature -Name FS-DFS-Replication -IncludeManagementTools
# Create replication group
New-DfsReplicationGroup -GroupName "Files-RG"
# Add members
Add-DfsrMember -GroupName "Files-RG" -ComputerName "FileServer01", "FileServer02"
# Add replicated folder
New-DfsReplicatedFolder -GroupName "Files-RG" -FolderName "Departments"
# Set replication topology (full mesh)
Add-DfsrConnection -GroupName "Files-RG" `
-SourceComputerName "FileServer01" `
-DestinationComputerName "FileServer02"
# Configure membership
Set-DfsrMembership -GroupName "Files-RG" -FolderName "Departments" `
-ComputerName "FileServer01" -ContentPath "D:\Departments" -PrimaryMember $true
Set-DfsrMembership -GroupName "Files-RG" -FolderName "Departments" `
-ComputerName "FileServer02" -ContentPath "D:\Departments"
# View replication status
Get-DfsrState -ComputerName "FileServer01"
Get-DfsrBacklog -GroupName "Files-RG" -FolderName "Departments" `
-SourceComputerName "FileServer01" -DestinationComputerName "FileServer02"
Key Takeaways
- Storage Spaces Direct delivers hyper-converged infrastructure
- ReFS provides data integrity and modern storage features
- Deduplication saves disk space on file servers and backups
- Storage tiering balances performance and capacity
- iSCSI Target Server provides SAN storage over Ethernet
- Storage Replica enables synchronous/asynchronous replication
- DFS Namespaces simplify file access across servers
- DFS Replication keeps folders synchronized across sites
Next Steps
- Deploy Storage Spaces Direct for hyper-converged infrastructure
- Implement ReFS on new volumes for data integrity
- Enable deduplication on appropriate workloads
- Configure storage tiering for balanced performance
- Set up iSCSI for block-level storage
- Implement Storage Replica for disaster recovery
- Deploy DFS for distributed file access
Additional Resources
- Storage Spaces Direct
- Resilient File System (ReFS)
- Data Deduplication
- iSCSI Target Server
- Storage Replica
- DFS Namespaces and Replication
Store. Protect. Replicate. Scale.