How to set up an Internal Load Balancer using a batch file and Azure CLI


Batch files are not just a bad memory from the 80s, they can still be very useful.
In this exercise we’ll see how to create an internal Load Balancer in Microsoft Azure using a parametrized batch file.  Let’s summarize what’s involved.

You’ll see:
– how to create a resource group
– how to set up a static public IP
– how to create a virtual network and related subnets
– how to create a Load Balancer and related address pools
– how to create Load Balancer NAT rule/s
– how to create a NIC (Network Interface Card)
– how to create a Storage Account
– how to create a Virtual Machine
… and, of course …
– how to connect all the above together.


If you intend to just read and not replicate all you need is 5-10 min of free time.
Otherwise, here’s the list of ingredients:
– Azure account
– PC running Windows
– Azure CLI (use the installation instructions at: )
– Text Editor
–  a bit of patience 🙂


My text editor of choice is Notepad++ (available at: ) or any other editor with similar IntelliSense/highlight capabilities. If you’re using Notepad++ and you’re creating the batch file from scratch, you need to specify the file type manually by right-clicking at the bottom left in the main window and selecting “Batch”.



Before we begin, a quick recap on batch files and command prompt functionality. Just the essentials, in keeping with the overall spirit of this exercise.

– To set a variable inside a batch file we use the following notation:

SET variableName=value


– A variable must be declared before being used.

– To use a variable with a command we enclose the variable name with %:



– Variables are scoped to the running Command Prompt session and won’t persist to other sessions.
– Avoid spaces in variable names and (possibly) in values.
– Comments must begin with the keyword rem:

rem this is a comment

– To avoid the batch operation being interrupted after a command you need to use the call keyword on each command:

call azure group create...


– You can pause the script on any line using the pause command; and the resume by pressing any key.


The following diagram shows a simplified schema of the scenario we’re about to create.



This scenario wouldn’t be 100% suitable for a real world use case, webpool and sqlpool have been chosen just as an example. The point of this exercise is to show how to create rules for establishing communication with address pools and create specific NAT rules using the CLI and a batch file.

FrontVM can be reached from the Internet (usual RDP connection) at the provided static IP/DNS.

The Load Balancer has an IP assigned inside the subnet of the Front VM.

