In this post I will show you how to deploy and configure the Azure Resource Manager (ARM and CSP) network load balancer. The post will cover load balancing Azure virtual machines and creating NAT rules.
As I explained in Understanding the Azure Resource Manager Load Balancer, Microsoft has made significant changes to how virtual machines are networked in a Resource Manager or ARM deployment. The concepts of cloud services and endpoints are dead. Instead, there are two options for making a virtual machine available on the Internet:
- Public IP (PIP) Address: This is also known as an instance-level address. You assign a public IP address resource, with an optional Microsoft-owned domain name, to the virtual NIC of an individual virtual machine. This is a simple approach, but it isn’t very scalable or manageable, and it will waste public IPv4 addresses and increase costs.
- Load Balancer: You create a single point of entry to your service that will have a single IP address. You can use the load balancer to create NAT rules, for example to enable remote desktop access to individual virtual machines with port remapping (TCP 50051 to TCP 3389 on VM01). You can also use the load balancer to create load balancing rules to spread traffic across a number of virtual machines.
The load balancer, which is a function of the network fabric in Azure and not Windows Network Load Balancing (NLB), can be used to provide external or internal load balancing, as was explained in my previous post.
I have deployed two new web servers as virtual machine in an Azure virtual network subnet, called web-vm01 and web-vm02. I want to deploy a load balancer in the Azure fabric that will load balancer HTTP traffic to both of these machines, and will allow me to create NAT rules that will allow remote desktop access to both virtual machines.
There are two things to note about the default virtual machine deployment:
- The wizard to create a new Windows Server 2012 R2 virtual machine in ARM will deploy an instance-level public IP address that is associated with the virtual NIC; I made sure that a public IP address was not created for the virtual machines.
- I have made sure that there is a single network security group (NSG), that is associated with the virtual network subnet; the default deployment creates one NSG that is associated with the NIC of the virtual machine so I removed this option during the machine deployment.
- Both of my virtual machines were created in a common availability set – you cannot add existing machines to a new availability set!
Note, I cannot connect to my virtual machines via remote desktop without a VPN connection with this design. I will resolve this issue (which might not be an issue for some) using NAT rules.
New Load Balancer
In the Azure Portal, click New and search for Load Balancer; the first result should be the Load Balancer published by Microsoft in Networking. Click this option and click Create.
Give the load balancer a name; my resource group is called web-rg so I have named the load balancer web-lb.
The scheme option allows you to choose between an internal-facing or an external-facing load balancer – this allows you to either create the load balancer with a virtual network configuration (private) or with a publicly accessible IP address. I chose the latter option for my web server deployment.
Under public IP address, I am creating a new IP address with a static IP address. This will allow me to reliably point a DNS A record at the load balancer.
Finally, I selected my subscription, my web server resource group, and ensured that the region matched my resource group deployment.
A new load balancer will be running after a few minutes. You can see the public IP address of the load balancer in the resource’s blade, and this view also summarizes the rules that you have deployed (none at this point).
New NAT Rule
I want to enable RDP to each virtual machine in my deployment, whether it is load balanced or not. Open the settings of the new load balancer and select Inbound NAT Rules > Add. Fill in the details of the new NAT rule. Remote Desktop will use TCP 3389 but I will have multiple machines. So to make this work, I will use port mapping:
- TCP 50001 will be redirected to TCP 3389 on web-vm01
- TCP 50002 will be redirected to TCP 3389 on web-vm02
So I will connect to TCP 50002 on the load balancer’s public IP address if I want to connect to web-vm02 via remote desktop.
Most of the configuration is identical to creating a NAT rule on your broadband router or office firewall. One thing to note is Floating IP; this is used in scenarios such as SQL AlwaysOn so that the Azure virtual machine can receive traffic using the original destination IP address.
Azure will update the network configuration and the job will be completed within a few minutes. Now you should be able to open up the blade of the virtual machine, click Connect, and be able to remote desktop into the virtual machine using the new NAT rule.
I created two NAT rules, one for each virtual machine.
Now I try to remote into my virtual machines. The Connect button is no longer disabled but the connection times out. What is wrong?
Network Security Group
Although my security group appears blank, if I enable visibility of Default Rules, I will see a rule called DenyAllInbound with a priority of 65500. This rule prevents traffic routed by my NAT rule from reaching the virtual machines.
Browse to the settings of the network security group and click Add. Create a rule to allow traffic to reach TCP 3389. You can further restrict this to only allow traffic from a particular source, but be careful not to allow mobile administration.
This NSG is associated with the virtual network’s subnet so it will apply to all virtual machines in the subnet. It is possible to further restrict this with CIDR block, Tag, or by creating per-machine NSGs (best practice is per subnet).
Now I can successfully log into both of my virtual machines and enable the IIS role.
Create a Load Balancing Rule
Now I want to create a rule to allow HTTP traffic (TCP 80) in to my web servers, and be load balanced across the entire availability set; this gives me fault tolerance and can be later combined with auto-scaling for dynamic load capacity.
There are two prerequisites:
- A probe
- A backend pool based on the availability set
Open the settings of the load balancer and select Backend Pools > Add. Enter the name of the new backend pool. Then click Add A Virtual Machine and select a machine to add. Add all of the virtual machines from your availability set and save the results.
Return to the settings of the load balancer, open Probes and click Add. Here you will create a probe to query the availability of the machines in your availability set. You can get pretty fancy with this capability; make sure that you test the availability of the service that you are load balancing, e.g., HTTP.
Now we are ready to create a load balancing rule. Return to the settings of the load balancer, enter Load Balancing Rules and click Add. Here you will:
- Give the rule a name
- Choose a protocol and a port
- Select the backend pool
- Select the probe
- Choose if you want session persistent (None, Client IP, or Client IP and Protocol)
- Configure a session timeout (4-30 minutes)
- Choose if you want a floating IP – only recommended for a SQL AlwaysOn Availability Group Listener.
After the rule is created I can try to browse the load balanced website, using the public IP address of the load balancer … and it fails! That’s because we didn’t create a rule in the network security group!
Return to the settings of the NSG, enter Inbound Security Rules and create a rule to allow traffic to TCP 80. Once again, you can get very specific by using CIDR blocks or Tags. However, best practice is to have one NSG per subnet, and to put different tiers of applications into different subnets.
After the rule saves, I can browse the site using the public IP address of the load balancer.