Hyper-V 2019 R2 using Failover Clustering with CSV and SCVMM 2019

Reference topology

IP plan (sample):


Host firmware & OS prep

  1. Update BIOS, NIC, HBA, NVMe/SSD firmware to vendor HCL for S2D.

  2. In storage controllers: Disable RAID, set drives to JBOD/HBA mode. Enable NVMe if applicable.

  3. Install Windows Server 2019 Datacenter, latest cumulative updates.

  4. Join all hosts to the same AD domain. Ensure consistent time/NTP.

  5. Name resolution: hosts resolve each other by A records; reverse lookup zones present.

PowerShell on each host (elevated):

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V, Failover-Clustering, FS-FileServer, RSAT-Clustering-PowerShell, DataCenterBridging -All
Install-WindowsFeature -Name Hyper-V, Failover-Clustering, FS-FileServer, RSAT-Clustering-PowerShell, RSAT-Hyper-V-Tools -IncludeManagementTools

If using BitLocker on data drives, plan to enable Auto-unlock for S2D volumes later (don’t encrypt before pool creation).


Networking on hosts

RDMA / DCB (if RoCEv2)

Example host config (adjust NIC names):

# Identify NICs for Storage (RDMA)
Get-NetAdapter | Where-Object {$_.Name -like "Storage*"} | Enable-NetAdapterRdma

# If RoCEv2: enable DCB and set ETS/PFC (example; use vendor guidance for exact priorities)
Install-WindowsFeature Data-Center-Bridging
New-NetQosPolicy "SMB" -NetDirectPortMatchCondition 445 -PriorityValue8021Action 3
Enable-NetQosFlowControl -Priority 3
Disable-NetQosFlowControl -Priority 0,1,2,4,5,6,7
Set-NetQosDcbxSetting -Willing 0
Enable-NetAdapterQos -Name "Storage1","Storage2"

On each host, create a Hyper-V SET switch for VM/Li-Mig/mgmt (or separate switches if you prefer):

New-VMSwitch -Name "vSwitch-Host" -NetAdapterName "Mgmt1","Mgmt2" -EnableEmbeddedTeaming $true -AllowManagementOS $true

# Tag VLANs if needed
Set-VMNetworkAdapter -ManagementOS -Name "vEthernet (vSwitch-Host)" -VlanID 10  # Mgmt VLAN example

Assign dedicated IPs for Storage NICs (no default gateway on storage VLAN):

New-NetIPAddress -InterfaceAlias "Storage1" -IPAddress 172.16.0.11 -PrefixLength 24
New-NetIPAddress -InterfaceAlias "Storage2" -IPAddress 172.16.0.12 -PrefixLength 24

Live Migration settings

Enable-VMMigration
Set-VMHost -VirtualMachineMigrationAuthenticationType CredSSP -VirtualMachineMigrationPerformanceOption SMB
Add-VMMigrationNetwork 10.20.0.0/24

Storage sanity checks (pre-S2D)

On one host, validate disks are visible as CanPool:

Get-PhysicalDisk | ft FriendlyName, CanPool, MediaType, Size, HealthStatus

All S2D-candidate disks must be CanPool = True (system OS disk won’t be). If false, clear metadata:

Get-PhysicalDisk -CanPool $False | Where MediaType -ne "Unspecified" # sanity check
# If needed (be careful):
# Reset-PhysicalDisk -FriendlyName "PhysicalDiskX"

Build the Failover Cluster (no S2D yet)

From any host (or an admin workstation):

Validation

Test-Cluster -Node Host1,Host2,Host3,Host4 -Include "Storage","Inventory","Network","SystemConfiguration" -Verbose

Fix all Errors. Warnings for S2D disks are typical pre-enable.

Create cluster

New-Cluster -Name HVCL01 -Node Host1,Host2,Host3,Host4 -StaticAddress 10.10.0.50 -NoStorage

Quorum witness

Azure Cloud Witness (recommended):

Set-ClusterQuorum -CloudWitness -AccountName "<StorageAccountName>" -AccessKey "<Key>"

(or file share witness if preferred)


Enable S2D on the cluster

From one node:

Enable-ClusterS2D -Confirm:$false -CacheState Enabled
# or explicit:
# Enable-ClusterS2D -AutoConfig:Enabled -Confirm:$false

This creates a cluster storage pool named like S2D on HVCL01.

Create storage tiers (example: hybrid)

# Discover mediatypes
Get-PhysicalDisk | Group MediaType, CanPool | ft Count, Name

