Posted in : Azure, NetScaler By Simon Gottschlag Translate with Google ⟶

3 years ago

Update:
I’ve found out that there’s a much easier way of doing the below in Azure – take a look at the updated blog post:
Updated: NetScaler Active/Passive HA in Azure with multiple NICs/IPs (DSR/Floating IP)
——
There are a lot of information out there about setting up NetScaler HA in Azure. One way is using a single NIC and a single IP for all traffic – which allows for active/passive but causes other limitations. Another way is to use multiple NICs/IPs and use active/active. Both cases uses Azure LB to provide high availability.

I want to use multiple NICs/IPs but in active/passive, and have found a hybrid of the two that seems to be working. I haven’t tested everything together with this configuration, but basic failover between the NetScalers seems to be working fine.
What are the requirements before following my instructions below?

  • Create a vnet and three subnets, as well as a resource group and availability set
  • Configure INC on the NetScalers / each get a unique SNIP on each subnet
  • Make sure to place the VIPs that are going to be used in a /31 (10.99.0.202 and 10.99.0.203 for example) – use the CIDR calculator if you are unsure
  • Place the Azure LBs on the same subnets as they are load balancing (the same subnets we have the VIPs)  and place the NetScalers on different subnets than resources using the Azure LBs. This may not be a requirement, but is how I’ve done it.

In my case, i have the following subnets:

  • management = 10.99.0.0/24
  • inside = 10.99.1.0/24
  • outside = 10.99.2.0/24
  • VIPs on inside:
    • NetScaler #1: 10.99.1.202
    • NetScaler #2: 10.99.1.203
    • Azure LB Frontend IP: 10.99.1.204
  • VIPs on outside:
    • NetScaler #1: 10.99.2.202
    • NetScaler #2: 10.99.2.203
    • Azure LB Frontend IP: 10.99.2.204

First of, create NetScaler #1:

$AVSetName = "avset-weu-prod-netscaler"
$RGName = "rg-weu-prod"
$VMName = "vm-weu-ns1"
$VMSize = "Standard_DS3_v2"
$OSDiskName = "osdisk-$($VMName)"
$VHDName = "$($OSDiskName).vhd"
$Location = "West Europe"
$VNetName = "vnet-weu-prod"
$NICName1 = "nic-$($VMName)-mgmt"
$NIC1PrivateIP1 = "10.99.0.200"
$NIC1PrivateIP2 = "10.99.0.202"
$Subnet1Name = "management"
$NICName2 = "nic-$($VMName)-inside"
$NIC2PrivateIP1 = "10.99.1.200"
$NIC2PrivateIP2 = "10.99.1.202"
$Subnet2Name = "inside"
$NICName3 = "nic-$($VMName)-outside"
$NIC3PrivateIP1 = "10.99.2.200"
$NIC3PrivateIP2 = "10.99.2.202"
$Subnet3Name = "outside"
$PublisherName = "citrix"
$OfferName = "netscalervpx-120"
$SKUName = "netscalerbyol"
$VMCredentials = Get-Credential
$AvailabilitySet = Get-AzureRmAvailabilitySet -ResourceGroupName $RGName -Name $AVSetName
$VM = New-AzureRmVMConfig -VMName $VMName -VMSize $VMSize -AvailabilitySetID $AvailabilitySet.Id
Set-AzureRmVMPlan -VM $VM -Publisher $PublisherName -Product $OfferName -Name $SKUName
Get-AzureRmMarketplaceTerms -Publisher $PublisherName -Product $OfferName -Name $SKUName | Set-AzureRmMarketplaceTerms -Accept
Set-AzureRmVMOSDisk -VM $VM -Name $OSDiskName -VhdUri $VHDName -Caching ReadWrite -CreateOption FromImage
Set-AzureRmVMOperatingSystem -VM $VM -Linux -ComputerName $VMName -Credential $VMCredentials
Set-AzureRmVMSourceImage -VM $VM -PublisherName $PublisherName -Offer $OfferName -Skus $SKUName -Version "latest"
Set-AzureRmVMOSDisk -VM $VM -Name $OSDiskName -CreateOption FromImage
$VNet = Get-AzureRMVirtualNetwork -Name $VNetName -ResourceGroupName $RGName
$Subnet1 = Get-AzureRmVirtualNetworkSubnetConfig -Name $Subnet1Name -VirtualNetwork $VNet
$NIC1IPConfig1 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName1)-IPConfig1" -Subnet $Subnet1 -PrivateIpAddress $NIC1PrivateIP1 -Primary
$NIC1IPConfig2 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName1)-IPConfig2" -Subnet $Subnet1 -PrivateIpAddress $NIC1PrivateIP2
$NIC1 = New-AzureRmNetworkInterface -Name $NICName1 -ResourceGroupName $RGName -Location $Location -IpConfiguration $NIC1IPConfig1,$NIC1IPConfig2
$Subnet2 = Get-AzureRmVirtualNetworkSubnetConfig -Name $Subnet2Name -VirtualNetwork $VNet
$NIC2IPConfig1 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName2)-IPConfig1" -Subnet $Subnet2 -PrivateIpAddress $NIC2PrivateIP1 -Primary
$NIC2IPConfig2 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName2)-IPConfig2" -Subnet $Subnet2 -PrivateIpAddress $NIC2PrivateIP2
$NIC2 = New-AzureRmNetworkInterface -Name $NICName2 -ResourceGroupName $RGName -Location $Location -IpConfiguration $NIC2IPConfig1,$NIC2IPConfig2
$Subnet3 = Get-AzureRmVirtualNetworkSubnetConfig -Name $Subnet3Name -VirtualNetwork $VNet
$NIC3IPConfig1 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName3)-IPConfig1" -Subnet $Subnet3 -PrivateIpAddress $NIC3PrivateIP1 -Primary
$NIC3IPConfig2 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName3)-IPConfig2" -Subnet $Subnet3 -PrivateIpAddress $NIC3PrivateIP2
$NIC3 = New-AzureRmNetworkInterface -Name $NICName3 -ResourceGroupName $RGName -Location $Location -IpConfiguration $NIC3IPConfig1,$NIC3IPConfig2
Add-AzureRmVMNetworkInterface -VM $VM -Id $NIC1.Id -Primary
Add-AzureRmVMNetworkInterface -VM $VM -Id $NIC2.Id
Add-AzureRmVMNetworkInterface -VM $VM -Id $NIC3.Id
New-AzureRmVM -VM $VM -ResourceGroupName $RGName -Location $Location

