Multiple Front Ends for the Same Scaleset
Published Nov 10 2022 10:08 AM 1,636 Views

I recently had a customer that was looking to consolidate two public services, with two public identities, on a single VM Scale Set while keeping distinct front-end IPs, allowing for cost efficiency on Azure resources while still giving front-end flexibility.


This post gets into some of the details of the implementation.

High-Level Designs

The starting design was a pretty standard “isolated service” type design:



The goal was to consolidate to a single environment with two identities, with the two services on the back end on unique ports:



For the sake of simplicity, I’m going to use a new, simple environment, but the concepts would map to more complicated environments of course as well.  I created a simple Ubuntu VM from the Marketplace, then customized that VM by adding Node.js and creating a couple of back-end services.  The back-end services here are a pair of very simple Node.js applications listening on ports 3000 and 4000:



const http = require("http");
var portNumber = 3000;

//create the server
const server = http.createServer(function(req,res) {
    res.end(`The server is at ${req.socket.localAddress}:${port}\nThe client is at: ${req.socket.remoteAddress}\n`);

// listen on port
const port = process.argv[2] || portNumber;
console.log(`Launching at ${port}... `);

server.listen(port, function() {
    console.log(`The server is listening in port ${port}.\n`);



This is launched using a very simple launcher script:



localadmin@customer100:~$ cat
cd /home/localadmin
exec /usr/bin/node app.js 3000 2>&1 >> /var/log/server_node3000.log &
exec /usr/bin/node app.js 4000 2>&1 >> /var/log/server_node4000.log



which in turn is launched through a simple root user crontab entry:

@reboot /bin/sh /home/localadmin/

(Yes, this is a bit inelegant, but again, the goal is to show the load balancer piece!)  The scale set was created as a private VMSS, meaning it did not have any public IP addresses associated with it.  This was important, because the goal is to perform port translation from port 80 on the front end to different ports on the back end, so there’s no reason to publish the scale set directly when the load balancer can do that.


So, at this point, it’s time to publish the load balancer.  Let’s go over the details of the load balancer.


First up is the front-end IP configuration.  Because the goal is two public service identities, one for each of the services, there are two front-end IPs:


Notice that each of the front ends is showing with a single rule.  That’s going to be looked at shortly, but rules require the other portions of the rule before the rule can be defined.


The next step is the backend pools.  Because there is a single VMSS, there is just one backend pool, pointing at the shared NIC for the VMSS:


Then, there are the health probes.  Given that both services are HTTP services, a very basic HTTP health probe on the root is sufficient for each of the two ports:


This is now enough to allow for the load balancing rules.  Essentially, there are two rules, one for the public IP that represents the port 3000 service, using the port 3000 health check, and one for the public IP that represents the port 4000 service, using the port 4000 health check:


And, that’s it!  We now have two public IP addresses, one for each of the back-end services on the shared VMSS.  The front-end IP list gives the IP addresses to test, one for port 3000:


And one for port 4000:



So, what has been accomplished here?  Effectively, two load balancers and two scale sets were consolidated into one, using port translation on each of the front ends to map to different service ports on the back end.


Version history
Last update:
‎Nov 10 2022 10:08 AM
Updated by: