Build and Validate a Cluster-Ready Host

PowerShell Deployment and Validation

Build and Validate a Cluster-Ready Host

This is where the keyboards come out.

Posts 1 through 4 made the business case, dismantled the myths, and confirmed your hardware is ready. Now it’s time to build something. In this fifth post of the Hyper-V Renaissance series, we’re going to take a bare-metal server, or a freshly wiped former VMware host, and turn it into a production-ready Hyper-V node that’s fully validated for cluster membership.

Every step is scripted. Every configuration is documented. If you can’t reproduce it with PowerShell, it doesn’t belong in a production deployment.

Repository: All scripts from this post are available in the series repository.


What We’re Building

By the end of this post, you’ll have a Hyper-V host with the following configuration:

ComponentConfiguration
OSWindows Server 2025 Datacenter (Server Core or Desktop Experience)
RolesHyper-V, Failover Clustering
NetworkingSwitch Embedded Teaming (SET) virtual switch with separated traffic (Management, Live Migration, Storage, VM)
StorageMPIO configured, iSCSI or FC connectivity ready
ValidationTest-Cluster passed, network validated, storage latency baselined

You’ll repeat this process for each node in your cluster. Post 8 ties it all together into a complete cluster deployment.


Prerequisites

Before you begin, ensure you have the following:

RequirementDetails
Server hardwareValidated per Post 4 (BIOS configured, firmware current)
Windows Server 2025 mediaISO or USB boot media with Datacenter edition
LicensingWindows Server 2025 Datacenter product key or KMS/ADBA activation
Network infrastructureAt least two physical NICs (four recommended), switch ports configured with appropriate VLANs
Storage infrastructureiSCSI target or FC fabric accessible from the host (covered in detail in Post 6)
Active DirectoryDomain controller accessible on the management network
DNSForward and reverse lookup zones configured

Phase 1: Windows Server 2025 Installation

Install Windows Server 2025 Datacenter from your preferred media. If you’re automating at scale, use an unattended answer file or your existing deployment solution (MDT, SCCM/MECM, or PXE). For a single host build, a standard interactive install works fine.

Server Core vs. Desktop Experience: Server Core is the recommended deployment option for Hyper-V hosts. It has a smaller attack surface, fewer updates, and lower resource overhead. Everything we do in this guide works on both options. If your team isn’t comfortable with Server Core yet, Desktop Experience works, you can always convert later.

Once Windows is installed and you’ve set the local administrator password, connect via RDP or the console and open an elevated PowerShell session.

Initial Host Configuration

# ============================================================
# Phase 1: Base OS Configuration
# ============================================================

# Set the hostname
$HostName = "HV-NODE-01"
Rename-Computer -NewName $HostName -Force

# Set the time zone (adjust for your location)
Set-TimeZone -Id "Eastern Standard Time"

# Configure Windows Update to download but not auto-install
# (You control when hosts reboot, not Microsoft)
$AutoUpdate = (New-Object -ComObject Microsoft.Update.AutoUpdate)
# For Server Core, use Group Policy or registry:
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" `
    -Name "AUOptions" -Value 3 -Type DWord -Force

# Enable Remote Desktop
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" `
    -Name "fDenyTSConnections" -Value 0 -Force
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"

# Enable Remote Management (for WAC and remote PowerShell)
Enable-PSRemoting -Force
winrm quickconfig -quiet

# Restart to apply hostname change
Restart-Computer -Force

After the reboot, reconnect and join the domain:

