🔐 Azure Private Link - Design and Implementation Guide
1. Overview and Architecture
Azure Private Link enables secure connectivity to Azure services over a private endpoint in your virtual network. This eliminates exposure to the public internet while maintaining service functionality.
graph TB
subgraph "On-Premises"
OnPrem[On-Premises Network]
OnPremVM[Virtual Machine]
end
subgraph "Azure Hub VNet"
HubVNet[Hub Virtual Network
10.0.0.0/16]
VNetGW[VNet Gateway]
Firewall[Azure Firewall]
DNS[Private DNS Zone]
end
subgraph "Azure Spoke VNet"
SpokeVNet[Spoke Virtual Network
10.1.0.0/16]
VM[Virtual Machine]
PE[Private Endpoint
10.1.1.10]
end
subgraph "Azure PaaS Services"
Storage[Azure Storage Account]
SQL[Azure SQL Database]
KeyVault[Azure Key Vault]
end
OnPrem --> VNetGW
VNetGW --> HubVNet
HubVNet --> SpokeVNet
VM --> PE
PE --> Storage
PE --> SQL
PE --> KeyVault
DNS --> PE
style PE fill:#e1f5fe
style DNS fill:#f3e5f5
style Storage fill:#e8f5e8
style SQL fill:#e8f5e8
style KeyVault fill:#e8f5e8
Architecture Overview Explanation:
This diagram shows the complete Azure Private Link architecture with hub-and-spoke topology. The private endpoint acts as a network interface that connects your virtual network privately to Azure services. Traffic flows through the private endpoint using Microsoft's backbone network, never traversing the public internet. The hub VNet contains shared services like DNS and gateway connections, while spoke VNets contain workloads and private endpoints.
2. Traffic Flow Diagrams
2.1 Private Endpoint Traffic Flow
sequenceDiagram
participant VM as Virtual Machine
participant PE as Private Endpoint
participant DNS as Private DNS Zone
participant PaaS as Azure PaaS Service
VM->>DNS: 1. Resolve service FQDN
DNS->>VM: 2. Return private IP (10.1.1.10)
VM->>PE: 3. Connect to private IP
PE->>PaaS: 4. Forward request via backbone
PaaS->>PE: 5. Return response
PE->>VM: 6. Forward response
Note over VM,PaaS: All traffic uses private IP space
Note over PE,PaaS: Microsoft backbone network
Private Endpoint Traffic Flow Explanation:
This sequence diagram illustrates how traffic flows through a private endpoint. When a VM needs to access an Azure service, it first resolves the service's FQDN through the private DNS zone, which returns the private endpoint's IP address instead of the public IP. The VM then connects to this private IP, and the private endpoint forwards the request through Microsoft's backbone network to the actual service. This ensures all communication remains private and secure.
2.2 DNS Resolution Flow
graph TD
VM[Virtual Machine] --> CustomDNS{Custom DNS Server?}
CustomDNS -->|Yes| CustomServer[Custom DNS Server]
CustomDNS -->|No| AzureDNS[Azure Provided DNS]
CustomServer --> PrivateZone[Private DNS Zone
privatelink.blob.core.windows.net]
AzureDNS --> PrivateZone
PrivateZone --> PrivateIP[Private IP: 10.1.1.10]
subgraph "Without Private Link"
PublicDNS[Public DNS] --> PublicIP[Public IP: 20.60.40.4]
end
style PrivateZone fill:#e1f5fe
style PrivateIP fill:#c8e6c9
style PublicIP fill:#ffcdd2
DNS Resolution Flow Explanation:
This diagram shows how DNS resolution works with Private Link. The private DNS zone overrides public DNS resolution, ensuring that when applications resolve Azure service FQDNs, they receive private IP addresses instead of public ones. This is crucial for ensuring traffic flows through the private endpoint rather than over the public internet.
3. Implementation Sequence
graph TD
Start([Start Implementation]) --> Step1[1. Create Resource Group]
Step1 --> Step2[2. Create Virtual Network]
Step2 --> Step3[3. Create Subnet for Private Endpoints]
Step3 --> Step4[4. Create Azure Service
Storage/SQL/KeyVault]
Step4 --> Step5[5. Create Private Endpoint]
Step5 --> Step6[6. Create Private DNS Zone]
Step6 --> Step7[7. Link DNS Zone to VNet]
Step7 --> Step8[8. Create DNS A Record]
Step8 --> Step9[9. Configure Network Security]
Step9 --> Step10[10. Test Connectivity]
Step10 --> End([Implementation Complete])
style Start fill:#c8e6c9
style End fill:#c8e6c9
style Step5 fill:#e1f5fe
style Step6 fill:#f3e5f5
Implementation Sequence Explanation:
This flowchart outlines the correct order for implementing Azure Private Link. The sequence is important because each step builds upon the previous ones. You must create the network infrastructure first, then the Azure service, followed by the private endpoint, and finally the DNS configuration. This order ensures proper connectivity and name resolution.
4. Prerequisites and Setup
Prerequisites:
- Azure CLI installed and configured
- Appropriate Azure subscription permissions
- Understanding of Azure networking concepts
- Resource group and virtual network planning
4.1 Azure CLI Login and Setup
# Login to Azure
az login
# Set subscription (replace with your subscription ID)
az account set --subscription "your-subscription-id"
# Install Azure CLI extensions if needed
az extension add --name azure-cli-iot-ext
Login Command Explanation:
These commands authenticate you with Azure and set the working subscription. The az login
command opens a browser for authentication, while az account set
ensures you're working with the correct subscription. Extensions may be needed for specific services.
5. Step-by-Step Implementation
1Create Resource Group
az group create \
--name "rg-private-link-demo" \
--location "East US" \
--tags "Environment=Demo" "Purpose=PrivateLink"
Resource Group Creation:
This creates a logical container for all Private Link resources. The --name
parameter specifies the resource group name, --location
sets the Azure region, and --tags
adds metadata for organization and cost tracking. Choose a location close to your users for optimal performance.
2Create Virtual Network
az network vnet create \
--resource-group "rg-private-link-demo" \
--name "vnet-private-link" \
--address-prefixes "10.1.0.0/16" \
--location "East US" \
--tags "Environment=Demo"
Virtual Network Creation:
This creates the virtual network that will host your private endpoints. The --address-prefixes
parameter defines the IP address space (10.1.0.0/16 provides 65,536 addresses). Choose an address space that doesn't conflict with on-premises networks or other VNets you plan to peer with.
3Create Subnet for Private Endpoints
az network vnet subnet create \
--resource-group "rg-private-link-demo" \
--vnet-name "vnet-private-link" \
--name "subnet-private-endpoints" \
--address-prefixes "10.1.1.0/24" \
--disable-private-endpoint-network-policies true
Private Endpoint Subnet Creation:
This creates a dedicated subnet for private endpoints. The --disable-private-endpoint-network-policies true
parameter is crucial - it disables network policies (like NSGs and UDRs) on the subnet to allow private endpoint functionality. The /24 subnet provides 256 addresses, suitable for multiple private endpoints.
4Create Azure Storage Account
az storage account create \
--name "stprivatelinkdemo$(date +%s)" \
--resource-group "rg-private-link-demo" \
--location "East US" \
--sku "Standard_LRS" \
--kind "StorageV2" \
--https-only true \
--min-tls-version "TLS1_2" \
--allow-blob-public-access false
Storage Account Creation:
This creates a storage account that will be accessed via private endpoint. The
$(date +%s)
appends a timestamp to ensure a unique name.
--https-only true
enforces secure connections,
--min-tls-version TLS1_2
sets minimum security standards, and
--allow-blob-public-access false
prevents public access to containers.
Alternative SKU Options:
Standard_LRS
- Locally redundant storage (cheapest)
Standard_GRS
- Geo-redundant storage
Standard_ZRS
- Zone-redundant storage
Premium_LRS
- Premium locally redundant storage
5Disable Public Network Access
# Store storage account name for reuse
STORAGE_NAME="stprivatelinkdemo$(date +%s)"
az storage account update \
--name "$STORAGE_NAME" \
--resource-group "rg-private-link-demo" \
--default-action "Deny" \
--bypass "AzureServices"
Network Access Configuration:
This command disables public network access to the storage account.
--default-action Deny
blocks all public access, while
--bypass AzureServices
allows trusted Azure services to access the account. This forces all access through the private endpoint, ensuring security.
Bypass Options:
None
- No services can bypass
AzureServices
- Allow trusted Azure services
Logging
- Allow storage logging services
Metrics
- Allow storage metrics services
6Create Private Endpoint
# Get storage account resource ID
STORAGE_ID=$(az storage account show \
--name "$STORAGE_NAME" \
--resource-group "rg-private-link-demo" \
--query "id" \
--output tsv)
# Create private endpoint
az network private-endpoint create \
--name "pe-storage-blob" \
--resource-group "rg-private-link-demo" \
--vnet-name "vnet-private-link" \
--subnet "subnet-private-endpoints" \
--private-connection-resource-id "$STORAGE_ID" \
--group-id "blob" \
--connection-name "pe-connection-storage"
Private Endpoint Creation:
This creates the private endpoint that connects your VNet to the storage account. The
--group-id blob
parameter specifies which service within the storage account to connect to.
Storage Account Group IDs:
blob
- Blob storage service
file
- File storage service
queue
- Queue storage service
table
- Table storage service
web
- Static web hosting
The private endpoint gets assigned a private IP address from the subnet automatically.
7Create Private DNS Zone
az network private-dns zone create \
--resource-group "rg-private-link-demo" \
--name "privatelink.blob.core.windows.net"
Private DNS Zone Creation:
This creates a private DNS zone that will resolve the storage account's FQDN to the private endpoint's IP address. The zone name
privatelink.blob.core.windows.net
is the standard format for blob service private endpoints.
Common Private DNS Zone Names:
privatelink.blob.core.windows.net
- Blob storage
privatelink.file.core.windows.net
- File storage
privatelink.database.windows.net
- SQL Database
privatelink.vaultcore.azure.net
- Key Vault
privatelink.azurewebsites.net
- App Service
8Link DNS Zone to Virtual Network
az network private-dns link vnet create \
--resource-group "rg-private-link-demo" \
--zone-name "privatelink.blob.core.windows.net" \
--name "dns-link-vnet-private-link" \
--virtual-network "vnet-private-link" \
--registration-enabled false
DNS Zone VNet Link:
This links the private DNS zone to your virtual network, allowing VMs in the VNet to resolve names using the private zone.
--registration-enabled false
prevents automatic registration of VM records in the zone. This link is essential for DNS resolution to work properly.
Registration Options:
false
- Manual record management (recommended for private endpoints)
true
- Automatic VM record registration
9Create DNS A Record
# Get private endpoint IP address
PRIVATE_IP=$(az network private-endpoint show \
--name "pe-storage-blob" \
--resource-group "rg-private-link-demo" \
--query "customDnsConfigs[0].ipAddresses[0]" \
--output tsv)
# Create A record pointing to private endpoint
az network private-dns record-set a add-record \
--resource-group "rg-private-link-demo" \
--zone-name "privatelink.blob.core.windows.net" \
--record-set-name "$STORAGE_NAME" \
--ipv4-address "$PRIVATE_IP"
DNS A Record Creation:
This creates an A record that maps the storage account's name to the private endpoint's IP address. The record name is the storage account name, and it points to the private IP address obtained from the private endpoint. This ensures that when applications resolve the storage account's FQDN, they get the private IP instead of the public IP.
DNS Record Types Available:
A
- IPv4 address record (most common for private endpoints)
AAAA
- IPv6 address record
CNAME
- Canonical name record
TXT
- Text record
10Create Test Virtual Machine
# Create subnet for VM
az network vnet subnet create \
--resource-group "rg-private-link-demo" \
--vnet-name "vnet-private-link" \
--name "subnet-vm" \
--address-prefixes "10.1.2.0/24"
# Create public IP for VM
az network public-ip create \
--resource-group "rg-private-link-demo" \
--name "pip-vm-test" \
--sku "Standard" \
--allocation-method "Static"
# Create network security group
az network nsg create \
--resource-group "rg-private-link-demo" \
--name "nsg-vm-test"
# Create SSH rule
az network nsg rule create \
--resource-group "rg-private-link-demo" \
--nsg-name "nsg-vm-test" \
--name "AllowSSH" \
--priority 1000 \
--source-address-prefixes "*" \
--source-port-ranges "*" \
--destination-address-prefixes "*" \
--destination-port-ranges "22" \
--access "Allow" \
--protocol "Tcp"
# Create VM
az vm create \
--resource-group "rg-private-link-demo" \
--name "vm-test" \
--image "Ubuntu2204" \
--vnet-name "vnet-private-link" \
--subnet "subnet-vm" \
--nsg "nsg-vm-test" \
--public-ip-address "pip-vm-test" \
--admin-username "azureuser" \
--generate-ssh-keys \
--size "Standard_B2s"
Test VM Creation:
This creates a complete virtual machine setup for testing private endpoint connectivity. The VM is placed in a separate subnet from the private endpoints with its own network security group.
--generate-ssh-keys
automatically creates SSH keys if they don't exist. The VM will be used to test that the storage account is accessible via the private endpoint.
VM Size Options:
Standard_B1s
- 1 vCPU, 1GB RAM (smallest/cheapest)
Standard_B2s
- 2 vCPU, 4GB RAM (recommended for testing)
Standard_D2s_v3
- 2 vCPU, 8GB RAM (production workloads)
6. Advanced Scenarios
6.1 Multiple Service Private Endpoints
graph TB
subgraph "Virtual Network"
subgraph "PE Subnet"
PE1[Private Endpoint
Storage Blob]
PE2[Private Endpoint
Storage File]
PE3[Private Endpoint
SQL Database]
PE4[Private Endpoint
Key Vault]
end
subgraph "VM Subnet"
VM[Test VM]
end
end
subgraph "Private DNS Zones"
DNS1[privatelink.blob.core.windows.net]
DNS2[privatelink.file.core.windows.net]
DNS3[privatelink.database.windows.net]
DNS4[privatelink.vaultcore.azure.net]
end
subgraph "Azure Services"
Storage[Storage Account]
SQL[SQL Database]
KV[Key Vault]
end
VM --> PE1
VM --> PE2
VM --> PE3
VM --> PE4
PE1 --> Storage
PE2 --> Storage
PE3 --> SQL
PE4 --> KV
DNS1 --> PE1
DNS2 --> PE2
DNS3 --> PE3
DNS4 --> PE4
Multiple Service Private Endpoints:
This diagram shows how multiple private endpoints can be deployed in the same subnet to access different Azure services. Each service type requires its own private DNS zone with the appropriate privatelink subdomain. This pattern allows you to create a centralized private connectivity hub for multiple Azure services.
6.2 SQL Database Private Endpoint
# Create SQL Server
az sql server create \
--name "sql-private-link-demo" \
--resource-group "rg-private-link-demo" \
--location "East US" \
--admin-user "sqladmin" \
--admin-password "ComplexPassword123!" \
--enable-public-network false
# Create SQL Database
az sql db create \
--resource-group "rg-private-link-demo" \
--server "sql-private-link-demo" \
--name "demodb" \
--edition "Basic"
# Get SQL Server resource ID
SQL_ID=$(az sql server show \
--name "sql-private-link-demo" \
--resource-group "rg-private-link-demo" \
--query "id" \
--output tsv)
# Create private endpoint for SQL
az network private-endpoint create \
--name "pe-sql-server" \
--resource-group "rg-private-link-demo" \
--vnet-name "vnet-private-link" \
--subnet "subnet-private-endpoints" \
--private-connection-resource-id "$SQL_ID" \
--group-id "sqlServer" \
--connection-name "pe-connection-sql"
# Create private DNS zone for SQL
az network private-dns zone create \
--resource-group "rg-private-link-demo" \
--name "privatelink.database.windows.net"
# Link DNS zone to VNet
az network private-dns link vnet create \
--resource-group "rg-private-link-demo" \
--zone-name "privatelink.database.windows.net" \
--name "dns-link-sql" \
--virtual-network "vnet-private-link" \
--registration-enabled false
SQL Database Private Endpoint:
This creates a SQL Database with private endpoint connectivity. The
--enable-public-network false
parameter disables public access from the start. The
--group-id sqlServer
connects to the entire SQL Server instance, allowing access to all databases on that server.
SQL Database Editions:
Basic
- Up to 2GB, basic performance
Standard
- Up to 1TB, better performance
Premium
- Up to 4TB, high performance
GeneralPurpose
- vCore-based, balanced
BusinessCritical
- vCore-based, high performance
6.3 Cross-Subscription Private Link
# Create private endpoint in different subscription
az network private-endpoint create \
--name "pe-cross-subscription" \
--resource-group "rg-consumer-subscription" \
--vnet-name "vnet-consumer" \
--subnet "subnet-private-endpoints" \
--private-connection-resource-id "/subscriptions/provider-sub-id/resourceGroups/rg-provider/providers/Microsoft.Storage/storageAccounts/stprovider" \
--group-id "blob" \
--connection-name "cross-sub-connection" \
--request-message "Cross-subscription private link connection"
# Check connection status
az network private-endpoint show \
--name "pe-cross-subscription" \
--resource-group "rg-consumer-subscription" \
--query "privateLinkServiceConnections[0].privateLinkServiceConnectionState"
Cross-Subscription Private Endpoint:
This creates a private endpoint that connects to a resource in a different subscription. The
--private-connection-resource-id
parameter uses the full resource ID from the provider subscription. The
--request-message
parameter sends a message to the resource owner, who must approve the connection before it becomes active.
Connection States:
Pending
- Waiting for approval
Approved
- Connection approved and active
Rejected
- Connection rejected by resource owner
Disconnected
- Connection terminated
6.5 DNS Resolution in Hub-and-Spoke
sequenceDiagram
participant VM as VM in Spoke VNet
participant HubDNS as Hub DNS Zone
participant PE as Private Endpoint
participant Storage as Storage Account
VM->>HubDNS: 1. DNS Query: mystorageacct.blob.core.windows.net
Note over HubDNS: DNS Zone contains A record:
mystorageacct → 10.1.1.10
HubDNS->>VM: 2. DNS Response: 10.1.1.10
VM->>PE: 3. HTTP Request to 10.1.1.10
PE->>Storage: 4. Forward request via backbone
Storage->>PE: 5. Response
PE->>VM: 6. Response
Note over VM,Storage: DNS resolution is logical
Network traffic is direct
DNS vs Network Traffic Separation:
This sequence diagram clarifies that DNS resolution and network traffic are separate processes. The VM queries the centralized DNS zone in the hub (step 1-2), which returns the private endpoint's IP address. However, the actual network traffic (steps 3-6) flows directly from the VM to the private endpoint, not through the hub. The hub DNS zone only stores the mapping information - it doesn't route traffic.
graph TB
subgraph "Hub VNet - 10.0.0.0/16"
HubVM[Hub VM]
DNS[Private DNS Zones
Central Management]
FW[Azure Firewall]
end
subgraph "Spoke VNet 1 - 10.1.0.0/16"
Spoke1VM[Spoke 1 VM]
PE1[Private Endpoint
Storage
IP: 10.1.1.10]
end
subgraph "Spoke VNet 2 - 10.2.0.0/16"
Spoke2VM[Spoke 2 VM]
PE2[Private Endpoint
SQL
IP: 10.2.1.10]
end
subgraph "On-Premises"
OnPrem[On-Prem Network]
end
HubVM <-->|VNet Peering| Spoke1VM
HubVM <-->|VNet Peering| Spoke2VM
OnPrem -->|VPN/ExpressRoute| HubVM
Spoke1VM -->|Network Traffic| PE1
Spoke2VM -->|Network Traffic| PE2
DNS -->|DNS Zone Links| Spoke1VM
DNS -->|DNS Zone Links| Spoke2VM
DNS -->|DNS Resolution| HubVM
Note1[DNS Zones contain A records:
storageacct.blob.core.windows.net → 10.1.1.10
sqlserver.database.windows.net → 10.2.1.10]
style DNS fill:#f3e5f5
style PE1 fill:#e1f5fe
style PE2 fill:#e1f5fe
style Note1 fill:#fff9c4
Hub-and-Spoke Private Link Architecture:
This corrected diagram shows how Private Link actually works in a hub-and-spoke topology. The private DNS zones in the hub VNet don't have direct network connections to private endpoints. Instead, they contain DNS A records that map service FQDNs to private endpoint IP addresses. When VMs in spoke VNets make DNS queries, they're resolved through the hub's DNS zones via VNet links, returning the appropriate private IP addresses. The actual network traffic then flows directly from the VM to the private endpoint in its local spoke VNet.
7. Troubleshooting
7.1 Common Issues and Solutions
DNS Resolution Issues:
If DNS resolution is not working properly, check that the private DNS zone is correctly linked to your VNet and that the A record points to the correct private IP address.
7.2 Diagnostic Commands
# Test DNS resolution from VM (run on the VM)
nslookup $STORAGE_NAME.blob.core.windows.net
# Test connectivity with curl
curl -I https://$STORAGE_NAME.blob.core.windows.net
# Alternative DNS test with dig
dig $STORAGE_NAME.blob.core.windows.net
# Check private endpoint status
az network private-endpoint show \
--name "pe-storage-blob" \
--resource-group "rg-private-link-demo" \
--query "connectionState"
# List private DNS records
az network private-dns record-set list \
--resource-group "rg-private-link-demo" \
--zone-name "privatelink.blob.core.windows.net"
# Check effective routes on VM NIC
az network nic show-effective-route-table \
--resource-group "rg-private-link-demo" \
--name "vm-testVMNic"
# Verify private endpoint network interface
az network private-endpoint show \
--name "pe-storage-blob" \
--resource-group "rg-private-link-demo" \
--query "networkInterfaces[0].id"
Diagnostic Commands:
These commands help troubleshoot Private Link connectivity issues. nslookup
and dig
verify DNS resolution returns private IP addresses. curl
tests actual connectivity. The private endpoint show command checks the connection state, and the DNS record list command verifies the A records are correctly configured. The effective routes command shows the routing table to ensure traffic flows correctly.
7.3 Network Flow Verification
graph LR
VM[VM: 10.1.2.4] --> DNS{DNS Query}
DNS -->|Resolves to| PrivateIP[Private IP: 10.1.1.10]
PrivateIP --> PE[Private Endpoint]
PE --> Backbone[Microsoft Backbone]
Backbone --> Service[Azure Service]
DNS -->|Should NOT resolve to| PublicIP[Public IP: 20.60.40.4]
PublicIP -.->|Blocked| Internet[Internet]
style PrivateIP fill:#c8e6c9
style PublicIP fill:#ffcdd2
style Internet fill:#ffcdd2
Network Flow Verification:
This diagram illustrates how to verify that traffic is flowing through the private endpoint correctly. DNS queries should resolve to private IP addresses (10.x.x.x range) rather than public IP addresses. If DNS resolves to public IPs, check your private DNS zone configuration. The traffic should never traverse the public internet when properly configured.
7.4 Command Execution Order Diagram
graph TD
A[az group create] --> B[az network vnet create]
B --> C[az network vnet subnet create
PE Subnet]
C --> D[az storage account create]
D --> E[az storage account update
Disable Public Access]
E --> F[az network private-endpoint create]
F --> G[az network private-dns zone create]
G --> H[az network private-dns link vnet create]
H --> I[az network private-dns record-set a add-record]
I --> J[az network vnet subnet create
VM Subnet]
J --> K[az vm create]
K --> L[Test: nslookup & curl]
style A fill:#e8f5e8
style F fill:#e1f5fe
style G fill:#f3e5f5
style L fill:#fff3e0
Command Execution Order:
This diagram shows the exact sequence in which Azure CLI commands should be executed for successful Private Link implementation. Each step depends on the previous ones being completed successfully. The green boxes represent infrastructure setup, blue represents private endpoint creation, purple represents DNS configuration, and orange represents testing. Following this order ensures all dependencies are met.
Key Takeaways:
- Private endpoints provide secure, private connectivity to Azure services
- DNS configuration is crucial for proper functionality
- Network policies must be disabled on private endpoint subnets
- Implementation order matters - follow the sequence diagram
- Test connectivity thoroughly after implementation
- Each Azure service has its own privatelink DNS zone format
- Cross-subscription scenarios require approval workflows
- Hub-and-spoke topologies centralize DNS management