Create NetScaler #2:

$AVSetName = "avset-weu-prod-netscaler"
$RGName = "rg-weu-prod"
$VMName = "vm-weu-ns2"
$VMSize = "Standard_DS3_v2"
$OSDiskName = "osdisk-$($VMName)"
$VHDName = "$($OSDiskName).vhd"
$Location = "West Europe"
$VNetName = "vnet-weu-prod"
$NICName1 = "nic-$($VMName)-mgmt"
$NIC1PrivateIP1 = "10.99.0.201"
$NIC1PrivateIP2 = "10.99.0.203"
$Subnet1Name = "management"
$NICName2 = "nic-$($VMName)-inside"
$NIC2PrivateIP1 = "10.99.1.201"
$NIC2PrivateIP2 = "10.99.1.203"
$Subnet2Name = "inside"
$NICName3 = "nic-$($VMName)-outside"
$NIC3PrivateIP1 = "10.99.2.201"
$NIC3PrivateIP2 = "10.99.2.203"
$Subnet3Name = "outside"
$PublisherName = "citrix"
$OfferName = "netscalervpx-120"
$SKUName = "netscalerbyol"
$VMCredentials = Get-Credential
$AvailabilitySet = Get-AzureRmAvailabilitySet -ResourceGroupName $RGName -Name $AVSetName
$VM = New-AzureRmVMConfig -VMName $VMName -VMSize $VMSize -AvailabilitySetID $AvailabilitySet.Id
Set-AzureRmVMPlan -VM $VM -Publisher $PublisherName -Product $OfferName -Name $SKUName
Get-AzureRmMarketplaceTerms -Publisher $PublisherName -Product $OfferName -Name $SKUName | Set-AzureRmMarketplaceTerms -Accept
Set-AzureRmVMOSDisk -VM $VM -Name $OSDiskName -VhdUri $VHDName -Caching ReadWrite -CreateOption FromImage
Set-AzureRmVMOperatingSystem -VM $VM -Linux -ComputerName $VMName -Credential $VMCredentials
Set-AzureRmVMSourceImage -VM $VM -PublisherName $PublisherName -Offer $OfferName -Skus $SKUName -Version "latest"
Set-AzureRmVMOSDisk -VM $VM -Name $OSDiskName -CreateOption FromImage
$VNet = Get-AzureRMVirtualNetwork -Name $VNetName -ResourceGroupName $RGName
$Subnet1 = Get-AzureRmVirtualNetworkSubnetConfig -Name $Subnet1Name -VirtualNetwork $VNet
$NIC1IPConfig1 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName1)-IPConfig1" -Subnet $Subnet1 -PrivateIpAddress $NIC1PrivateIP1 -Primary
$NIC1IPConfig2 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName1)-IPConfig2" -Subnet $Subnet1 -PrivateIpAddress $NIC1PrivateIP2
$NIC1 = New-AzureRmNetworkInterface -Name $NICName1 -ResourceGroupName $RGName -Location $Location -IpConfiguration $NIC1IPConfig1,$NIC1IPConfig2
$Subnet2 = Get-AzureRmVirtualNetworkSubnetConfig -Name $Subnet2Name -VirtualNetwork $VNet
$NIC2IPConfig1 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName2)-IPConfig1" -Subnet $Subnet2 -PrivateIpAddress $NIC2PrivateIP1 -Primary
$NIC2IPConfig2 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName2)-IPConfig2" -Subnet $Subnet2 -PrivateIpAddress $NIC2PrivateIP2
$NIC2 = New-AzureRmNetworkInterface -Name $NICName2 -ResourceGroupName $RGName -Location $Location -IpConfiguration $NIC2IPConfig1,$NIC2IPConfig2
$Subnet3 = Get-AzureRmVirtualNetworkSubnetConfig -Name $Subnet3Name -VirtualNetwork $VNet
$NIC3IPConfig1 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName3)-IPConfig1" -Subnet $Subnet3 -PrivateIpAddress $NIC3PrivateIP1 -Primary
$NIC3IPConfig2 = New-AzureRmNetworkInterfaceIpConfig -Name "$($NICName3)-IPConfig2" -Subnet $Subnet3 -PrivateIpAddress $NIC3PrivateIP2
$NIC3 = New-AzureRmNetworkInterface -Name $NICName3 -ResourceGroupName $RGName -Location $Location -IpConfiguration $NIC3IPConfig1,$NIC3IPConfig2
Add-AzureRmVMNetworkInterface -VM $VM -Id $NIC1.Id -Primary
Add-AzureRmVMNetworkInterface -VM $VM -Id $NIC2.Id
Add-AzureRmVMNetworkInterface -VM $VM -Id $NIC3.Id
New-AzureRmVM -VM $VM -ResourceGroupName $RGName -Location $Location