# Join Active Directory domain
$Credential = Get-Credential -Message "Enter domain admin credentials"
Add-Computer -DomainName "yourdomain.local" -Credential $Credential `
    -OUPath "OU=Hyper-V Hosts,OU=Servers,DC=yourdomain,DC=local" -Force
Restart-Computer -Force

Phase 2: Install Required Roles and Features

After the domain join, install all the roles and features needed for a cluster-ready Hyper-V host in a single pass:

# ============================================================
# Phase 2: Roles and Features Installation
# ============================================================

# Install Hyper-V, Failover Clustering, and supporting features
$Features = @(
    "Hyper-V",
    "Failover-Clustering",
    "Multipath-IO",
    "RSAT-Clustering-PowerShell",
    "RSAT-Hyper-V-Tools",
    "Hyper-V-PowerShell",
    "Data-Center-Bridging"
)

Install-WindowsFeature -Name $Features -IncludeManagementTools -Restart

# After reboot, verify installation
Get-WindowsFeature | Where-Object { $_.Installed -eq $true -and $_.Name -in $Features } |
    Format-Table Name, InstallState -AutoSize

What each feature provides:

FeaturePurpose
Hyper-VThe hypervisor role itself
Failover-ClusteringWindows Server Failover Clustering for HA
Multipath-IORedundant storage paths (iSCSI/FC)
RSAT-Clustering-PowerShellCluster management cmdlets
RSAT-Hyper-V-ToolsHyper-V management tools (includes Hyper-V Manager on Desktop Experience)
Hyper-V-PowerShellHyper-V PowerShell module
Data-Center-BridgingRequired for RDMA/RoCEv2 and priority flow control

Phase 3: Network Configuration

Networking is where most Hyper-V deployments either shine or fall apart. We’re going to build this right from the start using Switch Embedded Teaming (SET), which is the supported and recommended approach for Windows Server 2025 Hyper-V hosts.

Why SET Instead of LBFO NIC Teaming

Traditional LBFO NIC Teaming is deprecated for Hyper-V deployments as of Windows Server 2022. Microsoft explicitly recommends Switch Embedded Teaming (SET) for Hyper-V virtual switches. SET combines the virtual switch and the NIC team into a single construct, which simplifies management, supports RDMA on host virtual NICs, and is compatible with SR-IOV on Windows Server 2025.

Network Design

For a production cluster, you need separated traffic types. Here’s the reference architecture:

Traffic TypeVLANSubnetBandwidthPurpose
Management1010.10.10.0/241-10 GbpsRDP, WAC, domain communication
Live Migration2010.10.20.0/2410-25 GbpsVM live migration traffic
Storage3010.10.30.0/2410-25 GbpsiSCSI, SMB3 storage traffic
VM Network10010.10.100.0/2410-25 GbpsVirtual machine production traffic

Inventory Your Physical NICs

Before configuring anything, document what you’re working with:

# Discover physical network adapters
Get-NetAdapter -Physical |
    Select-Object Name, InterfaceDescription, LinkSpeed, MacAddress, Status |
    Format-Table -AutoSize

# Check for RDMA capability
Get-NetAdapterRdma | Format-Table Name, Enabled, OperationalState -AutoSize

# Check for SR-IOV capability
Get-NetAdapterSriov | Format-Table Name, Enabled, NumVFs -AutoSize

Create the SET Virtual Switch

This is the core networking construct. We’re creating a single SET-enabled virtual switch that bonds multiple physical NICs and provides all traffic segregation through virtual NICs (vNICs):

# ============================================================
# Phase 3: SET Virtual Switch Configuration
# ============================================================

# Define the physical NICs to include in the SET team
# Replace with your actual adapter names from Get-NetAdapter
$TeamMembers = @("NIC1", "NIC2", "NIC3", "NIC4")

# Create the SET virtual switch
New-VMSwitch -Name "SET-Switch" `
    -NetAdapterName $TeamMembers `
    -EnableEmbeddedTeaming $true `
    -AllowManagementOS $true `
    -MinimumBandwidthMode Weight

Write-Host "SET Switch created successfully." -ForegroundColor Green

Create Host Virtual NICs (vNICs)

Now create separate virtual NICs for each traffic type and assign VLANs:

# The management vNIC is created automatically when AllowManagementOS = $true
# Rename it for clarity
Rename-VMNetworkAdapter -ManagementOS -Name "SET-Switch" -NewName "Management"

# Create additional vNICs for separated traffic
Add-VMNetworkAdapter -ManagementOS -SwitchName "SET-Switch" -Name "LiveMigration"
Add-VMNetworkAdapter -ManagementOS -SwitchName "SET-Switch" -Name "Storage"

# Assign VLANs to each vNIC
Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName "Management" -Access -VlanId 10
Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName "LiveMigration" -Access -VlanId 20
Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName "Storage" -Access -VlanId 30

# Assign IP addresses
New-NetIPAddress -InterfaceAlias "vEthernet (Management)" `
    -IPAddress "10.10.10.11" -PrefixLength 24 -DefaultGateway "10.10.10.1"
