Scalable Enterprise Web Routing: Azure App Gateway + VMSS with Azure CLI

Published: (February 27, 2026 at 10:24 PM EST)
4 min read
Source: Dev.to

Source: Dev.to

Building a resilient web architecture requires more than just a single server

In this tutorial, we transition from simple load balancing to Layer 7 Application Routing. We will deploy a Virtual Machine Scale Set (VMSS) and front it with an Azure Application Gateway, all using the Azure CLI.

🏗️ The Architecture

Unlike a standard Load Balancer (Layer 4), an Application Gateway (Layer 7) can make routing decisions based on HTTP headers and URL paths. We combine this with a VMSS to ensure our backend automatically scales based on demand.

Architecture diagram

🛠️ Objectives

  • Deploy an Application Gateway for advanced web traffic management.
  • Master Azure CLI for infrastructure automation.
  • Utilize VMSS Extensions to “bootstrap” applications automatically.
  • Setup a Mock Service using Python for isolated network testing.

💻 The Full Automation Script

Copy and save this script as deploy_appgw.sh. If you are on Windows, you can run it in WSL or Azure Cloud Shell.

#!/bin/bash

# --- 1. Configuration ---
rg="my-automated-rg3"
location="eastus2"
vnet_name="shared-vnet"
vmss_name="Hub-VMSS"
appgw_name="Hub-AppGateway"

echo "--- Starting Phase 6: Application Gateway & VMSS Deployment ---"

# --- 2. Create the Dedicated App Gateway Subnet ---
# App Gateway v2 requires its own empty subnet (min /24 recommended)
echo "Adding Application Gateway Subnet..."
az network vnet subnet create \
  --resource-group $rg \
  --vnet-name $vnet_name \
  --name appgw-subnet \
  --address-prefixes 10.0.4.0/24

# --- 3. Deploy the Virtual Machine Scale Set (VMSS) ---
echo "Deploying VMSS (The Elastic Backend)..."
az vmss create \
  --resource-group $rg \
  --name $vmss_name \
  --image Canonical:0001-com-ubuntu-server-jammy:22_04-lts:latest \
  --vm-sku Standard_B2ts_v2 \
  --instance-count 2 \
  --vnet-name $vnet_name \
  --subnet workload-subnet \
  --upgrade-policy-mode automatic \
  --admin-username azureuser \
  --generate-ssh-keys

# --- 4. Automate App Deployment with VMSS Extensions ---
# This "bootstraps" a Python mock service on every instance as it scales
echo "Applying Custom Script Extension..."
az vmss extension set \
  --publisher Microsoft.Azure.Extensions \
  --version 2.0 \
  --name CustomScript \
  --resource-group $rg \
  --vmss-name $vmss_name \
  --settings '{"commandToExecute": "mkdir -p /tmp/www && echo \"
## Backend Instance: $(hostname)
\" > /tmp/www/index.html && cd /tmp/www && nohup python3 -m http.server 80 &"}'

# --- 5. Deploy the Application Gateway ---
echo "Creating Public IP for Gateway..."
az network public-ip create \
  --resource-group $rg \
  --name appgw-public-ip \
  --allocation-method Static \
  --sku Standard

echo "Deploying Application Gateway (Standard_v2)..."
az network application-gateway create \
  --name $appgw_name \
  --resource-group $rg \
  --location $location \
  --capacity 2 \
  --sku Standard_v2 \
  --public-ip-address appgw-public-ip \
  --vnet-name $vnet_name \
  --subnet appgw-subnet \
  --frontend-port 80 \
  --priority 100 \
  --http-settings-port 80 \
  --http-settings-protocol Http

# --- 6. Connect VMSS to the Gateway Backend Pool ---
echo "Linking VMSS to Application Gateway..."
backend_pool_id=$(az network application-gateway address-pool show \
  --gateway-name $appgw_name \
  --resource-group $rg \
  --name appGatewayBackendPool \
  --query id -o tsv)

az vmss update \
  --resource-group $rg \
  --name $vmss_name \
  --set virtualMachineProfile.networkProfile.networkInterfaceConfigurations[0].ipConfigurations[0].applicationGatewayBackendAddressPools="[{'id': '$backend_pool_id'}]"

# Force update existing instances
az vmss update-instances --instance-ids "*" --name $vmss_name --resource-group $rg

echo "--- DEPLOYMENT COMPLETE ---"

🔍 Post‑Deployment Inspection (Azure CLI)

The CLI is the most powerful tool for inspecting live resources. Use these commands to verify your setup.

Check Backend Health

Confirm the Application Gateway can successfully “see” and “probe” the VMSS instances:

az network application-gateway show-backend-health \
  --name Hub-AppGateway \
  --resource-group my-automated-rg3

Scale Up!

Test the elasticity of your design by increasing the instance count:

az vmss scale \
  --resource-group my-automated-rg3 \
  --name Hub-VMSS \
  --new-capacity 4

❓ Troubleshooting Tips

  1. Subnet Restrictions
    The Application Gateway v2 must be in its own subnet. You cannot place VMs or other resources in appgw-subnet. If your deployment fails with a “Subnet Busy” error, check for existing NICs.

  2. Extension Issues
    If the web service isn’t responding, check the status of the VMSS extension:

    az vmss extension show \
      --resource-group my-automated-rg3 \
      --vmss-name Hub-VMSS \
      --name CustomScript
  3. App Gateway vs. Load Balancer: Which one?

    • Load Balancer (L4) – Use for high‑performance, low‑latency traffic for internal services (e.g., SQL, non‑HTTP protocols).
    • Application Gateway (L7) – Use when you need SSL termination, URL‑path routing, or Web Application Firewall (WAF) protection.

🏁 Conclusion

By combining Application Gateway with VMSS, we’ve built a production‑ready entry point for our Azure network. The use of CLI automation and extensions ensures that our environment is repeatable and easily scalable.

0 views
Back to Blog

Related posts

Read more »