How to Configure Windows Server 2016 Software Load Balancer
Software Load Balancer (SLB) is a core component of the Software Defined Networking (SDN) stack in Windows Server 2016 Datacenter edition. It distributes network traffic across multiple virtual machines or services using the same load balancing algorithms and capabilities as hardware load balancers, but implemented entirely in software on Hyper-V hosts. SLB supports both inbound (North-South) traffic from external clients and outbound NAT, as well as East-West load balancing between virtual machines within the datacenter. This guide covers deploying and configuring the Software Load Balancer on Windows Server 2016.
Software Load Balancer Architecture
SLB in Windows Server 2016 consists of three main components. The SLB Multiplexer (MUX) is a virtual machine that receives inbound traffic destined for virtual IP (VIP) addresses and forwards it to the appropriate backend VM using Direct Server Return (DSR). The SLB Host Agent runs on each Hyper-V host and programs the local Open vSwitch Forwarding Extension with load balancing rules. Network Controller manages the configuration of all SLB components through REST APIs. SLB uses Border Gateway Protocol (BGP) to advertise VIP routes to the physical network fabric, allowing top-of-rack switches to direct inbound traffic to the SLB MUX VMs.
Prerequisites for Software Load Balancer
SLB requires a fully deployed Network Controller cluster as described in the Network Controller setup guide. All Hyper-V hosts must be configured with the SDN Host Agent. A BGP-capable network fabric is required for VIP route advertisement, or a BGP peer can be configured on the gateway. SLB MUX VMs should be deployed on separate Hyper-V hosts from each other for high availability. Each SLB MUX VM requires at least 2 vCPUs and 4 GB RAM. Windows Server 2016 Datacenter edition is required on all components.
Installing the SLB MUX Role
On each VM that will serve as an SLB MUX, install the SoftwareLoadBalancer role. Create and configure MUX VMs first, ensuring they are connected to the management network and have proper connectivity to Network Controller. Install the SLB role on each MUX VM:
Install-WindowsFeature -Name SoftwareLoadBalancer -IncludeManagementTools
Verify installation on each MUX VM:
Get-WindowsFeature -Name SoftwareLoadBalancer
Registering the SLB MUX with Network Controller
Register each MUX VM with Network Controller to make it part of the managed SLB infrastructure. Define the MUX configuration and submit it to Network Controller. On the Network Controller management host:
$mux = New-Object Microsoft.Windows.NetworkController.LoadBalancerMux
$mux.ResourceId = "MUX_01"
$mux.Properties = New-Object Microsoft.Windows.NetworkController.LoadBalancerMuxProperties
$mux.Properties.RouterConfiguration = New-Object Microsoft.Windows.NetworkController.RouterConfiguration
$mux.Properties.RouterConfiguration.LocalASN = 64512
$mux.Properties.RouterConfiguration.PeerRouterConfigurations = @()
New-NetworkControllerLoadBalancerMux -ConnectionUri "https://192.168.10.50" -ResourceId "MUX_01" -Properties $mux.Properties
Configuring a Virtual IP Load Balancer Rule
Create a load balancer with a public VIP that distributes HTTP traffic across backend VMs. First, define the frontend IP configuration using the public VIP address:
$lbProperties = New-Object Microsoft.Windows.NetworkController.LoadBalancerProperties
$frontendIP = New-Object Microsoft.Windows.NetworkController.LoadBalancerFrontendIpConfiguration
$frontendIP.ResourceId = "FE_WebVIP"
$frontendIP.Properties = New-Object Microsoft.Windows.NetworkController.LoadBalancerFrontendIpConfigurationProperties
$frontendIP.Properties.PrivateIPAddress = "10.10.10.100"
$frontendIP.Properties.PrivateIPAllocationMethod = "Static"
$lbProperties.FrontendIPConfigurations = @($frontendIP)
Define the backend address pool containing the VMs to receive load-balanced traffic:
$backendPool = New-Object Microsoft.Windows.NetworkController.LoadBalancerBackendAddressPool
$backendPool.ResourceId = "BackendPool_Web"
$backendPool.Properties = New-Object Microsoft.Windows.NetworkController.LoadBalancerBackendAddressPoolProperties
$lbProperties.BackendAddressPools = @($backendPool)
Define the load balancing rule for HTTP (TCP port 80):
$lbRule = New-Object Microsoft.Windows.NetworkController.LoadBalancingRule
$lbRule.ResourceId = "LBRule_HTTP"
$lbRule.Properties = New-Object Microsoft.Windows.NetworkController.LoadBalancingRuleProperties
$lbRule.Properties.Protocol = "TCP"
$lbRule.Properties.FrontendPort = 80
$lbRule.Properties.BackendPort = 80
$lbRule.Properties.EnableFloatingIP = $false
$lbRule.Properties.IdleTimeoutInMinutes = 4
$lbRule.Properties.LoadDistribution = "Default"
$lbProperties.LoadBalancingRules = @($lbRule)
Create the load balancer object in Network Controller:
New-NetworkControllerLoadBalancer -ConnectionUri "https://192.168.10.50" -ResourceId "WebFarm_LB" -Properties $lbProperties
Adding Backend VMs to the Load Balancer Pool
Associate backend VM network interfaces with the load balancer’s backend pool. For each backend VM, retrieve the network interface resource and add the backend pool reference:
$nic = Get-NetworkControllerNetworkInterface -ConnectionUri "https://192.168.10.50" -ResourceId "WebVM01_NIC"
$backendPoolRef = New-Object Microsoft.Windows.NetworkController.ResourceReference
$backendPoolRef.ResourceRef = "/loadBalancers/WebFarm_LB/backendAddressPools/BackendPool_Web"
$nic.Properties.IpConfigurations[0].Properties.LoadBalancerBackendAddressPools = @($backendPoolRef)
New-NetworkControllerNetworkInterface -ConnectionUri "https://192.168.10.50" -ResourceId "WebVM01_NIC" -Properties $nic.Properties
Configuring Outbound NAT
SLB can also provide outbound NAT for VMs that need to initiate connections to the internet using a shared public IP address. Create an outbound NAT rule:
$natRule = New-Object Microsoft.Windows.NetworkController.OutboundNatRule
$natRule.ResourceId = "Outbound_NAT"
$natRule.Properties = New-Object Microsoft.Windows.NetworkController.OutboundNatRuleProperties
$natRule.Properties.Protocol = "ALL"
$natRule.Properties.FrontendIPConfigurations = @($frontendIP)
$natRule.Properties.BackendAddressPools = @($backendPool)
$lbProperties.OutboundNatRules = @($natRule)
New-NetworkControllerLoadBalancer -ConnectionUri "https://192.168.10.50" -ResourceId "WebFarm_LB" -Properties $lbProperties
Monitoring Software Load Balancer
Monitor SLB health and statistics through Network Controller. Retrieve all load balancers and their configurations:
Get-NetworkControllerLoadBalancer -ConnectionUri "https://192.168.10.50" | Select-Object ResourceId
View MUX health status:
Get-NetworkControllerLoadBalancerMux -ConnectionUri "https://192.168.10.50" | Select-Object ResourceId, @{N="Status";E={$_.Properties.Status}}
Review SLB-related events in the Windows Event Viewer under Applications and Services Logs > Microsoft > Windows > SoftwareLoadBalancer on each MUX VM for connection errors or performance warnings.
Best Practices for Software Load Balancer
Deploy at least two MUX VMs on separate Hyper-V hosts for high availability. Configure BGP peering between MUX VMs and physical top-of-rack switches to ensure VIP routes are properly advertised and withdrawn during failover. Use health probes in your load balancer rules to automatically remove failed backend VMs from the pool. Separate management, provider, and tenant network traffic using dedicated network adapters and VLANs on Hyper-V hosts. Monitor MUX VM CPU and memory usage and scale out by adding additional MUX VMs as traffic volumes grow. Test failover scenarios by intentionally stopping a MUX VM and verifying that traffic continues to flow through the remaining MUX VM. Document all VIP addresses, backend pool memberships, and port mappings to simplify troubleshooting and change management.
The Windows Server 2016 Software Load Balancer provides enterprise-grade load balancing capabilities without the cost of dedicated hardware appliances, making it an essential component of any software-defined datacenter built on Hyper-V and the Windows Server 2016 SDN stack.