Configure Azure LB:

$RGName = "rg-weu-prod"
$VNetName = "vnet-weu-prod"
$Location = "West Europe"
$ALBName = "alb-netscaler"
$ALBHealthProbeName = "healthprobe-alb-netscaler"
$Subnet1Name = "inside"
$Subnet1FEIP = "10.99.1.204"
$Subnet1FEName = "fe-alb-netscaler-inside"
$Subnet1BEPoolName = "be-alb-netscaler-inside"
$Subnet1LBRule1Name = "lb-alb-netscaler-inside-http"
$Subnet1LBRule2Name = "lb-alb-netscaler-inside-ssl"
$Subnet2Name = "outside"
$Subnet2FEIP = "10.99.2.204"
$Subnet2FEName = "fe-alb-netscaler-outside"
$Subnet2BEPoolName = "be-alb-netscaler-outside"
$Subnet2LBRule1Name = "lb-alb-netscaler-outside-http"
$Subnet2LBRule2Name = "lb-alb-netscaler-outside-ssl"
$NS1NICInsideName = "nic-vm-weu-ns1-inside"
$NS1NICInsideVIPConfigName = "nic-vm-weu-ns1-inside-IPConfig2"
$NS1NICOutsideName = "nic-vm-weu-ns1-outside"
$NS1NICOutsideVIPConfigName = "nic-vm-weu-ns1-outside-IPConfig2"
$NS2NICInsideName = "nic-vm-weu-ns2-inside"
$NS2NICInsideVIPConfigName = "nic-vm-weu-ns2-inside-IPConfig2"
$NS2NICOutsideName = "nic-vm-weu-ns2-outside"
$NS2NICOutsideVIPConfigName = "nic-vm-weu-ns2-outside-IPConfig2"
$VNet = Get-AzureRMVirtualNetwork -Name $VNetName -ResourceGroupName $RGName
$Subnet1 = Get-AzureRmVirtualNetworkSubnetConfig -Name $Subnet1Name -VirtualNetwork $VNet
$Subnet2 = Get-AzureRmVirtualNetworkSubnetConfig -Name $Subnet2Name -VirtualNetwork $VNet
$FEIPSubnet1 = New-AzureRmLoadBalancerFrontendIpConfig -Name $Subnet1FEName -PrivateIpAddress $Subnet1FEIP -SubnetId $Subnet1.ID
$FEIPSubnet2 = New-AzureRmLoadBalancerFrontendIpConfig -Name $Subnet2FEName -PrivateIpAddress $Subnet2FEIP -SubnetId $Subnet2.ID
$BEPoolSubnet1 = New-AzureRmLoadBalancerBackendAddressPoolConfig -Name $Subnet1BEPoolName
$BEPoolSubnet2 = New-AzureRmLoadBalancerBackendAddressPoolConfig -Name $Subnet2BEPoolName
$ALBHealthProbe = New-AzureRmLoadBalancerProbeConfig -Name $ALBHealthProbeName -Protocol Tcp -Port 9000 -IntervalInSeconds 5 -ProbeCount 2
$LBRule1Subnet1 = New-AzureRmLoadBalancerRuleConfig -Name $Subnet1LBRule1Name -FrontendIpConfiguration $FEIPSubnet1 -BackendAddressPool $BEPoolSubnet1 -Probe $ALBHealthProbe -Protocol Tcp -FrontendPort 80 -BackendPort 80
$LBRule2Subnet1 = New-AzureRmLoadBalancerRuleConfig -Name $Subnet1LBRule2Name -FrontendIpConfiguration $FEIPSubnet1 -BackendAddressPool $BEPoolSubnet1 -Probe $ALBHealthProbe -Protocol Tcp -FrontendPort 443 -BackendPort 443
$LBRule1Subnet2 = New-AzureRmLoadBalancerRuleConfig -Name $Subnet2LBRule1Name -FrontendIpConfiguration $FEIPSubnet2 -BackendAddressPool $BEPoolSubnet2 -Probe $ALBHealthProbe -Protocol Tcp -FrontendPort 80 -BackendPort 80
$LBRule2Subnet2 = New-AzureRmLoadBalancerRuleConfig -Name $Subnet2LBRule2Name -FrontendIpConfiguration $FEIPSubnet2 -BackendAddressPool $BEPoolSubnet2 -Probe $ALBHealthProbe -Protocol Tcp -FrontendPort 443 -BackendPort 443
$ALB = New-AzureRmLoadBalancer -ResourceGroupName $RGName -Name $ALBName -Location $Location -FrontendIpConfiguration $FEIPSubnet1,$FEIPSubnet2 -LoadBalancingRule $LBRule1Subnet1,$LBRule2Subnet1,$LBRule1Subnet2,$LBRule2Subnet2 -BackendAddressPool $BEPoolSubnet1,$BEPoolSubnet2 -Probe $ALBHealthProbe
$NS1NICInside = Get-AzureRmNetworkInterface -ResourceGroupName $RGName -Name $NS1NICInsideName
$NS1NICOutside = Get-AzureRmNetworkInterface -ResourceGroupName $RGName -Name $NS1NICOutsideName
$NS2NICInside = Get-AzureRmNetworkInterface -ResourceGroupName $RGName -Name $NS2NICInsideName
$NS2NICOutside = Get-AzureRmNetworkInterface -ResourceGroupName $RGName -Name $NS2NICOutsideName
($NS1NICInside.IPConfigurations | ?{$_.Name -eq $NS1NICInsideVIPConfigName}).LoadBalancerBackendAddressPools.Add($BEPoolSubnet1)
($NS1NICOutside.IPConfigurations | ?{$_.Name -eq $NS1NICOutsideVIPConfigName}).LoadBalancerBackendAddressPools.Add($BEPoolSubnet2)
($NS2NICInside.IPConfigurations | ?{$_.Name -eq $NS2NICInsideVIPConfigName}).LoadBalancerBackendAddressPools.Add($BEPoolSubnet1)
($NS2NICOutside.IPConfigurations | ?{$_.Name -eq $NS2NICOutsideVIPConfigName}).LoadBalancerBackendAddressPools.Add($BEPoolSubnet2)
Set-AzureRmNetworkInterface -NetworkInterface $NS1NICInside
Set-AzureRmNetworkInterface -NetworkInterface $NS1NICOutside
Set-AzureRmNetworkInterface -NetworkInterface $NS2NICInside
Set-AzureRmNetworkInterface -NetworkInterface $NS2NICOutside