Set-DnsClientServerAddress -InterfaceAlias "vEthernet (Management)" `
    -ServerAddresses "10.10.10.5","10.10.10.6"

New-NetIPAddress -InterfaceAlias "vEthernet (LiveMigration)" `
    -IPAddress "10.10.20.11" -PrefixLength 24

New-NetIPAddress -InterfaceAlias "vEthernet (Storage)" `
    -IPAddress "10.10.30.11" -PrefixLength 24

# Set bandwidth weights (ensure critical traffic gets priority)
Set-VMNetworkAdapter -ManagementOS -Name "Management" -MinimumBandwidthWeight 10
Set-VMNetworkAdapter -ManagementOS -Name "LiveMigration" -MinimumBandwidthWeight 30
Set-VMNetworkAdapter -ManagementOS -Name "Storage" -MinimumBandwidthWeight 40

Write-Host "Host vNICs configured with VLAN separation." -ForegroundColor Green

Verify the Network Configuration

# Verify SET switch team
Get-VMSwitch | Format-Table Name, SwitchType, EmbeddedTeamingEnabled -AutoSize
Get-VMSwitchTeam | Format-List *

# Verify host vNICs
Get-VMNetworkAdapter -ManagementOS |
    Select-Object Name, SwitchName, MacAddress, Status |
    Format-Table -AutoSize

# Verify VLAN assignments
Get-VMNetworkAdapterVlan -ManagementOS | Format-Table -AutoSize

# Verify IP addressing
Get-NetIPAddress -InterfaceAlias "vEthernet*" |
    Select-Object InterfaceAlias, IPAddress, PrefixLength |
    Format-Table -AutoSize

# Test connectivity on each vNIC
Test-NetConnection -ComputerName "10.10.10.1" -InformationLevel Detailed  # Gateway
Test-NetConnection -ComputerName "10.10.10.5" -InformationLevel Detailed  # DNS

If your NICs support RDMA (iWARP or RoCEv2), enable it on the Live Migration and Storage vNICs for significantly improved performance:

# Enable RDMA on the Live Migration and Storage vNICs
Enable-NetAdapterRdma -Name "vEthernet (LiveMigration)"
Enable-NetAdapterRdma -Name "vEthernet (Storage)"

# Verify RDMA is enabled
Get-NetAdapterRdma -Name "vEthernet*" | Format-Table Name, Enabled -AutoSize

# For RoCEv2, configure Data Center Bridging (DCB) priority flow control
# This requires matching configuration on your physical switches
Install-WindowsFeature Data-Center-Bridging

# Create a QoS policy for RDMA traffic
New-NetQosPolicy -Name "SMB" -NetDirectPortMatchCondition 445 -PriorityValue8021Action 3
New-NetQosPolicy -Name "ClusterHeartbeat" -Cluster -PriorityValue8021Action 7

# Enable flow control for RDMA priority class
Enable-NetQosFlowControl -Priority 3
Disable-NetQosFlowControl -Priority 0,1,2,4,5,6,7

# Enable DCB on physical adapters
foreach ($Adapter in $TeamMembers) {
    Enable-NetAdapterQos -Name $Adapter
}

Write-Host "RDMA and DCB configured." -ForegroundColor Green

Important: RDMA configuration (especially RoCEv2/DCB) requires matching configuration on your physical network switches. Work with your network team to ensure Priority Flow Control (PFC) and Enhanced Transmission Selection (ETS) are configured consistently end-to-end. iWARP-based RDMA is more forgiving and doesn’t require DCB switch configuration.


Phase 4: Storage Preparation

This phase prepares the host for external storage connectivity. We’ll cover iSCSI here since it’s the most common protocol for organizations without existing Fibre Channel infrastructure. Post 6 covers storage integration in detail across all protocols.

Configure MPIO for iSCSI

# ============================================================
# Phase 4: Storage Preparation
# ============================================================

# MPIO should already be installed from Phase 2
# Enable MPIO support for iSCSI devices
Enable-MSDSMAutomaticClaim -BusType iSCSI

# Verify MPIO is configured for iSCSI
Get-MSDSMAutomaticClaimSettings

# The server needs a reboot after enabling iSCSI MPIO claims
Restart-Computer -Force

After the reboot, configure the iSCSI Initiator:

# Start the iSCSI Initiator service and set to auto-start
Set-Service -Name MSiSCSI -StartupType Automatic
Start-Service -Name MSiSCSI

# Get the iSCSI Initiator IQN (you'll need this for storage array configuration)
$IQN = (Get-InitiatorPort).NodeAddress
Write-Host "iSCSI Initiator IQN: $IQN" -ForegroundColor Cyan

# Add iSCSI target portals (replace with your storage array IPs)
New-IscsiTargetPortal -TargetPortalAddress "10.10.30.100" -InitiatorPortalAddress "10.10.30.11"
New-IscsiTargetPortal -TargetPortalAddress "10.10.30.101" -InitiatorPortalAddress "10.10.30.11"

# Discover available targets
Get-IscsiTarget

# Connect to targets with MPIO (repeat for each path)
# Replace the NodeAddress with the IQN from your storage array
$TargetIQN = "iqn.2010-06.com.storagevendor:targetname"

Connect-IscsiTarget -NodeAddress $TargetIQN `
    -TargetPortalAddress "10.10.30.100" `
    -InitiatorPortalAddress "10.10.30.11" `
    -IsPersistent $true `
    -IsMultipathEnabled $true

Connect-IscsiTarget -NodeAddress $TargetIQN `
    -TargetPortalAddress "10.10.30.101" `
    -InitiatorPortalAddress "10.10.30.11" `
    -IsPersistent $true `
    -IsMultipathEnabled $true

# Verify iSCSI sessions
Get-IscsiSession | Format-Table InitiatorNodeAddress, TargetNodeAddress,
    IsConnected, IsPersistent -AutoSize

# Verify MPIO paths
Get-IscsiConnection | Format-Table ConnectionIdentifier, InitiatorAddress,
    TargetAddress -AutoSize

# Check MPIO policy on connected disks
Get-MSDSMGlobalDefaultLoadBalancePolicy
mpclaim -s -d  # Shows multipath devices and paths

Configure the SAN Policy

By default, Windows Server may keep SAN disks offline. Set the SAN policy to bring new disks online automatically:

# Set SAN policy to online shared disks (required for clustering)
Set-StorageSetting -NewDiskPolicy OnlineAll

Note: If you’re using Fibre Channel instead of iSCSI, MPIO configuration is similar but the transport setup differs. Your FC HBA vendor provides host utilities that set appropriate timeout values and MPIO policies. See Post 6 for FC-specific guidance.


Phase 5: Hyper-V Host Configuration

With roles installed, networking configured, and storage connected, configure the Hyper-V host settings:

# ============================================================
# Phase 5: Hyper-V Host Configuration
# ============================================================

# Set default VM storage paths
$VMPath = "C:\ClusterStorage\Volume1\VMs"       # Will be a CSV after clustering
$VHDPath = "C:\ClusterStorage\Volume1\VHDs"      # Adjust per your storage design

# For now, set temporary local paths (updated after cluster creation)
Set-VMHost -VirtualMachinePath "D:\VMs" -VirtualHardDiskPath "D:\VHDs"

# Create the directories if they don't exist
New-Item -Path "D:\VMs" -ItemType Directory -Force
New-Item -Path "D:\VHDs" -ItemType Directory -Force

# Configure Live Migration settings
Enable-VMMigration
Set-VMMigrationNetwork "10.10.20.0/24"  # Use the Live Migration VLAN

# Set authentication protocol for live migration
# Kerberos is recommended for domain-joined hosts (constrained delegation required)
# CredSSP is simpler but less secure
Set-VMHost -VirtualMachineMigrationAuthenticationType Kerberos

# Set maximum simultaneous live migrations
# Rule of thumb: 1 per 10 Gbps of live migration bandwidth
Set-VMHost -MaximumVirtualMachineMigrations 4

# Set maximum storage migrations
Set-VMHost -MaximumStorageMigrations 2

# Enable NUMA spanning (default, but verify)
Set-VMHost -NumaSpanningEnabled $true

# Configure enhanced session mode (Desktop Experience only)
Set-VMHost -EnableEnhancedSessionMode $true

# Verify host configuration
Get-VMHost | Format-List VirtualMachinePath, VirtualHardDiskPath,
    VirtualMachineMigrationEnabled, VirtualMachineMigrationAuthenticationType,
    MaximumVirtualMachineMigrations, MaximumStorageMigrations, NumaSpanningEnabled

Configure Kerberos Constrained Delegation (for Live Migration)

If you chose Kerberos authentication for live migration (recommended), configure constrained delegation in Active Directory. Run this from a domain controller or a machine with the AD PowerShell module:

# Run on a domain controller or machine with RSAT-AD-PowerShell
# Allow HV-NODE-01 to delegate to HV-NODE-02 for CIFS and Microsoft Virtual System Migration Service

$SourceNode = "HV-NODE-01"
$TargetNode = "HV-NODE-02"

# Get the computer objects
$Source = Get-ADComputer $SourceNode
$Target = Get-ADComputer $TargetNode

# Configure delegation for live migration and shared storage
Set-ADComputer -Identity $Source -Add @{
    'msDS-AllowedToDelegateTo' = @(
        "cifs/$TargetNode",
        "cifs/$TargetNode.yourdomain.local",
        "Microsoft Virtual System Migration Service/$TargetNode",
        "Microsoft Virtual System Migration Service/$TargetNode.yourdomain.local"
    )
}

# Repeat in reverse direction
Set-ADComputer -Identity $Target -Add @{
    'msDS-AllowedToDelegateTo' = @(
        "cifs/$SourceNode",
        "cifs/$SourceNode.yourdomain.local",
        "Microsoft Virtual System Migration Service/$SourceNode",
        "Microsoft Virtual System Migration Service/$SourceNode.yourdomain.local"
    )
}

Write-Host "Kerberos constrained delegation configured for live migration." -ForegroundColor Green

Phase 6: Pre-Cluster Validation

This is the “trust but verify” checkpoint. Before this host joins or forms a cluster, it must pass validation. Microsoft requires a passing cluster validation report as a condition of support for failover cluster configurations.

Network Validation

# ============================================================
# Phase 6: Comprehensive Validation
# ============================================================

# --- Network Validation ---

Write-Host "=== Network Validation ===" -ForegroundColor Cyan

# 1. Verify all vNICs are up
$vNICs = Get-NetAdapter -Name "vEthernet*"
foreach ($vNIC in $vNICs) {
    $status = if ($vNIC.Status -eq "Up") { "PASS" } else { "FAIL" }
    $color = if ($status -eq "PASS") { "Green" } else { "Red" }
    Write-Host "  $($vNIC.Name): $status ($($vNIC.LinkSpeed))" -ForegroundColor $color
}

# 2. Verify VLAN tagging
Get-VMNetworkAdapterVlan -ManagementOS | ForEach-Object {
    Write-Host "  $($_.ParentAdapter.Name): VLAN $($_.AccessVlanId)" -ForegroundColor White
}

# 3. Test connectivity on each network
$PingTests = @(
    @{ Name = "Gateway"; Target = "10.10.10.1"; Interface = "vEthernet (Management)" },
    @{ Name = "DNS"; Target = "10.10.10.5"; Interface = "vEthernet (Management)" },
    @{ Name = "DC"; Target = "10.10.10.5"; Interface = "vEthernet (Management)" }
)

foreach ($Test in $PingTests) {
    $Result = Test-NetConnection -ComputerName $Test.Target -WarningAction SilentlyContinue
    $status = if ($Result.TcpTestSucceeded -or $Result.PingSucceeded) { "PASS" } else { "FAIL" }
    $color = if ($status -eq "PASS") { "Green" } else { "Red" }
    Write-Host "  Ping $($Test.Name) ($($Test.Target)): $status" -ForegroundColor $color
}

# 4. Verify DNS resolution
$DNSTest = Resolve-DnsName -Name "yourdomain.local" -ErrorAction SilentlyContinue
if ($DNSTest) {
    Write-Host "  DNS Resolution: PASS" -ForegroundColor Green
} else {
    Write-Host "  DNS Resolution: FAIL" -ForegroundColor Red
}

# 5. Verify SET team health
$TeamInfo = Get-VMSwitchTeam
Write-Host "`n  SET Team Members:" -ForegroundColor White
foreach ($Member in $TeamInfo.NetAdapterInterfaceDescription) {
    $Adapter = Get-NetAdapter -InterfaceDescription $Member
    $color = if ($Adapter.Status -eq "Up") { "Green" } else { "Red" }
    Write-Host "    $($Adapter.Name): $($Adapter.Status) ($($Adapter.LinkSpeed))" -ForegroundColor $color
}

