Azure - Hosting an IIS Website on Azure VMs with a Public Load Balancer Pt1

Objective

This post aims to show how you would create a Front and Back end environment – showing the steps needed to achieve this in azure 

Set Up

To create this type of environment in Azure the first step to take is making a Resource Group (RG). The resource group is the logical container that will hold all your resources for the solution you’re crafting. I made the RG so I could start creating and configuring my azure Virtual Networks (VNET). I need to create two VNETS, one for my front end resources and another for my backend. The front end VNET will adopt a public IP address from a load balancer that I later deploy whereas the backend VNET uses a private IP. This mean’s it cannot be contacted or reached over the public internet and only reached inside my Azure Network. 

Create and Configure Virtual Networks.

Using the Azure GUI I searched for “Virtual Networks” Where I created both my VNETS. I did this first as Microsoft do not charge you for having a VNET deployed instead you’re charged by traffic. Since no other resources at this time are deployed you can have them deployed for as long as possible without spending a penny. 

The front end VNET is created alongside a subnet, the subnet is where my resources will be deployed to.

I created the Backend VNET/Subnet, you can see that the IP ranges are different which is important, it’s best to never let IP ranges clash with each other especially when working in large scale environments. 

The next step when both VNETs was created was to peer them together so they had bi directional relationships.

 

Note that the Peering state shows as “Connected” This shows you that the peer has worked. 

Create and Prepare Virtual Machines

Now my VNETS are set up for the Front/Back end both with subnets and peering enabled it was time to deploy my virtual machines (VM). The front end VMs for the project will host a HTML page, this is to show what VM you get when accessing over HTTP. The backend VM will not have the same structure as the front, instead nothing is deployed to the backend. For this project I wanted to show how you’d jumpbox from either front end VM to the backend. This way it keeps the Backend VM more secure as you cannot access it outside of the Azure VNETS. 

I created the first front end VM1, I used a BS2 VM as I found the BS1 VMs wasn’t great for GUI especially in the windows servers. I used the Windows 2022 server OS. I connected the Front End Subnet to the VM and created a Network Security Group. (NSG) The NSG will be needed to filter different types of network traffic.

Now the VM is created I needed to create a Public IP resource that would be connected to the Network Interface Card (NIC) This is needed so I can remote onto the VM and install the IIS feature in the server manager. IIS will be the service used on the VM to display a webpage over the internet. I need a public IP as without it the VNET and VM will stay private to the azure network and outside devices cannot remote into it unless I use Bastion on the GUI of azure. 

So I created the following on the NIC card in the IPConfig

An Public IP is then assigned to the VM

Since I need to “Connect” to the server I need to change the Network Security Rules (NSG) By default on the VM creation you can select the ports you want to allow but I skipped this so I could do it myself on the NSG. I created an inbound rule on the NSG that allowed Port 3389 which is used for RDP. 

With this rule in place it will allow my to RDP from the Azure GUI into the VM, If I had added a “Source” and added my IP from my personal device it would of allowed me to RDP from my PC into the server, but for this test I didn’t do that. 

With the follow steps completed I could now connect into the VM where I could install the IIS service. Without the NSG rule in place allowing Port 3389 or without a public IP I’d be unable to connect to the resource. 

When I was in the server I added the IIS service using server manager which launches on boot. I also changed the default HTML page to my own. Note inside server manager you may need to wait until the server is done preparing. You can also add IIS by going to Manage and adding a new role. The IIS role will be in a list.

 You will find that when IIS is installed you can edit the files from the C Drive inside a folder called inetpub/wwwroot 

 

You can then change the default webpage that is deployed with IIS to whatever you want. In this case I’ve made a HTML file that will show a webpage telling the end client what VM they are using. In a production environment this could instead be a marketing website or a store front where customers can buy something. 

 

When all this was done and I had tested the webpage worked by searching http://localhost – I went back into the Azure GUI and turned off the VM, I no longer have a reason to keep it running and this way I’ll save up time costs.

After I was done setting up VM1 I detected the Public IP address from it so I could repeat the steps and create VM2, I did this manually inside the Azure GUI for practise but there are other ways to do this, I could have used an ARM/Bicep template to deploy instead of doing everything again.

For this test I did it manually via Azure GUI, on deployment I did not make another NSG – since both VMs are identical I decided to use the same NSG and just attach it to the NIC card. 

After deploying the Second VM I then repeated all the other steps so I had two identical VMs
– Adding the Public IP to the VM2
– Remoting into the VM as I did not need to create more NSG rules since I’m using a pre existing resource 
– Installed IIS from the server manager

– Changing the default HTML page to my own – changing the text to VM2 instead of VM1.

For the backend VM nothing really needed to be prepared. I made the VM like the front end except it had it’s own NSG as it would not share the public Front end VM rules. It also had a separate admin sign on name just for identification purposes. 

The only other thing I did was enable the RDP port so that if I wanted I could remote into VM1/VM2 with the public facing IP and then jumpbox into the backend VM. This type of example is common in production environments. This way the backend stays private and never needs a public IP which would expose the VM. 

Load Balancer Integration

At this point I have created two VMs that sit on the front end that use a public IP address to allow admins to remote in using RDP but also have a IIS service installed so you can browse the public IP and you’ll see a webpage. This webpage would be the custom made HTML I showed above. Your NSG would need to trust your IP address to be able to view the webpage outside of the azure environment. This is fine but both VMs are identical, both require a public IP which would clutter my Resource Group with two public IPs both different. 

 

Instead I decided to use a load balancer (LB), the load balancer would:

  • Apply a new Public IP which the LB would assign to each VM 
  • The public IP would stay the same for each resource. The flow of traffic would go to the same IP each time
  • The Load balancer can direct traffic to the VM with the least demand so it would keep the sites running smoothly. 
  • In a production environment the backend would feed the front end with the logic it would need to display an Application/Webpage etc. The HTML I made acts as a visual aid. 

I searched for the Load balancer and went with a Standard Load Balancer

I set up the LB and used a new public IP which would be used to distribute traffic between the front end VMs.

Since the LB will be managing public IP traffic I needed to make a Health Probe so the LB understood it would need to allow port 80 which if for HTTP.

I later also edited the rule so the path went to the HTML page instead of the root folder. The name of the path is the HTML file name, I called mine Index.

As an additional step I made a Health Probe to allow the LB to let me RDP into either front end server. I only did this for testing. Best practise would be to separate the two VMs using NAT. 

Using this approach would make you randomly remote into either VM behind the LB. Meaning the server you get is random. I only did this to make sure I could still jumpbox into VM3 – Backend Server/

Now the LB is set up the VMs for the front end are now sitting behind it. So traffic should be distributed between the two VMs using the public IP the LB will assign. The VMs should now have the LB assigned in the VM settings.

 

Summary

After the final step above you should now be able to search for the Load Balancers public IP and come across the web pages.

 

I was able to search the IP using my personal device. My computer would search for the public IP assigned by the LB. The LB then communicates this to the VM NSG. The VM NSG would need to allow traffic coming from Port 80 and then you should be able to search the webpages. 

 

At this point I deleted my public IP I used for testing as I no longer need it since I have the LB public IP.

You can see from the illustration that on one side you can see the LB is launched VM1, in another tab I went incognito and got VM2 instead as VM1 had more traffic in that moment. 

 

I also tested to see if my RDP rule worked and was able to RDP into the server and still able to jumpbox into the backend.

 

When everything was working I then decided to export the arm template and then delete all my resources. Downloading the template allows me to revisit this if I ever want to create it again and make further changes. I saved the template and the paramaters. Microsoft best practise is to delete any resources you no longer need to stop any costs being charged.