Storage Spaces Direct in Windows Server 2019

Storage Spaces Direct (S2D) is the award-winning software-defined storage (SDS) tecnhology that was first introduced in Windows Server 2016. Since that moment, S2D has become my one of the favourite and frequently used role in Windows Server (on-premises and even in Azure).

Windows Server 2019 that is going to be generally available in the second half of this year (September or October – in accordance with WS 2012-2016 release dates) continues to develop S2D by adding new features. Why don’t we discuss them right now?

TIP: Windows Server 2019 preview build is available here


More volumes, bigger capacity per server and cluster

Storage Spaces Direct Scalability in Windows Server 2019

USB Witness

Storage Spaces Direct can be configured with just two nodes. However, we will need to design witness placement to protect our cluster from unexpected failure (in other words, we should achieve quorum). In Windows Server 2016, you can place witness on a file share, cloud (details here) or disk witness (it’d be very strange if it was actually used in S2D clusters). What about customers who don’t have any AD infrastructure or Azure/Internet access? Here is a breakthrough – USB Witness.

usb witness windows server 2019

In short, you will be able to configure a true two-node S2D by using USB thumb drive connected to the router that is already used for VM/management traffic between nodes, for instance. Other two network interfaces (shown on the picture above), could be RDMA-adapters (recommended and supported) or Thunderbolt (POC, Project Kepler-47).

Simply insert the USB drive into the port on the router, set the share name and access information, configure witness in PowerShell: Set-ClusterQuorum -FileShareWitness \path\ -Credential  and you are ready to go.

TIP: the router should support SMB2+ and USB. And, given that a witness.log is a quite small file (just kilobytes), you can use any-sized USB drives. The list of the supported routers will be available later.

Data Deduplication

ReFS  is the recommended file system for S2D, improves VHDX creation/expansion speed (enables Accelerated VHDX operations), provides higher stability by detecting corruptions and allowing you to repair them with no volume downtime. However, some features such as ODX, Data Deduplication are not supported by ReFS in Windows Server 2016.

Starting with the Windows Server 2019 (1709 and later), Data Deduplication has been fully supported for ReFS. It means that you no longer need to choose between NTFS and ReFS file systems while planning S2D volumes. Create ReFS volume, enable Data Deduplication (PowerShell/Windows Admin Center), and then check the savings of storage space (use PowerShell and Get-DedupVolume cmdlet).

data deduplication s2d windows server 2019

Proactive outlier detection

It was quite challenging to investigate  performance issues in S2D in Windows Server 2016. We had to use PowerShell or performance counters (+VMFleet) to get a full picture of our setup’s behavior. Windows Server 2019 significantly simplifies that. S2D now records the outcome (success/failure) and latency (elapsed time) for every read/write IO to every drive without any performance impact. Therefore, drives with latency/outcome issues will be marked in PowerShell and Windows Admin Center as “Abnormal Latency” status. In addition, you can organize pooled drives into peer groups, and then compare latency against peers to quickly find any bottlenecks (new cmdlet: Get-PhysicalDiskIoReport).

This azure-inspired mechanism works on the lower level than performance counters and enabled by default for every SATA,SAS,NVMe drives.

latency outlier detection s2d 2019


-Faster mirror-accelerated parity volumes (~x2)

-PMEM (Persistent Memory) drives support (Intel Optane/NVDIMM-N) for use as cache and capacity

-Deep integration with Windows Admin Center (a free HTML5-based management interface for entire Windows Server infrastructure. We’ll look at this a bit later)

Automate SCOM 2016 installation with PowerShell

This blog post demonstrates how to automate installation of SCOM 2016 and its requirements using PowerShell. If you’d like, you can also use it partly to install just software prerequisites or service accounts.

