Introduction to Cluster-Aware Updating

Cluster-Aware Updating (CAU) is a Windows Server 2019 feature that automates the process of applying software updates to nodes in a Windows Server Failover Cluster while maintaining high availability. CAU orchestrates the drain-update-reboot-resume cycle for each cluster node sequentially, ensuring that the cluster remains available for workloads throughout the update process. It integrates with Windows Update, WSUS, and Microsoft Update Catalog, and can be run in both self-updating mode (the cluster triggers itself on schedule) and remote-updating mode (an administrator or automation tool triggers it externally).

Prerequisites


# Install the CAU feature and Failover Clustering tools on all nodes
Install-WindowsFeature -Name RSAT-Clustering, RSAT-Clustering-PowerShell,
    RSAT-Clustering-AutomationServer -IncludeManagementTools

# Verify CAU cmdlets are available
Get-Command -Module ClusterAwareUpdating

# Verify the cluster is healthy before proceeding
Get-Cluster | Select-Object Name, Domain, SharedVolumesRoot
Get-ClusterNode | Select-Object Name, State, NodeWeight
Get-ClusterResource | Where-Object { $_.State -ne 'Online' }

# Check cluster quorum configuration
Get-ClusterQuorum | Select-Object QuorumResource, QuorumType

# Ensure all nodes are running Windows Server 2019 with matching build
Get-ClusterNode | ForEach-Object {
    Invoke-Command -ComputerName $_.Name -ScriptBlock {
        Get-ComputerInfo | Select-Object CsName, OsBuildNumber, OsVersion
    }
}

CAU Self-Updating Mode Configuration

In self-updating mode, CAU creates a clustered role on the failover cluster that schedules and executes update runs autonomously. This is the recommended mode for clusters with regular maintenance windows:


# Enable CAU self-updating mode on the cluster
# The cluster must have at least one available network for CAU communication
Add-CauClusterRole -ClusterName 'CLUSTER01' `
    -EnableFirewallRules `
    -Force

# Configure the CAU update schedule
# Run every second Tuesday (Patch Tuesday) at 2:00 AM
Add-CauClusterRole -ClusterName 'CLUSTER01' `
    -DaysOfWeek Tuesday `
    -WeeksOfMonth 2 `
    -BeginTime 02:00 `
    -MaxRetriesPerNode 3 `
    -RequireAllNodesOnline `
    -WarnAfter (New-TimeSpan -Hours 4) `
    -StopOnPluginFailure `
    -EnableFirewallRules `
    -Force

# Verify CAU cluster role was added
Get-CauClusterRole -ClusterName 'CLUSTER01' | Format-List

# View the CAU clustered role in Failover Cluster Manager
Get-ClusterResource -Cluster 'CLUSTER01' | Where-Object { $_.ResourceType -eq 'CAU' }

Running a CAU Update in Remote-Updating Mode

Remote-updating mode is triggered by an administrator or automation system from a management workstation. This gives full control over timing and provides a direct view of progress:


# Test run (no changes made) - validates the cluster is CAU-ready
Test-CauSetup -ClusterName 'CLUSTER01' -Verbose

# Invoke-CauRun preview (shows what updates would be installed)
Invoke-CauRun -ClusterName 'CLUSTER01' `
    -MaxFailedNodes 0 `
    -MaxRetriesPerNode 2 `
    -RequireAllNodesOnline `
    -Force

# Start an actual update run
Invoke-CauRun -ClusterName 'CLUSTER01' `
    -CauPluginName 'Microsoft.WindowsUpdatePlugin' `
    -CauPluginArguments @{
        'QueryString' = "IsInstalled=0 and Type='Software' and IsHidden=0"
    } `
    -MaxFailedNodes 0 `
    -MaxRetriesPerNode 3 `
    -RequireAllNodesOnline `
    -WarnAfter (New-TimeSpan -Hours 2) `
    -AttemptSoftReboot `
    -RebootTimeoutMinutes 30 `
    -Force

# Stop an in-progress update run
Stop-CauRun -ClusterName 'CLUSTER01' -Force

Monitoring CAU Progress


# Get the current CAU run status
Get-CauRun -ClusterName 'CLUSTER01'

# Monitor progress in real time (poll every 30 seconds)
do {
    $run = Get-CauRun -ClusterName 'CLUSTER01'
    Write-Output "$(Get-Date -Format HH:mm:ss) - Status: $($run.RunStatus) | Node: $($run.CurrentClusterNode) | Updates: $($run.NumberOfSuccessfullyUpdatedNodes)/$($run.NumberOfNodesToUpdate)"
    Start-Sleep -Seconds 30
} while ($run.RunStatus -in 'Running','NotStarted')

Write-Output "CAU Run completed with status: $($run.RunStatus)"

Configuring CAU Pre/Post-Update Scripts

CAU supports BeforeUpdateScript and AfterUpdateScript hooks that run before draining and after updating each node. Use these to perform application-specific quiesce operations:


# Pre-update script: quiesce SQL Server Availability Group
# C:ScriptsCAU-PreUpdate.ps1
param(
    [string]$CluNode,
    [string]$CluName
)