Storage Validation

# --- Storage Validation ---

Write-Host "`n=== Storage Validation ===" -ForegroundColor Cyan

# 1. Check iSCSI sessions
$Sessions = Get-IscsiSession
Write-Host "  Active iSCSI Sessions: $($Sessions.Count)" -ForegroundColor White
$Sessions | ForEach-Object {
    Write-Host "    Target: $($_.TargetNodeAddress) Connected: $($_.IsConnected)" -ForegroundColor White
}

# 2. Check MPIO paths
Write-Host "`n  MPIO Paths:" -ForegroundColor White
$MPIODisks = Get-MSDSMGlobalDefaultLoadBalancePolicy
Write-Host "    Default LB Policy: $MPIODisks" -ForegroundColor White

# 3. Check visible disks
$Disks = Get-Disk | Where-Object { $_.BusType -ne "NVMe" -and $_.BusType -ne "SATA" -and $_.Number -gt 0 }
Write-Host "`n  SAN Disks Visible: $($Disks.Count)" -ForegroundColor White
foreach ($Disk in $Disks) {
    Write-Host "    Disk $($Disk.Number): $([math]::Round($Disk.Size / 1GB, 2)) GB - $($Disk.BusType) - $($Disk.OperationalStatus)" -ForegroundColor White
}