# Create tiers
New-StorageTier -StoragePoolFriendlyName "S2D on HVCL01" -FriendlyName "Capacity" -MediaType HDD
New-StorageTier -StoragePoolFriendlyName "S2D on HVCL01" -FriendlyName "Performance" -MediaType SSD

Example: 2× volumes with nested tiers:

# Example sizes—adjust to capacity
New-Volume -StoragePoolFriendlyName "S2D on HVCL01" -FriendlyName "CSV01" `
  -FileSystem ReFS -StorageTierFriendlyNames Performance,Capacity `
  -StorageTierSizes 500GB,2TB -AllocationUnitSize 64KB

New-Volume -StoragePoolFriendlyName "S2D on HVCL01" -FriendlyName "CSV02" `
  -FileSystem ReFS -StorageTierFriendlyNames Performance,Capacity `
  -StorageTierSizes 500GB,2TB -AllocationUnitSize 64KB

These auto-mount as Cluster Shared Volumes under C:\ClusterStorage\CSV01, etc.

(Optional) CSV cache for read-heavy Hyper-V:

(Get-Cluster).BlockCacheSize = 2048  # in MB

Hyper-V host tuning (cluster-wide)

# Live migration: SMB over storage/LM network
(Get-Cluster).RouteHistoryLength = 30 # optional visibility tuning
Set-ClusterParameter -InputObject (Get-ClusterNetwork | ? {$_.Role -eq 1}) -Name Metric -Value 100 # Example network metric tuning

# Enable VMQ/NOT on mgmt NICs (vendor guidance), SR-IOV if supported
# Ensure Time Sync, Integration Services (2019 uses in-box components)

Bring SCVMM 2019 into the picture

Prep SCVMM

Add hosts to VMM Fabric

VMM console → FabricServersAdd Hyper-V Hosts and Clusters:

VMM will discover the existing Failover Cluster automatically.

Logical networks & IP Pools

Fabric → Networking:

  1. Logical Network: LN-Mgmt, LN-Storage, LN-LM, LN-VM (with associated sites/VLANs).

  2. IP Pools for Mgmt and Live Migration (Storage often static/no gateway).

Fabric → NetworkingPort Profiles / Logical Switches:

Apply the Logical Switch to each host NIC team (vSwitch-Host). VMM can standardize vNICs on the host (e.g., Mgmt, LM).

VM Networks

Storage classification

Fabric → Storage:

Templates & placement


Live Migration & resiliency checks

  1. In Failover Cluster Manager, Move the test VM between nodes (Live Migration).

  2. Pull a drive (in a maintenance window) or pause a node to validate S2D resiliency.

  3. Check Storage Health:

Get-StoragePool -FriendlyName "S2D on HVCL01" | Get-PhysicalDisk | ft FriendlyName, HealthStatus
Get-StorageSubSystem Cluster* | Get-StorageHealthReport

Maintenance mode / patching


Security & optional features

$vol = Get-Volume -FileSystemLabel "CSV01"
Enable-BitLocker -MountPoint $vol.Path -UsedSpaceOnly -TpmProtector

Common pitfalls & fixes


Quick end-to-end command recap (bare minimum)

# On each host
Install-WindowsFeature Hyper-V, Failover-Clustering, FS-FileServer -IncludeManagementTools
New-VMSwitch -Name "vSwitch-Host" -NetAdapterName "Mgmt1","Mgmt2" -EnableEmbeddedTeaming $true -AllowManagementOS $true
Enable-NetAdapterRdma -Name "Storage1","Storage2"
New-NetIPAddress -InterfaceAlias "Storage1" -IPAddress 172.16.0.11 -PrefixLength 24
New-NetIPAddress -InterfaceAlias "Storage2" -IPAddress 172.16.0.12 -PrefixLength 24

# From one admin node
Test-Cluster -Node Host1,Host2,Host3,Host4
New-Cluster -Name HVCL01 -Node Host1,Host2,Host3,Host4 -StaticAddress 10.10.0.50 -NoStorage
Set-ClusterQuorum -CloudWitness -AccountName "<StorageAccount>" -AccessKey "<Key>"
Enable-ClusterS2D -Confirm:$false

# Create tiers & volumes (examples)
New-StorageTier -StoragePoolFriendlyName "S2D on HVCL01" -FriendlyName "Perf" -MediaType SSD
New-StorageTier -StoragePoolFriendlyName "S2D on HVCL01" -FriendlyName "Cap"  -MediaType HDD
New-Volume -StoragePoolFriendlyName "S2D on HVCL01" -FriendlyName "CSV01" -FileSystem ReFS `
  -StorageTierFriendlyNames Perf,Cap -StorageTierSizes 500GB,2TB -AllocationUnitSize 64KB