Please note: I’m only using internal LBs here, you need to modify the configuration to create a Public IP.
Now, configure IPs and HA (with INC) and disable MBF/configure PBR (not required).

# NetScaler #1
set ns config -IPAddress 10.99.0.200 -netmask 255.255.255.0
add ns ip 10.99.1.200 255.255.255.0 -vServer DISABLED
add ns ip 10.99.2.200 255.255.255.0 -vServer DISABLED
add ns ip 10.99.0.202 255.255.255.0 -vServer DISABLED
add HA node 1 10.99.0.201 -inc ENABLED
add ns pbr PBR-MANAGEMENT ALLOW -srcIP = 10.99.0.0-10.99.0.255 -destIP "!=" 10.99.0.0-10.99.0.255 -nextHop 10.99.0.1 -priority 10
add ns pbr PBR-INSIDE ALLOW -srcIP = 10.99.1.0-10.99.1.255 -destIP "!=" 10.99.1.0-10.99.1.255 -nextHop 10.99.1.1 -priority 20
add ns pbr PBR-OUTSIDE ALLOW -srcIP = 10.99.2.0-10.99.2.255 -destIP "!=" 10.99.2.0-10.99.2.255 -nextHop 10.99.2.1 -priority 30
# NetScaler #2
set ns config -IPAddress 10.99.0.201 -netmask 255.255.255.0
add ns ip 10.99.1.201 255.255.255.0 -vServer DISABLED
add ns ip 10.99.2.201 255.255.255.0 -vServer DISABLED
add ns ip 10.99.0.203 255.255.255.0 -vServer DISABLED
add HA node 1 10.99.0.200 -inc ENABLED
add ns pbr PBR-MANAGEMENT ALLOW -srcIP = 10.99.0.0-10.99.0.255 -destIP "!=" 10.99.0.0-10.99.0.255 -nextHop 10.99.0.1 -priority 10
add ns pbr PBR-INSIDE ALLOW -srcIP = 10.99.1.0-10.99.1.255 -destIP "!=" 10.99.1.0-10.99.1.255 -nextHop 10.99.1.1 -priority 20
add ns pbr PBR-OUTSIDE ALLOW -srcIP = 10.99.2.0-10.99.2.255 -destIP "!=" 10.99.2.0-10.99.2.255 -nextHop 10.99.2.1 -priority 30