My demo lab is configured in the following way:

  • SCOM Server –  VM with up to 8Gb RAM, 4vCPU, Windows Server 2016
  • SCOM VMs has an Internet Connection (to get Report Viewer/Runtime)
  • SQL Server – VM with up to 4Gb RAM. Windows Server 2016
  • Database Services, Full Text and Reporting Services – Native were installed on the SQL Server VM.
  • These machines are also joined to the same domain
  • SCOM media copied to the <systemdrive>\SCOM2016
  • I checked the script using my domain administrator account
  • Download link is available at the bottom
What does the script do?
  • Downloads and installs Report Viewer Controls and required Runtime
New-Item $env:systemdrive\SCOM2016Reqs -ItemType Directory
Invoke-WebRequest -OutFile $env:systemdrive\SCOM2016Reqs\ReportViewer.msi
Invoke-WebRequest -OutFile $env:systemdrive\SCOM2016Reqs\SQLSysClrTypes.msi
Start-Process "$env:systemdrive\SCOM2016Reqs\SQLSysClrTypes.msi" /qn -Wait
Start-Process "$env:systemdrive\SCOM2016Reqs\ReportViewer.msi" /quiet -Wait
Write-Host "The Report Viewer Controls and Runtime have been installed" -ForegroundColor DarkCyan
  • Creates required service accounts, SCOM administrator group in the specified OU and configures required permissions (local admin rights for the SCOM admin group)
Install-WindowsFeature RSAT-AD-PowerShell
New-AdUser SCOM-AccessAccount -SamAccountName scom.aa -AccountPassword (ConvertTo-SecureString -AsPlainText $svcpass -Force) -PasswordNeverExpires $true -Enabled $true -Path "OU=$ouname,$adcn"
New-AdUser SCOM-DataWareHouse-Reader -SamAccountName scom.dwr -AccountPassword (ConvertTo-SecureString -AsPlainText $svcpass -Force) -PasswordNeverExpires $true -Enabled $true -Path "OU=$ouname,$adcn"
New-AdUser SCOM-DataWareHouse-Write -SamAccountName scom.dww -AccountPassword (ConvertTo-SecureString -AsPlainText $svcpass -Force) -PasswordNeverExpires $true -Enabled $true -Path "OU=$ouname,$adcn"
New-AdUser SCOM-Server-Action -SamAccountName -AccountPassword (ConvertTo-SecureString -AsPlainText $svcpass -Force) -PasswordNeverExpires $true -Enabled $true -Path "OU=$ouname,$adcn"
New-AdGroup -Name SCOM-Admins -GroupScope Global -GroupCategory Security -Path "OU=$ouname,$adcn"
Add-AdGroupMember SCOM-Admins scom.aa,scom.dwr,scom.dww,
Add-LocalGroupMember -Member $dname\SCOM-Admins -Group Administrators
#SQL Server service accounts (SQLSSRS is a service reporting services account)
New-AdUser SQLSVC -SamAccountName sqlsvc -AccountPassword (ConvertTo-SecureString -AsPlainText $svcpass -Force) -PasswordNeverExpires $true -Enabled $true -Path "OU=$ouname,$adcn"
New-AdUser SQLSSRS -SamAccountName sqlssrs -AccountPassword (ConvertTo-SecureString -AsPlainText $svcpass -Force) -PasswordNeverExpires $true -Enabled $true -Path "OU=$ouname,$adcn"
Write-Host "The service Accounts and SCOM-Admins group have been added to OU=$ouname,$adcn" -ForegroundColor DarkCyan

  • Configures SQL Server by creating required Windows Firewall rules and adding SCOM-Admins group to the administrators on the server
