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.
🛠️ 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 this 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 \"<h1>Backend Instance: $(hostname)</h1>\" > /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?
- Use Load Balancer (L4) when you need high-performance, low-latency traffic for internal services (e.g., SQL, non-HTTP protocols).
- Use Application Gateway (L7) 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.

Top comments (0)