Chapter 5: Networking
How traffic actually moves between Azure resources, the public internet, and your own data centre. Networking is where most outage stories start, so it pays to get the model right early.
Virtual Network (VNet)
A Virtual Network is your private, isolated network in Azure. All resources (VMs, databases, etc.) placed in a VNet can communicate with each other privately.
VNet: 10.0.0.0/16
├── Subnet: web-snet 10.0.1.0/24 - Public-facing VMs, App Service
├── Subnet: app-snet 10.0.2.0/24 - Backend application tier
├── Subnet: db-snet 10.0.3.0/24 - Databases
└── Subnet: AzureBastionSubnet 10.0.4.0/26 - Bastion host (must use this name)
Creating a VNet
# Create VNet with an address space
az network vnet create \
--resource-group myapp-rg \
--name myapp-vnet \
--address-prefix 10.0.0.0/16 \
--location eastus
# Add subnets
az network vnet subnet create \
--resource-group myapp-rg \
--vnet-name myapp-vnet \
--name web-snet \
--address-prefix 10.0.1.0/24
az network vnet subnet create \
--resource-group myapp-rg \
--vnet-name myapp-vnet \
--name db-snet \
--address-prefix 10.0.3.0/24
# List subnets
az network vnet subnet list \
--resource-group myapp-rg \
--vnet-name myapp-vnet \
--output table
VNet Peering
Connect two VNets so their resources can communicate privately (even across subscriptions or regions):
# Peer VNet A to VNet B
az network vnet peering create \
--resource-group myapp-rg \
--name vnetA-to-vnetB \
--vnet-name vnetA \
--remote-vnet /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/vnetB \
--allow-vnet-access
# Peer VNet B to VNet A (peering is not transitive; must create both directions)
az network vnet peering create \
--resource-group myapp-rg \
--name vnetB-to-vnetA \
--vnet-name vnetB \
--remote-vnet /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/vnetA \
--allow-vnet-access
VNet peering is not transitive: if A↔B and B↔C, then A cannot reach C unless you also peer A↔C.
Network Security Groups (NSGs)
An NSG is a stateful firewall containing allow/deny rules for inbound and outbound traffic. You attach NSGs to subnets or individual NICs.
NSG Rules (evaluated in priority order, lowest number = first)
Priority | Name | Protocol | Source | Destination | Port | Action
---------|---------------|----------|---------------|-------------|-------|-------
100 | Allow-HTTP | TCP | Any | Any | 80 | Allow
110 | Allow-HTTPS | TCP | Any | Any | 443 | Allow
200 | Allow-SSH | TCP | 203.0.113.0/24| Any | 22 | Allow
65000 | (default) | Any | VirtualNetwork| Any | * | Allow
65001 | (default) | Any | AzureLoadBal | Any | * | Allow
65500 | (default) | Any | Any | Any | * | Deny (catch-all)
# Create an NSG
az network nsg create \
--resource-group myapp-rg \
--name web-nsg
# Allow HTTPS inbound
az network nsg rule create \
--resource-group myapp-rg \
--nsg-name web-nsg \
--name Allow-HTTPS \
--priority 100 \
--direction Inbound \
--protocol TCP \
--source-address-prefix '*' \
--destination-port-range 443 \
--access Allow
# Allow SSH only from a specific IP
az network nsg rule create \
--resource-group myapp-rg \
--nsg-name web-nsg \
--name Allow-SSH-Office \
--priority 200 \
--direction Inbound \
--protocol TCP \
--source-address-prefix 203.0.113.0/24 \
--destination-port-range 22 \
--access Allow
# Attach NSG to a subnet
az network vnet subnet update \
--resource-group myapp-rg \
--vnet-name myapp-vnet \
--name web-snet \
--network-security-group web-nsg
Service Tags
Instead of hardcoding IP ranges, use Service Tags to represent Azure services:
| Tag | Represents |
|---|---|
Internet | All public internet traffic |
VirtualNetwork | VNet address space + peered VNets |
AzureLoadBalancer | Azure infrastructure health probes |
Storage | Azure Storage IP ranges |
Sql | Azure SQL IP ranges |
AzureCloud | All Azure datacenter IPs |
AppService | App Service outbound IPs |
# Allow traffic only from Azure Front Door
az network nsg rule create \
--resource-group myapp-rg \
--nsg-name web-nsg \
--name Allow-FrontDoor \
--priority 150 \
--direction Inbound \
--protocol TCP \
--source-address-prefix AzureFrontDoor.Backend \
--destination-port-range 443 \
--access Allow
Azure Bastion
Azure Bastion provides secure SSH/RDP access to VMs directly through the browser, without exposing port 22 or 3389 to the internet.
# Create Bastion (requires a /26 subnet named AzureBastionSubnet)
az network vnet subnet create \
--resource-group myapp-rg \
--vnet-name myapp-vnet \
--name AzureBastionSubnet \
--address-prefix 10.0.4.0/26
az network public-ip create \
--resource-group myapp-rg \
--name bastion-pip \
--sku Standard
az network bastion create \
--resource-group myapp-rg \
--name myapp-bastion \
--public-ip-address bastion-pip \
--vnet-name myapp-vnet \
--location eastus
Once deployed, connect to any VM via the Azure Portal → VM → Connect → Bastion.
Load Balancer
Azure Load Balancer distributes TCP/UDP traffic across healthy VMs at layer 4 (transport layer).
| SKU | Public | Internal | Availability Zones | Use Case |
|---|---|---|---|---|
| Basic | yes | yes | No | Dev/test |
| Standard | yes | yes | Yes | Production |
# Create a public Standard Load Balancer
az network public-ip create \
--resource-group myapp-rg \
--name lb-pip \
--sku Standard \
--allocation-method Static
az network lb create \
--resource-group myapp-rg \
--name myapp-lb \
--sku Standard \
--public-ip-address lb-pip \
--frontend-ip-name myFrontEnd \
--backend-pool-name myBackEnd
# Health probe (TCP port 80)
az network lb probe create \
--resource-group myapp-rg \
--lb-name myapp-lb \
--name httpProbe \
--protocol Tcp \
--port 80
# Load balancing rule (distribute port 80)
az network lb rule create \
--resource-group myapp-rg \
--lb-name myapp-lb \
--name httpRule \
--protocol Tcp \
--frontend-port 80 \
--backend-port 80 \
--frontend-ip-name myFrontEnd \
--backend-pool-name myBackEnd \
--probe-name httpProbe
Application Gateway
Application Gateway is a layer-7 (HTTP/HTTPS) load balancer with additional features:
- URL-based routing (
/api/*to API backend,/to web backend) - SSL/TLS termination
- Web Application Firewall (WAF)
- Session affinity (cookie-based)
- Autoscaling
# Create Application Gateway (simplified; full config has many more options)
az network application-gateway create \
--resource-group myapp-rg \
--name myapp-agw \
--location eastus \
--sku WAF_v2 \
--capacity 2 \
--vnet-name myapp-vnet \
--subnet agw-snet \
--public-ip-address agw-pip \
--http-settings-protocol Http \
--http-settings-port 80 \
--routing-rule-type Basic \
--priority 100
Application Gateway vs Load Balancer vs Front Door
| Feature | Load Balancer | App Gateway | Front Door |
|---|---|---|---|
| Layer | 4 (TCP/UDP) | 7 (HTTP/HTTPS) | 7 (HTTP/HTTPS) |
| Scope | Regional | Regional | Global |
| URL routing | No | Yes | Yes |
| WAF | No | Yes (WAF_v2) | Yes |
| SSL offload | No | Yes | Yes |
| CDN | No | No | Yes |
| Multi-region | No | No | Yes |
Use Front Door as your global entry point for multi-region apps. Use Application Gateway for per-region routing and WAF. Use Load Balancer for non-HTTP or internal TCP traffic.
Azure DNS
Azure DNS hosts your DNS zones and records using Microsoft's global infrastructure.
# Create a DNS zone
az network dns zone create \
--resource-group myapp-rg \
--name myapp.com
# Add an A record
az network dns record-set a add-record \
--resource-group myapp-rg \
--zone-name myapp.com \
--record-set-name www \
--ipv4-address 20.1.2.3
# Add a CNAME
az network dns record-set cname set-record \
--resource-group myapp-rg \
--zone-name myapp.com \
--record-set-name api \
--cname myapp-api.azurewebsites.net
# List all records
az network dns record-set list \
--resource-group myapp-rg \
--zone-name myapp.com \
--output table
Private DNS Zones resolve names within a VNet without going to the internet:
# Create private DNS zone
az network private-dns zone create \
--resource-group myapp-rg \
--name privatelink.blob.core.windows.net # Used for Private Endpoints
# Link to a VNet
az network private-dns link vnet create \
--resource-group myapp-rg \
--zone-name privatelink.blob.core.windows.net \
--name myapp-vnet-link \
--virtual-network myapp-vnet \
--registration-enabled false
Private Endpoints
A Private Endpoint gives an Azure service (Storage, SQL, Key Vault, etc.) a private IP address inside your VNet, so traffic never crosses the public internet.
# Get the storage account ID
STORAGE_ID=$(az storage account show \
--name mystorageacct \
--resource-group myapp-rg \
--query id --output tsv)
# Create a private endpoint for Blob Storage
az network private-endpoint create \
--resource-group myapp-rg \
--name storage-pe \
--vnet-name myapp-vnet \
--subnet db-snet \
--private-connection-resource-id $STORAGE_ID \
--group-id blob \
--connection-name storageConnection
VPN Gateway
VPN Gateway connects your on-premises network to an Azure VNet over an encrypted IPsec/IKE tunnel.
# Create a VPN Gateway (takes ~30 minutes)
az network vnet subnet create \
--resource-group myapp-rg \
--vnet-name myapp-vnet \
--name GatewaySubnet \
--address-prefix 10.0.5.0/27 # Must be named GatewaySubnet
az network public-ip create \
--resource-group myapp-rg \
--name vpn-pip \
--allocation-method Dynamic
az network vnet-gateway create \
--resource-group myapp-rg \
--name myapp-vpn \
--location eastus \
--public-ip-address vpn-pip \
--vnet myapp-vnet \
--gateway-type Vpn \
--vpn-type RouteBased \
--sku VpnGw1
ExpressRoute is the premium alternative: a dedicated private connection from your data centre to Azure, not over the public internet. Offers guaranteed bandwidth and lower latency.
Common Network Topologies
Hub-and-Spoke (Recommended for Enterprise)
Hub VNet
├── Firewall / NVA
├── VPN / ExpressRoute Gateway
└── Shared services (DNS, monitoring)
│
┌─────────────┼─────────────┐
▼ ▼ ▼
Spoke VNet A Spoke VNet B Spoke VNet C
(Production) (Dev/Test) (Data)
Use Azure Virtual WAN to manage hub-and-spoke across many regions and many spokes.
Network Architecture Best Practices
- Segment by tier: Separate subnets for web, application, and database layers
- Use NSGs everywhere: Apply to subnets, not individual NICs, for manageability
- Avoid public IPs on VMs: Use Bastion for management access
- Use Private Endpoints: Keep traffic to Azure services inside the VNet
- Plan CIDR ranges carefully: Avoid overlap with on-premises ranges; leave room to grow
- Enable NSG Flow Logs: Critical for troubleshooting and security auditing
Next Steps
Continue to 06-databases.md to learn about Azure's managed database services.