Theoretical Foundation: Configure Azure DNS
1. Initial Intuitionβ
DNS (Domain Name System) is the phone book of the internet. When you type www.microsoft.com, your computer doesn't know what the IP address of that server is. It queries DNS, which responds with something like 20.112.52.29. Only then is the connection established. Without DNS, you would need to memorize IP addresses to access any website.
In Azure, there are two completely different contexts where DNS is relevant, and understanding this distinction is the starting point of everything:
The first is public DNS: name resolution for resources accessible from the internet, like mysite.com or api.mycompany.com. Azure DNS hosts public zones and responds to queries from anywhere in the world.
The second is private DNS: name resolution within your VNets, like vm-backend.internal.contoso.com or db.production.local. Azure Private DNS hosts private zones visible only to the VNets you link.
Both services have the same name on the platform and look similar, but they serve distinct purposes with different behaviors.
2. Contextβ
Azure DNS integrates with various other services and is a central component of network infrastructure:
For AZ-104, Azure DNS is especially relevant in the context of Private Endpoints: when a PaaS service (Storage, Key Vault, SQL) receives a Private Endpoint, its default FQDN (mystorageaccount.blob.core.windows.net) needs to resolve to the private IP of the endpoint, not to the default public IP. This is done with a Private DNS Zone specific to each service.
3. Building the Conceptsβ
3.1 Public DNS: Azure DNS Public Zonesβ
A DNS Zone is the container that hosts the DNS records of a domain. When you create a zone in Azure DNS for contoso.com, Azure becomes the authoritative server for that domain, responding to queries from anywhere in the world.
For Azure DNS to function as the authoritative server for your domain, you need to delegate the domain to Azure's nameservers. This is done at the domain registrar (where you bought the domain): you configure the registrar's nameservers to point to the 4 nameservers that Azure assigns to your zone.
The nameservers have the format:
ns1-01.azure-dns.com
ns2-01.azure-dns.net
ns3-01.azure-dns.org
ns4-01.azure-dns.info
Azure uses different TLDs (.com, .net, .org, .info) to increase resilience: an attack or problem with a specific TLD won't bring down resolution.
3.2 DNS Record Typesβ
DNS records are the entries within a zone. Each record has a type that defines what it represents:
| Type | Name | Use | Example |
|---|---|---|---|
| A | Address | IPv4 IP of a host | www β 20.112.52.29 |
| AAAA | IPv6 Address | IPv6 IP of a host | www β 2001:db8::1 |
| CNAME | Canonical Name | Alias to another name (not to IP) | www β contoso.azurewebsites.net |
| MX | Mail Exchanger | Domain's mail servers | @ β 10 mail.contoso.com |
| TXT | Text | Domain verification, SPF, DKIM | @ β "v=spf1 include:..." |
| NS | Name Server | Zone's authoritative servers | (automatic) |
| SOA | Start of Authority | Zone information | (automatic) |
| PTR | Pointer | Reverse resolution (IP β name) | 4.1.0.10.in-addr.arpa β vm-web.contoso.com |
| SRV | Service | Service location (e.g., SIP, XMPP) | _sip._tcp β priority, weight, port, target |
| CAA | Certification Authority Authorization | Defines which CAs can issue certificates | @ β 0 issue "letsencrypt.org" |
Special record: Alias Record (A/AAAA/CNAME)
Azure DNS supports a special type of record called Alias Record. Unlike a normal A record that points to a fixed IP, an Alias Record points to an Azure resource (Load Balancer, Traffic Manager, CDN, Public IP). When the resource's IP changes, the Alias Record updates automatically, without manual intervention.
This solves the classic problem of using CNAME at the domain apex: CNAME records at the apex (@, meaning contoso.com without subdomain) are prohibited by the DNS protocol. An Alias Record at the apex pointing to an Azure resource is allowed and recommended.
3.3 TTL (Time to Live)β
TTL is a field in each DNS record that indicates how many seconds other DNS resolvers can cache that record. Common values:
| TTL | Seconds | When to use |
|---|---|---|
| 300 | 5 minutes | Records that change frequently, or during migrations |
| 3600 | 1 hour | Stable production records |
| 86400 | 1 day | Very stable records (MX, NS) |
During migrations: reduce TTL to 300 seconds at least 24 hours before making the change. This ensures that when you change the record, global propagation occurs in at most 5 minutes. After stable migration, increase TTL again.
3.4 Private DNS: Azure Private DNS Zonesβ
A Private DNS Zone works like a DNS zone, but is visible only to the VNets you link to it. Names resolved by a Private DNS Zone are not accessible from the internet.
The mechanism is simple: Azure has an internal DNS server in each VNet accessible via IP 168.63.129.16. By default, this server resolves host names within the VNet. When you link a Private DNS Zone to a VNet, the DNS server 168.63.129.16 also starts querying the private zone.
Auto-registration: when a VNet is linked to a Private DNS Zone with auto-registration enabled, every VM created in that VNet has its hostname automatically registered in the zone. For example, if the zone is production.internal and you create a VM called vm-backend, the record vm-backend.production.internal is automatically created pointing to the VM's private IP.
### 3.5 Private DNS Zones for Private Endpoints
This is the most important use case for Private DNS Zones in the AZ-104 context. When a PaaS service receives a **Private Endpoint**, Azure creates a private IP for that service. For applications to access the service by name (not by IP), a Private DNS Zone specific to each service type is required.
| Service | Original FQDN | Required Private DNS Zone |
|---|---|---|
| Azure Blob Storage | `mystorageaccount.blob.core.windows.net` | `privatelink.blob.core.windows.net` |
| Azure File Storage | `mystorageaccount.file.core.windows.net` | `privatelink.file.core.windows.net` |
| Azure Key Vault | `mykeyvault.vault.azure.net` | `privatelink.vaultcore.azure.net` |
| Azure SQL Database | `myserver.database.windows.net` | `privatelink.database.windows.net` |
| Azure Cosmos DB | `mycosmos.documents.azure.com` | `privatelink.documents.azure.com` |
The mechanism is as follows: the service's original FQDN (`mystorageaccount.blob.core.windows.net`) has a CNAME that points to a `privatelink` name (`mystorageaccount.privatelink.blob.core.windows.net`). The Private DNS Zone `privatelink.blob.core.windows.net` has an A record mapping that name to the endpoint's private IP.
---
## 4. Structural View
```mermaid
graph TD
subgraph Public[Public DNS]
PZ[Azure DNS Zone\ncontoso.com] --> RA[A record: www β 20.112.x.x]
PZ --> RCNAME[CNAME: api β contoso.azurefd.net]
PZ --> RMX[MX: @ β mail.contoso.com]
PZ --> ALIAS[Alias: @ β pip-lb-frontend]
end
subgraph Private[Private DNS]
PRZ[Private DNS Zone\nproduction.internal\nLinked to VNet-Production] --> PA[A record: vm-backend β 10.0.2.4]
PRZ --> PB[A record: vm-db β 10.0.3.4]
PLINK[Private DNS Zone\nprivatelink.blob.core.windows.net\nLinked to VNet-Production] --> PC[A record: myaccount β 10.0.4.5]
end
INTERNET[Internet] -->|Public DNS query| PZ
VM_VNET[VM in VNet-Production] -->|168.63.129.16| PRZ
VM_VNET -->|168.63.129.16| PLINK
style PZ fill:#107c10,stroke:#0a5c0a,color:#fff
style PRZ fill:#d83b01,stroke:#a02d00,color:#fff
style PLINK fill:#d83b01,stroke:#a02d00,color:#fff
5. How It Works in Practiceβ
Configure a Public DNS Zone: Complete Flowβ
Check propagation: after configuring the nameservers, you can verify if delegation is working:
# Query which nameserver is being used for the domain
nslookup -type=NS contoso.com
# Query a specific record directly on Azure's nameserver
nslookup www.contoso.com ns1-01.azure-dns.com
Important and Non-Obvious Behaviorsβ
Zone Apex and CNAME: the domain root (contoso.com, without prefix) is called zone apex and is represented by @ in records. By DNS protocol, it's not possible to create a CNAME at the apex. If you need contoso.com to point to an Azure service (like App Service or Front Door), use an Alias Record in Azure DNS, which is a proprietary extension that bypasses this limitation.
Subdomain delegation: you can delegate a subdomain to another DNS server. For example, delegate division.contoso.com to an on-premises DNS server or to another zone in Azure DNS. This is done by creating an NS record in the subdomain pointing to the subdomain's authoritative servers.
Split-horizon resolution: in some scenarios you want api.contoso.com to resolve to a public IP when queried from the internet, but to a private IP when queried from within the VNet. This is possible with a Private DNS Zone contoso.com linked to the VNet with the api record pointing to the private IP, while the public zone has the same record pointing to the public IP. The VNet resolver (168.63.129.16) queries the private zone first.
6. Implementation Methodsβ
6.1 Azure Portalβ
When to use: initial configuration, adding individual records, visual verification.
Create public DNS Zone: Create a resource > Networking > DNS zone > enter domain name
Create Private DNS Zone: Create a resource > Networking > Private DNS zone > enter private zone name
Link Private DNS Zone to a VNet: Private DNS zone > Virtual network links > Add
In linking, you choose:
- The VNet to be linked
- Whether auto-registration is enabled (VMs created in this VNet are automatically registered)
Create records: DNS zone > + Record set > choose type, name, TTL and value
6.2 Azure CLIβ
Create public DNS Zone:
az network dns zone create \
--name contoso.com \
--resource-group rg-dns
List assigned nameservers (to configure in registrar):
az network dns zone show \
--name contoso.com \
--resource-group rg-dns \
--query "nameServers" \
--output table
Create DNS records:
# A record
az network dns record-set a add-record \
--resource-group rg-dns \
--zone-name contoso.com \
--record-set-name www \
--ipv4-address 20.112.52.29 \
--ttl 3600
# CNAME record
az network dns record-set cname set-record \
--resource-group rg-dns \
--zone-name contoso.com \
--record-set-name api \
--cname contoso.azurewebsites.net \
--ttl 3600
# MX record
az network dns record-set mx add-record \
--resource-group rg-dns \
--zone-name contoso.com \
--record-set-name "@" \
--exchange mail.contoso.com \
--preference 10 \
--ttl 3600
# TXT record (domain verification, SPF)
az network dns record-set txt add-record \
--resource-group rg-dns \
--zone-name contoso.com \
--record-set-name "@" \
--value "v=spf1 include:spf.protection.outlook.com -all" \
--ttl 3600
Create Alias Record pointing to public IP:
az network dns record-set a create \
--resource-group rg-dns \
--zone-name contoso.com \
--name "@" \
--ttl 300 \
--target-resource /subscriptions/<sub-id>/resourceGroups/rg-networking/providers/Microsoft.Network/publicIPAddresses/pip-lb-frontend
Create Private DNS Zone:
az network private-dns zone create \
--resource-group rg-dns \
--name production.internal
Link Private DNS Zone to a VNet with auto-registration:
az network private-dns link vnet create \
--resource-group rg-dns \
--zone-name production.internal \
--name link-vnet-production \
--virtual-network vnet-production \
--registration-enabled true
Create record in Private DNS Zone:
az network private-dns record-set a add-record \
--resource-group rg-dns \
--zone-name production.internal \
--record-set-name vm-backend \
--ipv4-address 10.0.2.4
Create Private DNS Zone for Storage Private Endpoint:
# Create zone for blob storage
az network private-dns zone create \
--resource-group rg-dns \
--name privatelink.blob.core.windows.net
# Link to production VNet (without auto-registration, manually managed)
az network private-dns link vnet create \
--resource-group rg-dns \
--zone-name privatelink.blob.core.windows.net \
--name link-vnet-production-blob \
--virtual-network vnet-production \
--registration-enabled false
6.3 PowerShellβ
# Create DNS Zone
New-AzDnsZone -Name "contoso.com" -ResourceGroupName "rg-dns"
# Create A record
New-AzDnsRecordSet -Name "www" -RecordType A -ZoneName "contoso.com" `
-ResourceGroupName "rg-dns" -Ttl 3600 `
-DnsRecords (New-AzDnsRecordConfig -Ipv4Address "20.112.52.29")
# Create Private DNS Zone
New-AzPrivateDnsZone -ResourceGroupName "rg-dns" -Name "production.internal"
# Link with auto-registration
$vnet = Get-AzVirtualNetwork -Name "vnet-production" -ResourceGroupName "rg-networking"
New-AzPrivateDnsVirtualNetworkLink `
-ResourceGroupName "rg-dns" `
-ZoneName "production.internal" `
-Name "link-vnet-production" `
-VirtualNetworkId $vnet.Id `
-EnableRegistration
6.4 Bicepβ
// Public DNS Zone
resource dnsZone 'Microsoft.Network/dnsZones@2018-05-01' = {
name: 'contoso.com'
location: 'global' // DNS Zones are global resources
}
// A record
resource wwwRecord 'Microsoft.Network/dnsZones/A@2018-05-01' = {
parent: dnsZone
name: 'www'
properties: {
TTL: 3600
ARecords: [
{
ipv4Address: '20.112.52.29'
}
]
}
}
// Private DNS Zone
resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
name: 'production.internal'
location: 'global'
}
// Link with VNet
resource vnetLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
parent: privateDnsZone
name: 'link-vnet-production'
location: 'global'
properties: {
virtualNetwork: {
id: vnet.id
}
registrationEnabled: true
}
}
7. Control and Securityβ
RBAC for Azure DNSβ
Azure DNS has specific roles:
| Role | Permissions |
|---|---|
| DNS Zone Contributor | Create and manage zones and records, but not VNets |
| Private DNS Zone Contributor | Create and manage private zones and links with VNets |
| Network Contributor | Includes DNS permissions plus other network resources |
To delegate DNS management to a specific team without giving access to other network resources, use the DNS Zone Contributor role on the specific zone.
Critical Record Protectionβ
Azure DNS supports record set locks via Azure Resource Locks: you can apply a CanNotDelete lock on SOA and NS records to prevent accidental deletion that could bring down the domain.
# Lock on a specific record set
az lock create \
--name lock-ns-records \
--lock-type CanNotDelete \
--resource-group rg-dns \
--resource-type Microsoft.Network/dnsZones/NS \
--resource contoso.com \
--parent dnsZones/contoso.com
Domain Verification (TXT Records)β
Services like Microsoft 365, Google Workspace and others require you to prove that you own the domain by adding a specific TXT record. Azure DNS makes this simple:
az network dns record-set txt add-record \
--resource-group rg-dns \
--zone-name contoso.com \
--record-set-name "@" \
--value "MS=ms12345678" # Value provided by the service
8. Decision Makingβ
Public vs. private DNS: when to use each?β
| Situation | Solution | Reason |
|---|---|---|
| Site accessible from the internet | Public DNS Zone in Azure DNS | Responds to global queries |
| VM names within VNets | Private DNS Zone with autoregistration | Internal resolution only |
| Private Endpoint for PaaS service | Private DNS Zone privatelink.* | Redirects name to private IP |
Custom domain at apex (contoso.com) | Alias Record in Azure DNS | Solution for CNAME limitation at apex |
| Different resolution internal vs. external | Split-horizon with public + private zone | Private zone overrides public for VNets |
Autoregistration enabled vs. disabled?β
| Situation | Autoregistration | Reason |
|---|---|---|
| VMs with predictable and stable names | Enabled | Eliminates manual record management |
| Services with manually managed IPs | Disabled | Full control over which records exist |
| Private Endpoints | Disabled | Records created by PE process, not by VMs |
| Multiple VNets linked to the same zone | Only one with autoregistration | Limitation: only one VNet per zone can have autoregistration |
9. Best Practicesβ
Separate DNS resources into a dedicated Resource Group: place all DNS Zones (public and private) in a specific Resource Group (rg-dns or rg-networking-global). This facilitates applying specific RBAC for the DNS team and prevents accidental deletion along with other resources.
Use low TTL (300 seconds) before any migration: at least 24 hours before changing a critical record (like the public IP of a site), reduce the TTL to 300 seconds. This minimizes the impact of clients with cache of the old value.
Create domain verification records for all Microsoft services you use: TXT records for SPF, DKIM and DMARC in the email domain, TXT verification records for Microsoft 365 and other services. Centralize everything in Azure DNS to have a single source of truth.
Document the purpose of each record set: use tags on record sets (via API/CLI) or maintain external documentation about which resource each record points to and who is responsible. In zones with dozens of records, this prevents conflicts and facilitates diagnosis.
For Private Endpoints: create private zones centrally in the hub and link to spokes: in a hub-spoke architecture, create the Private DNS Zones privatelink.* in the hub Resource Group and link to both the hub and each spoke. This prevents creating duplicate zones in each spoke.
10. Common Errorsβ
Configuring incorrect nameservers at the registrar
Azure assigns 4 specific nameservers for each zone. If the administrator copies the nameservers from another zone (or from a generic example), the domain becomes unresponsive or points to the wrong zone. Always copy the nameservers from the portal directly from the created zone.
Trying to create CNAME at the domain apex
@ CNAME to another name is invalid by the DNS protocol. Azure DNS allows creating the record, but this violates the standard and many resolvers behave unpredictably. The correct solution is to use an Alias Record pointing to an Azure resource, or an A record with static IP.
Linking a VNet to a Private DNS Zone without disabling autoregistration in multiple VNets
A Private DNS Zone allows autoregistration in only one VNet. If you enable autoregistration in two different VNets linked to the same zone, Azure rejects the second with an error. Clearly define which VNet is the "primary" for autoregistration of each zone.
Forgetting to create the Private DNS Zone for Private Endpoints
A Private Endpoint is created for a Storage Account. The private IP is working. But when the application tries to access myaccount.blob.core.windows.net, DNS resolves to the public IP, not to the endpoint's private IP. The solution is to create the Private DNS Zone privatelink.blob.core.windows.net and the corresponding A record. Without this, name resolution ignores the Private Endpoint.
Changing high TTL during migration
An A record has TTL of 86400 (1 day). The administrator changes the IP to the new server. Clients that queried DNS in the last 24 hours have the cache of the old IP and continue accessing the old server for up to 24 hours. The correct practice is to reduce TTL days before migration.
11. Operation and Maintenanceβ
Verify DNS Resolutionβ
To test if a record is being resolved correctly:
# Resolve a public record
nslookup www.contoso.com
# Resolve against Azure nameserver explicitly
nslookup www.contoso.com ns1-01.azure-dns.com
# Resolve private record from within a VM in the VNet
# (run on the VM, not locally)
nslookup vm-backend.producao.internal 168.63.129.16
Via Azure CLI to check existing records:
# List all records of a zone
az network dns record-set list \
--resource-group rg-dns \
--zone-name contoso.com \
--output table
# Check a specific record set
az network dns record-set a show \
--resource-group rg-dns \
--zone-name contoso.com \
--name www
Monitoring and Diagnosticsβ
Azure DNS doesn't have native metrics in Azure Monitor for individual queries. For detailed monitoring:
- Use external DNS monitoring tools (Pingdom, UptimeRobot) to check availability of public records
- For Private DNS, diagnosis is done within VMs using
nslookupordig
Important Limitsβ
| Item | Limit |
|---|---|
| Public zones per subscription | 250 |
| Private zones per subscription | 1,000 |
| Record sets per public zone | 10,000 |
| Record sets per private zone | 25,000 |
| VNets linked per private zone | 1,000 |
| Private zones per VNet (with resolution) | 1,000 |
| Queries per second per zone | No documented limit (managed by Microsoft) |
12. Integration and Automationβ
Integration with Private Endpoints: Automatic Flowβ
When you create a Private Endpoint through the portal and choose "Integrate with Private DNS Zone", Azure can automatically create:
- The Private DNS Zone
privatelink.[service].core.windows.net - The A record mapping the name to the endpoint IP
- The zone link with the selected VNet
This is convenient but can create duplicate zones in environments with multiple VNets. The recommended practice in enterprise environments is not to use automatic integration and manage zones manually (or via IaC) to have centralized control.
Automatic Record Updates with Azure Functionsβ
In scenarios where IPs change frequently (VMs with dynamic IPs, scaling services), an Azure Function can update DNS records automatically:
Hierarchical DNS with Azure DNS Resolverβ
For hybrid environments where VMs in Azure need to resolve on-premises names AND Azure names, the Azure DNS Private Resolver (separate service, but related) allows creating forwarding rules: queries for corp.company.local are forwarded to the on-premises DNS server, while queries for producao.internal are answered by Azure private zones.
13. Final Summaryβ
Essential points:
- Public DNS (Azure DNS Zones): hosts records for domains accessible from the internet. Requires nameserver delegation at the domain registrar.
- Private DNS (Azure Private DNS Zones): hosts records visible only to linked VNets. Used for internal VM resolution and for Private Endpoints.
- Azure DNS uses IP
168.63.129.16as the default resolver within VNets. - Autoregistration in Private DNS Zones automatically creates records for VMs created in the linked VNet.
- Private Endpoints require Private DNS Zones
privatelink.*to resolve the service FQDN to the endpoint's private IP.
Critical differences:
- DNS Zone (public) vs. Private DNS Zone: public responds to any query from the internet; private only responds to linked VNets.
- A record vs. Alias Record: A record points to a fixed IP; Alias Record points to an Azure resource and updates automatically when the IP changes.
- CNAME at apex is invalid by DNS protocol. Use Alias Record to point the apex (
@) to an Azure resource. - Autoregistration enabled in only one VNet per private zone. Multiple VNets can be linked, but only one can have autoregistration.
What needs to be remembered:
- When creating a DNS Zone, Azure assigns 4 unique nameservers. These nameservers must be configured at the domain registrar for Azure to be authoritative.
- Reduce TTL to 300 seconds at least 24 hours before making changes to critical records.
- For Private Endpoints to work by name (not by IP), the Private DNS Zone
privatelink.[service]must exist, have the correct A record and be linked to VNets that need to resolve the name. - In hub-spoke architectures, create Private DNS Zones
privatelink.*centrally and link to both hub and spokes. - Azure DNS is a global service: zones are
location: globalresources, not regional.