FrontVM can reach a machine connected to the Web Address Pool using the Load Balancer’s front IP on port 80 (; the same goes for the Sql Address Pool on port 1433.

A specific VM can be reached at a specific port using a NAT rule. FrontVM can connect in this case to webVM01 and sqlVM01 RDPs using ports TCP 5432 and TCP 5433.

All the resources will be created within the same Resource Group, which should ease any future deployment scenario.

A more detailed schema  is shown in the following diagram:

Before having a look at the script there are a couple of further steps to take:

– Log in to Azure using the CLI (instructions available at: )

– retrieve the Subscription ID with the command

azure account list

(we’ll need this to set the corresponding variable in the script file).

In case you have multiple subscriptions you need to specify the one you want to use with the command

azure account set subscriptionID




The following script is offered “as is” and no responsibility will be assumed for any data loss, running costs or any direct/indirect damage it may cause. The script will create (and run) resources in your own subscription, which means that it will generate costs! You may want to keep the following command

call azure group delete %ResGroupName%

handy, which will enable you to delete all the resources within the created Resource Group and terminate any associated costs.

Some preliminary gotchas:

– be careful with naming and the find/replace command: the string you may want to replace could be part of another string, and, changing it, you may invalidate the script or bork the whole process.

– don’t use a rem command after a SET in the same line:

SET var=value rem comment

the variable will have “value rem comment” as a value.

Here’s the script:

rem // Select Subscription
SET subscription=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
rem // Create Resource Group
SET ResGroupName=grpLBTest
rem // Select Region
SET Region=westus
rem // Set Virtual Network parameters
SET vNetName=LBTestVNet
SET vNetAddrSpace=
SET FrontSubNet=FrontEnd
SET FrontSubNetAddrSpace=
SET BackSubNet=BackEnd
SET BackSubNetAddrSpace=
rem // Set Public IP
SET PublicIPName=testIP
SET PublicIPDNS=lbtest123
rem // Set Load Balancer
SET LBName=LoadBalInternal
rem // LB front IP address
SET LBFrontIPAddr=
SET LBWebAddrPool=webPool
SET LBSqlAddrPool=sqlPool
rem // rule for managing traffic on port 80
SET LBWebRule=webPoolRule
rem // rule for managing traffic on port 1433
SET LBSqlRule=sqlPoolRule
rem // rule for creating NAT to reach VM RDP on web pool
SET LBWebNatRule=rdpNatWeb
rem // rule for creating NAT to reach VM RDP on sql pool
SET LBSqlNatRule=rdpNatSql
SET WebRdpPort=5432
SET SqlRdpPort=5433
SET LBProbeName=LBProbe
rem // Set NICs
rem // Set Storage Account
SET StorageAccountName=lbteststorage123123
rem // Set Availability Set
SET AvailSetName=availset
rem // Set Web VM
SET WebVM01=webvm001
SET WebVM01OsType=Windows
SET WebVM01ImageUrn=MicrosoftWindowsServer:WindowsServer:2008-R2-SP1:2.0.20151214
SET WebVM01UserName=myusername
SET WebVM01Password=H3r3SThePass!
rem // Set Sql VM
SET SqlVM01=sqlvm001
SET SqlVM01OsType=Windows
SET SqlVM01ImageUrn=MicrosoftWindowsServer:WindowsServer:2008-R2-SP1:2.0.20151214
SET SqlVM01UserName=myusername
SET SqlVM01Password=H3r3SThePass!
rem // Set front VM
SET FrontVM=frontMachine
SET FrontVM01OsType=Windows
SET FrontVM01ImageUrn=MicrosoftWindowsServer:WindowsServer:2008-R2-SP1:2.0.20151214
SET FrontVM01UserName=myusername
SET FrontVM01Password=H3r3SThePass!
rem // Set ARM mode
call azure config mode arm
rem // Create Resource Group
call azure group create -n %ResGroupName% -l %Region%
rem // Create Virtual Network
call azure network vnet create -g %ResGroupName% -n %vNetName% -a %vNetAddrSpace% -l %Region%
rem // Create Subnets
call azure network vnet subnet create -g %ResGroupName% -e %vNetName% -n %FrontSubNet% -a %FrontSubNetAddrSpace%
call azure network vnet subnet create -g %ResGroupName% -e %vNetName% -n %BackSubNet% -a %BackSubNetAddrSpace%
rem // Create Load Balancer
call azure network lb create -n %LBName% -l %Region% -g %ResGroupName%
rem // Create Load Balancer FrontEnd IP
call azure network lb frontend-ip create -g %ResGroupName% -l %LBName% -n %LBFrontIPName% -a %LBFrontIPAddr% -e %FrontSubNet% -m %vNetName%
rem // Create Load Balancer Address Pools
call azure network lb address-pool create -g %ResGroupName% -l %LBName% -n %LBWebAddrPool%
call azure network lb address-pool create -g %ResGroupName% -l %LBName% -n %LBSqlAddrPool%
rem // Create Load Balancer rules
call azure network lb rule create -g %ResGroupName% -l %LBName% -n %LBWebRule% -p tcp -f 80 -b 80 -t %LBFrontIPName% -o %LBWebAddrPool%
call azure network lb rule create -g %ResGroupName% -l %LBName% -n %LBSqlRule% -p tcp -f 1433 -b 1433 -t %LBFrontIPName% -o %LBSqlAddrPool%
rem // Create Load Balancer NAT rules
call azure network lb inbound-nat-rule create -g %ResGroupName% -l %LBName% -n %LBWebNatRule% -p TCP -f %WebRdpPort% -b 3389
call azure network lb inbound-nat-rule create -g %ResGroupName% -l %LBName% -n %LBSqlNatRule% -p TCP -f %SqlRdpPort% -b 3389
rem // Create Load Balancer probe
call azure network lb probe create -g %ResGroupName% -l %LBName% -n %LBProbeName% -p tcp -i 300 -c 4
rem // Create Load Balancer WebNIC
call azure network nic create -g %ResGroupName% -n %WebNIC% --subnet-name %BackSubNet% --subnet-vnet-name %vNetName% -d "/subscriptions/%subscription%/resourceGroups/%ResGroupName%/providers/Microsoft.Network/loadBalancers/%LBName%/backendAddressPools/%LBWebAddrPool%" -e "/subscriptions/%subscription%/resourceGroups/%ResGroupName%/providers/Microsoft.Network/loadBalancers/%LBName%/inboundNatRules/%LBWebNatRule%" %Region%
rem // Create Load Balancer SqlNIC
call azure network nic create -g %ResGroupName% -n %SqlNIC% --subnet-name %BackSubNet% --subnet-vnet-name %vNetName% -d "/subscriptions/%subscription%/resourceGroups/%ResGroupName%/providers/Microsoft.Network/loadBalancers/%LBName%/backendAddressPools/%LBSqlAddrPool%" -e "/subscriptions/%subscription%/resourceGroups/%ResGroupName%/providers/Microsoft.Network/loadBalancers/%LBName%/inboundNatRules/%LBSqlNatRule%" %Region%
rem // Create Public IP
call azure network public-ip create --resource-group %ResGroupName% --name %PublicIPName% --location %Region% --allocation-method Static --domain-name-label %PublicIPDNS%
rem // Create front NIC
call azure network nic create --name %FrontNIC% --resource-group %ResGroupName% --location %Region% --private-ip-address %FrontNICIP% --subnet-id "/subscriptions/%subscription%/resourceGroups/%ResGroupName%/providers/Microsoft.Network/virtualNetworks/%vNetName%/subnets/%FrontSubNet%" --public-ip-name %PublicIPName%
rem // Create Storage Account
call azure storage account create %StorageAccountName% -g %ResGroupName% --sku-name LRS --kind Storage --location %Region%
rem // Create WebVM01
call azure vm create --resource-group %ResGroupName% --name %WebVM01% --location %Region% --vnet-name %vNetName% --vnet-subnet-name %BackSubNet% --nic-name %WebNIC% --availset-name %AvailSetName% --storage-account-name %StorageAccountName% --os-type %WebVM01OsType% --image-urn %WebVM01ImageUrn% -u %WebVM01UserName% -p %WebVM01Password%
rem // Create SqlVM01
call azure vm create --resource-group %ResGroupName% --name %SqlVM01% --location %Region% --vnet-name %vNetName% --vnet-subnet-name %BackSubNet% --nic-name %SqlNIC% --availset-name %AvailSetName% --storage-account-name %StorageAccountName% --os-type %SqlVM01OsType% --image-urn %SqlVM01ImageUrn% -u %SqlVM01UserName% -p %SqlVM01Password%
rem // Create FrontVM
call azure vm create --resource-group %ResGroupName% --name %FrontVM% --location %Region% --vnet-name %vNetName% --vnet-subnet-name %FrontSubNet% --nic-name %FrontNIC% --storage-account-name %StorageAccountName% --os-type %FrontVM01OsType% --image-urn %FrontVM01ImageUrn% -u %FrontVM01UserName% -p %FrontVM01Password%
rem call azure group delete %ResGroupName% --quiet
rem pause


The script is self-explanatory so it’s not necessary to analyze each and every line at this point.

The first part contains variable declarations and it can be customized at will.

The last command (commented out by default) deletes the Resource Group and every resource within it (see the above note regarding when to use it).

The only necessary change, is to replace the fake GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx in line 2 with your own SubscriptionID.

Some further suggestions:

– you may want to save the script in a file, name the file as whatever.bat and run it from a Command Prompt session AFTER having completed the login procedure from the same session.

– the Command Prompt session usually has C:\users\yourUserName as a starting directory, you may want to save the batch file in the same directory.

– you can interrupt the script at any time by pressing Ctrl+X.

– if you want to pass all variable values as command line parameters, please consider the following:

parameters in the Command Line are identified by their order and they can thus be used inside the batch file with %1, %2, …, %n

For example, if you want to pass the Resource Group name and the region as parameters, you can set the following variables:

SET ResGroupName=%1 SET Region=%2

and then run the batch as follows:

createLoadBal.bat LbTestResGroup westus



If the script runs with no errors and every resource has been created, you can test the Load Balancer functionality as follows:

– Log in (RDP) to the front machine using the public IP address/DNS

– From the front machine (inside the RDP session), login to webvm01 using Load Balancer’s front IP, specifying the port 5432.

You can just run the command:

mstsc -v

– once inside the webvm01 RDP session, Install IIS (from the Server Management dialog: add roles => web server (IIS) => … => install => Close)

– once the installation is done, test IIS locally (run the command http://localhost [WIN+R] , the IIS welcome page should appear)

– close webvm01 RDP session

– You should be now inside the FrontVM RDP session

– run [WIN+R], the webvm01 IIS welcome page should appear.


I hope this post has helped you to get more familiar with the Azure CLI and the role batch files still have to play when working with Azure.

You can edit and adapt it as per your needs and/or disassemble it to take advantage of individual commands.

Feel free to add comments or questions below.

Leave a Reply