# 4. Quick storage latency test (write to iSCSI disk if available)
if ($Disks.Count -gt 0) {
    Write-Host "`n  Running basic I/O test..." -ForegroundColor Yellow
    # Simple sequential write test using diskspd or a basic file operation
    # For a proper baseline, use DiskSpd:
    # https://aka.ms/diskspd
    Write-Host "  (Use DiskSpd for production-grade storage baseline testing)" -ForegroundColor Gray
}

Role and Feature Validation

# --- Role and Feature Validation ---

Write-Host "`n=== Role and Feature Validation ===" -ForegroundColor Cyan

$RequiredFeatures = @(
    "Hyper-V", "Failover-Clustering", "Multipath-IO",
    "RSAT-Clustering-PowerShell", "Hyper-V-PowerShell"
)

foreach ($Feature in $RequiredFeatures) {
    $Installed = Get-WindowsFeature -Name $Feature
    $status = if ($Installed.InstallState -eq "Installed") { "PASS" } else { "FAIL" }
    $color = if ($status -eq "PASS") { "Green" } else { "Red" }
    Write-Host "  $($Feature): $status" -ForegroundColor $color
}

# Verify Hyper-V hypervisor is running
$HypervisorPresent = (Get-CimInstance Win32_ComputerSystem).HypervisorPresent
$color = if ($HypervisorPresent) { "Green" } else { "Red" }
Write-Host "  Hypervisor Present: $HypervisorPresent" -ForegroundColor $color