$secpasswd = ConvertTo-SecureString $sqlpass -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("$dname\$sqluser", $secpasswd)
$psrem = New-PSSession -ComputerName $sqlsrv -Credential $cred
Invoke-Command -Session $psrem -ScriptBlock{
Install-WindowsFeature RSAT-AD-Powershell
Set-NetFirewallRule -Name WMI-WINMGMT-In-TCP -Enabled True
New-NetFirewallRule -Name "SQL DB" -DisplayName "SQL Database" -Profile Domain -Direction Inbound -LocalPort 1433 -Protocol TCP -Action Allow
New-NetFirewallRule -Name "SQL Server Admin Connection" -DisplayName "SQL Admin Connection" -Profile Domain -Direction Inbound -LocalPort 1433 -Protocol TCP -Action Allow
New-NetFirewallRule -Name "SQL Browser" -DisplayName "SQL Browser" -Profile Domain -Direction Inbound -LocalPort 1434 -Protocol UDP -Action Allow
New-NetFirewallRule -Name "SQL SRRS (HTTP)" -DisplayName "SQL SRRS (HTTP)" -Profile Domain -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow
New-NetFirewallRule -Name "SQL SRRS (SSL)" -DisplayName "SQL SRRS (SSL)" -Profile Domain -Direction Inbound -LocalPort 443 -Protocol TCP -Action Allow
New-NetFirewallRule -Name "SQL Instance Custom Port" -DisplayName "SQL Instance Custom Port" -Profile Domain -Direction Inbound -LocalPort $sqlserverport -Protocol TCP -Action Allow
New-NetFirewallRule -Name "SQL Server 445" -DisplayName "SQL Server 445" -Profile Domain -Direction Inbound -LocalPort 445 -Protocol TCP -Action Allow
New-NetFirewallRule -Name "SQL Server 135" -DisplayName "SQL Server 135" -Profile Domain -Direction Inbound -LocalPort 135 -Protocol TCP -Action Allow
Add-LocalGroupMember -Member $arg[0]\SCOM-Admins -Group Administrators} -ArgumentList $dname
Write-Host "The SQL Server $sqlsrv has been configured" -ForegroundColor DarkCyan
  • Installs Web Console prerequisites (ISS and so on)
Install-WindowsFeature NET-WCF-HTTP-Activation45,Web-Static-Content,Web-Default-Doc,Web-Dir-Browsing,Web-Http-Errors, `
Write-Host "The Web Console prerequisites have been installed" -ForegroundColor DarkCyan
  • Installs the SCOM Server (OMServer, OMConsole and OMWebConsole).
$arglist= @("/install /components:OMServer,OMConsole,OMWebConsole /ManagementGroupName:$mgmtgroup /SqlServerInstance:$sqlsrv\$sqlinstancename /SqlInstancePort:$sqlserverport",
"/DatabaseName:OperationsManager /DWSqlServerInstance:$sqlsrv\$sqlinstancename /DWDatabaseName:OperationsManagerDW /ActionAccountUser:$dname\",
"/ActionAccountPassword:$svcpass /DASAccountUser:$dname\scom.aa /DASAccountPassword:$svcpass /DataReaderUser:$dname\scom.dwr",
"/DataReaderPassword:$svcpass /DataWriterUser:$dname\scom.dww /DataWriterPassword:$svcpass /WebSiteName:""Default Web Site""",
'/WebConsoleAuthorizationMode:Mixed /EnableErrorReporting:Always /SendCEIPReports:1 /UseMicrosoftUpdate:1 /AcceptEndUserLicenseAgreement:1 /silent')
Start-Process -FilePath $env:systemdrive\SCOM2016\setup.exe -ArgumentList $arglist -Wait
Write-Host "The SCOM has been installed. Don't forget to license SCOM" -ForegroundColor DarkCyan
  • Once SCOM is installed, verify installation logs located at  <username>\AppData\Local\SCOM\LOGS\OpsMgrSetupWizard.txt .
    Additionally, don’t forget to set a valid SCOM 2016 product key by using the  Set-SCOMLicense –ProductId <key>


That’s it. Just run the script, provide values for SQL Server connection/credentials and etc and wait until the SCOM installation is complete.

I uploaded the script, so feel free to use it (please mention my blog once you shared the script or part of it. Let’s respect each other!)