Write-EventLog -LogName Application -Source 'CAU' -EventId 5000 `
    -EntryType Information -Message "CAU PreUpdate starting for node $CluNode"

# Move SQL AG primary to another node
Import-Module SQLPS -DisableNameChecking
$agPrimary = Get-SqlAvailabilityGroup -ServerInstance "$CluNodeINST1" -ErrorAction SilentlyContinue
if ($agPrimary -and $agPrimary.LocalReplicaRole -eq 'Primary') {
    $agPrimary | Switch-SqlAvailabilityGroup
    Write-Output "AG failover initiated from $CluNode"
}

# Post-update script: verify AG health after node returns
# C:ScriptsCAU-PostUpdate.ps1
param([string]$CluNode, [string]$CluName)

$timeout = 300
$stopWatch = [System.Diagnostics.Stopwatch]::StartNew()
do {
    $ag = Get-SqlAvailabilityGroup -ServerInstance "$CluNodeINST1" -ErrorAction SilentlyContinue
    if ($ag -and $ag.HealthState -eq 'Healthy') {
        Write-Output "AG healthy on $CluNode"
        break
    }
    Start-Sleep -Seconds 10
} while ($stopWatch.Elapsed.TotalSeconds -lt $timeout)

# Register scripts with CAU
Add-CauClusterRole -ClusterName 'CLUSTER01' `
    -BeforeUpdateScript 'C:ScriptsCAU-PreUpdate.ps1' `
    -AfterNodeUpdateScript 'C:ScriptsCAU-PostUpdate.ps1' `
    -Force

Using a WSUS Plugin for CAU

By default, CAU uses Windows Update directly. Point it at your WSUS server to apply only the updates you have approved:


# Use WSUS plugin instead of Windows Update
Invoke-CauRun -ClusterName 'CLUSTER01' `
    -CauPluginName 'Microsoft.WindowsUpdatePlugin' `
    -CauPluginArguments @{
        'UseWindowsUpdateServer' = 'true'
    } `
    -Force

# Verify cluster nodes are pointing to WSUS
Get-ClusterNode | ForEach-Object {
    $wu = Invoke-Command -ComputerName $_.Name -ScriptBlock {
        Get-ItemProperty 'HKLM:SOFTWAREPoliciesMicrosoftWindowsWindowsUpdate' -Name WUServer
    }
    "$($_.Name): $($wu.WUServer)"
}

Reviewing CAU Update History


# Get the CAU update log for the last run
Get-CauReport -ClusterName 'CLUSTER01' -Last |
    Select-Object RunStartTime, RunEndTime, RunStatus, NumberOfSuccessfullyUpdatedNodes

# Get detailed report with per-node results
Get-CauReport -ClusterName 'CLUSTER01' -Last | 
    Select-Object -ExpandProperty NodeResults |
    Select-Object NodeName, UpdatesInstalled, UpdatesFailed, RebootRequired

# Export all historical CAU reports to HTML
Get-CauReport -ClusterName 'CLUSTER01' -StartDate (Get-Date).AddMonths(-3) |
    ForEach-Object { $_ | Export-CauReport -Path "C:ReportsCAU_$($_.RunStartTime.ToString('yyyyMMdd_HHmm')).html" }

# Check CAU event log
Get-WinEvent -LogName 'Microsoft-Windows-ClusterAwareUpdating/Admin' -MaxEvents 100 |
    Select-Object TimeCreated, LevelDisplayName, Message | Format-Table -Wrap

CAU Compatibility Testing


# Run the full CAU compatibility analysis on the cluster
Test-CauSetup -ClusterName 'CLUSTER01' -Verbose

# Individual checks included in Test-CauSetup:
# - All nodes online and accessible
# - WMI accessible on all nodes
# - Remote PowerShell enabled on all nodes
# - Firewall rules allow CAU communication
# - No pending reboots on any node
# - No conflicting CAU runs in progress

# Check for pending reboots before starting CAU
Get-ClusterNode | ForEach-Object {
    $pending = Invoke-Command -ComputerName $_.Name -ScriptBlock {
        $reboot = $false
        if (Test-Path 'HKLM:SOFTWAREMicrosoftWindowsCurrentVersionComponent Based ServicingRebootPending') { $reboot = $true }
        if (Test-Path 'HKLM:SOFTWAREMicrosoftWindowsCurrentVersionWindowsUpdateAuto UpdateRebootRequired') { $reboot = $true }
        [PSCustomObject]@{ Computer = $env:COMPUTERNAME; PendingReboot = $reboot }
    }
    $pending
}

Conclusion

Cluster-Aware Updating on Windows Server 2019 automates the most tedious and risky part of cluster maintenance—applying patches one node at a time while keeping applications online. Self-updating mode with a scheduled trigger on Patch Tuesday, combined with WSUS integration for approved-update control, pre/post-update scripts for application-aware quiescing, and comprehensive reporting, creates a fully automated patching pipeline for Windows Server failover clusters that requires no manual intervention for routine maintenance cycles.