Run Test-Cluster (Pre-Cluster Validation)

When you have two or more nodes prepared, run the full cluster validation test. This is the most important validation step and produces the report that Microsoft requires for support.

# --- Cluster Validation ---
# Run this when ALL nodes are prepared
# Replace node names with your actual hostnames

$Nodes = @("HV-NODE-01", "HV-NODE-02")

Write-Host "`n=== Running Cluster Validation ===" -ForegroundColor Cyan
Write-Host "This will take 10-30 minutes depending on configuration." -ForegroundColor Yellow

# Run all validation tests
Test-Cluster -Node $Nodes -Verbose

# The report is saved to:
# C:\Windows\Cluster\Reports\Validation Report <DateTime>.html
$ReportPath = Get-ChildItem "$env:SystemRoot\Cluster\Reports" -Filter "Validation*" |
    Sort-Object LastWriteTime -Descending | Select-Object -First 1
Write-Host "`nValidation report saved to: $($ReportPath.FullName)" -ForegroundColor Green

# If you only want to run specific test categories:
# Test-Cluster -Node $Nodes -Include "Network","Inventory","System Configuration"
# Available categories: Cluster Configuration, Hyper-V Configuration,
#   Inventory, Network, Storage, System Configuration

What Test-Cluster Validates

Test CategoryWhat It Checks
InventoryHardware, software, drivers, updates consistency across nodes
NetworkAdapter configuration, connectivity between nodes, IP addressing, firewall rules
StorageDisk access, MPIO paths, simultaneous access, failover behavior
System ConfigurationAD configuration, OS versions, required services, time sync
Hyper-V ConfigurationHyper-V role settings, virtual switch consistency, live migration readiness