Please note: I’m not configuring HA encryption or chaning the rpcNode password. Should always be done. Only showing what I think is the bare minimum to get it working.
Configure the most basic content switches for inside and outside:

# Creating responder action/policy to show something on the CS
add responder action REA-NETSCALER_IP respondwith "\"NetScaler IP: \" + SYS.NSIP + \" | VIP: \" + CLIENT.IP.DST"
add responder policy REP-NETSCALER_IP true REA-NETSCALER_IP
# Create CS for inside (HP = healthprobe, should match Azure LB configuration)
add cs vserver CS-INSIDE_HTTP HTTP -IPPattern 10.99.1.202 -IPMask 255.255.255.254 80 -cltTimeout 180
bind cs vserver CS-INSIDE_HTTP -policyName REP-NETSCALER_IP -priority 100 -gotoPriorityExpression END -type REQUEST
add cs vserver CS-INSIDE_HP_TCP_9000 TCP -IPPattern 10.99.1.202 -IPMask 255.255.255.254 9000 -cltTimeout 9000
# Create CS for outside (HP = healthprobe, should match Azure LB configuration)
add cs vserver CS-OUTSIDE_HTTP HTTP -IPPattern 10.99.2.202 -IPMask 255.255.255.254 80 -cltTimeout 180
bind cs vserver CS-OUTSIDE_HTTP -policyName REP-NETSCALER_IP -priority 100 -gotoPriorityExpression END -type REQUEST
add cs vserver CS-OUTSIDE_HP_TCP_9000 TCP -IPPattern 10.99.2.202 -IPMask 255.255.255.254 9000 -cltTimeout 9000

Now you should be able to failover between the NetScalers. From a VM on the same vnet, you should be presented with the following when NetScaler #1 is active:
http://10.99.1.202 = NetScaler IP: 10.99.0.200 | VIP: 10.99.1.202
http://10.99.1.203 = Not responding
http://10.99.1.204 = NetScaler IP: 10.99.0.200 | VIP: 10.99.1.202
And the following when NetScaler #2 is active:
http://10.99.1.202 = Not responding
http://10.99.1.203 = NetScaler IP: 10.99.0.201 | VIP: 10.99.1.203
http://10.99.1.204 = NetScaler IP: 10.99.0.201 | VIP: 10.99.1.203
 
Good luck with the configuration and feel free to drop a comment if you have any feedback or questions!

Tags : Azure, High Availability, Load Balancer, NetScaler

Personlig rådgivning

Vi erbjuder personlig rådgivning med författaren för 1400 SEK per timme. Anmäl ditt intresse i här så återkommer vi så snart vi kan.

Add comment

Your comment will be revised by the site if needed.