Interpreting Results

The validation report uses three indicators:

  • Green checkmark: Test passed , configuration meets Microsoft requirements.
  • Yellow triangle: Warning , the configuration works but doesn’t meet all best practices. Investigate these, but they don’t block cluster creation.
  • Red X: Failure , this issue must be resolved before creating the cluster. Common failures include mismatched drivers between nodes, network connectivity issues, or storage path problems.

Keep the validation report. Microsoft Support will request it if you ever open a cluster-related support case.


Phase 7: Host Hardening (Quick Wins)

Apply essential security hardening before putting this host into production. Full security architecture is covered in Post 10, but these are the baseline items:

# ============================================================
# Phase 7: Basic Host Hardening
# ============================================================

# Enable Windows Defender (should be on by default)
Set-MpPreference -DisableRealtimeMonitoring $false

# Add exclusions for Hyper-V (prevents performance issues)
$HyperVExclusions = @(
    "D:\VMs",
    "D:\VHDs",
    "%ProgramData%\Microsoft\Windows\Hyper-V",
    "%SystemRoot%\System32\vmms.exe",
    "%SystemRoot%\System32\vmwp.exe",
    "%SystemRoot%\System32\vmcompute.exe"
)
foreach ($Exclusion in $HyperVExclusions) {
    Add-MpPreference -ExclusionPath $Exclusion
}
Add-MpPreference -ExclusionExtension "vhd","vhdx","avhd","avhdx","vhds","iso"

# Enable Credential Guard (protects domain credentials)
# Requires UEFI Secure Boot and TPM 2.0
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\DeviceGuard" `
    -Name "EnableVirtualizationBasedSecurity" -Value 1 -Type DWord
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" `
    -Name "LsaCfgFlags" -Value 1 -Type DWord

# Disable unnecessary services
$DisableServices = @(
    "Browser",      # Computer Browser
    "lltdsvc",      # Link-Layer Topology Discovery Mapper
    "rspndr",       # Link-Layer Topology Discovery Responder
    "SharedAccess",  # Internet Connection Sharing
    "WlanSvc"       # WLAN AutoConfig (no WiFi on servers)
)
foreach ($Svc in $DisableServices) {
    $Service = Get-Service -Name $Svc -ErrorAction SilentlyContinue
    if ($Service) {
        Set-Service -Name $Svc -StartupType Disabled -ErrorAction SilentlyContinue
        Stop-Service -Name $Svc -Force -ErrorAction SilentlyContinue
    }
}

# Enable SMB encryption for cluster communication
Set-SmbServerConfiguration -EncryptData $true -Force

Write-Host "Basic host hardening applied." -ForegroundColor Green

The Complete Build Checklist

Use this checklist for each node you deploy:

PhaseItemStatus
OSWindows Server 2025 Datacenter installed
OSHostname set, domain joined
OSTime zone and NTP configured
RolesHyper-V role installed
RolesFailover Clustering installed
RolesMPIO installed and configured
NetworkSET virtual switch created
NetworkManagement vNIC configured with IP/VLAN
NetworkLive Migration vNIC configured with IP/VLAN
NetworkStorage vNIC configured with IP/VLAN
NetworkRDMA enabled (if applicable)
NetworkAll connectivity tests pass
StorageiSCSI/FC connectivity established
StorageMPIO paths verified
StorageSAN disks visible
Hyper-VDefault paths configured
Hyper-VLive migration enabled and configured
Hyper-VKerberos delegation configured
SecurityWindows Defender exclusions set
SecurityCredential Guard enabled
ValidationTest-Cluster passes all tests
ValidationValidation report saved

Troubleshooting Common Issues

SET Switch Creation Fails

If New-VMSwitch with -EnableEmbeddedTeaming fails, verify that:

  • All specified NICs are the same speed (mixing 1 GbE and 10 GbE is not supported in a SET team)
  • None of the NICs are already bound to another switch or LBFO team
  • The NICs support the same driver version

RDMA Doesn’t Enable on vNICs

RDMA on SET host vNICs requires that the underlying physical NICs support RDMA and have current drivers. Verify with Get-NetAdapterRdma -Name "PhysicalNICName" on each team member. Also confirm that your physical switches support and have DCB/PFC configured if using RoCEv2.

iSCSI Targets Not Discovered

Check that the iSCSI Initiator service is running (Get-Service MSiSCSI), the storage VLAN is correctly tagged, and the target portal IP is reachable from the storage vNIC (Test-NetConnection -ComputerName "10.10.30.100" -Port 3260).

Test-Cluster Shows Network Warnings

The most common network warning is nodes having different network configurations. Ensure all nodes have the same VLANs, the same number of vNICs, consistent IP subnets, and matching MTU settings. Test-Cluster checks for consistency across all nodes.


Next Steps

You now have a fully configured, validated Hyper-V host ready for cluster membership. Repeat this process on each additional node, keeping configurations consistent across all nodes.

In the next post, Post 6: Three-Tier Storage Integration, we’ll connect your hosts to external storage arrays using iSCSI, Fibre Channel, and SMB3, covering universal principles that work with any vendor and including a detailed Pure Storage reference implementation.

The foundation is laid. Time to connect the storage.


Resources

Microsoft Documentation


Series Navigation ← Previous: Post 4 , Reusing Your Existing VMware Hosts → Next: Post 6 , Three-Tier Storage Integration