Skip to content

Private DNS Zones

Azure Private DNS Zones enable DNS resolution of PaaS service private endpoints within each VNet. Without private DNS zones, services would resolve to the public IP of Azure PaaS resources — bypassing private endpoints entirely.


How Private DNS Works with Private Endpoints

Container App calls: mic-erp-be-dev-redis.redis.cache.windows.net

                              Azure DNS resolver

                    Private DNS Zone: privatelink.redis.cache.windows.net

                              Returns 10.0.2.5 (private IP)

                              Traffic stays within VNet

Without the private DNS zone, DNS would return the public IP X.X.X.X and traffic would exit the VNet — which is blocked by the NSG denying outbound internet from private-apps.


12 Private DNS Zones

All 12 zones are provisioned per-environment and linked to the environment's VNet.

Group 1: Core Azure Services

#DNS ZoneServiceUsed By
1privatelink.azurecr.ioAzure Container RegistryAll services pulling images
2privatelink.redis.cache.windows.netAzure Cache for RedisAll services using distributed cache
3privatelink.servicebus.windows.netAzure Service BusMessage-bus consumers and producers
4privatelink.blob.core.windows.netAzure Blob StorageAttachment service, reports
5privatelink.vaultcore.azure.netAzure Key VaultAll services reading secrets
6privatelink.database.windows.netAzure SQL / SQL ServerAll services with relational data

Group 2: Cosmos DB (Production)

#DNS ZoneServiceUsed By
7privatelink.mongo.cosmos.azure.comCosmos DB (Mongo API)MongoDB-based services
8privatelink.table.cosmos.azure.comCosmos DB (Table API)Reserved for future use

Group 3: Container Apps Environments

Azure Container Apps Environments create their own internal DNS zones for service-to-service communication. These are automatically managed by the CAE and should not be manually modified:

#DNS ZonePurpose
9{cae-name}.{region}.azurecontainerapps.ioPublic CAE FQDN
10{cae-name}.internal.{region}.azurecontainerapps.ioPrivate CAE internal FQDNs

Group 4: Supporting Services

#DNS ZoneServiceUsed By
11privatelink.azurewebsites.netAzure Static Web Apps / Web AppsFrontend static apps
12privatelink.monitor.azure.comAzure Monitor (OTLP endpoint)OpenTelemetry exporters

Bicep Provisioning

Each private DNS zone is provisioned with a VNet link in Devops/azure/infrastructure/modules/privateDns.bicep:

bicep
// Example: Redis private DNS zone
resource redisPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
  name: 'privatelink.redis.cache.windows.net'
  location: 'global'
}

resource redisVnetLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
  parent: redisPrivateDnsZone
  name: '${environmentName}-redis-dns-link'
  location: 'global'
  properties: {
    virtualNetwork: {
      id: vnet.id
    }
    registrationEnabled: false   // Only resolves, does not auto-register
  }
}

// A-record created by the private endpoint itself
resource redisPrivateEndpoint 'Microsoft.Network/privateEndpoints@2023-05-01' = {
  name: 'mic-erp-be-${environment}-redis-pe'
  location: location
  properties: {
    subnet: {
      id: privateEndpointsSubnet.id
    }
    privateLinkServiceConnections: [
      {
        name: 'redis-connection'
        properties: {
          privateLinkServiceId: redisCache.id
          groupIds: ['redisCache']
        }
      }
    ]
  }
}

resource redisDnsGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-05-01' = {
  parent: redisPrivateEndpoint
  name: 'default'
  properties: {
    privateDnsZoneConfigs: [
      {
        name: 'config'
        properties: {
          privateDnsZoneId: redisPrivateDnsZone.id
        }
      }
    ]
  }
}

DNS Resolution Troubleshooting

Verify DNS resolution from inside a Container App

bash
# Use a debug container or exec into a running container
az containerapp exec \
  --name mic-erp-accounting \
  --resource-group mic-erp-be-dev-apps-rg \
  --command nslookup

# Inside the container:
nslookup mic-erp-be-dev-redis.redis.cache.windows.net
# Expected: returns 10.0.2.5 (private IP)
# Wrong: returns 20.X.X.X (public IP) → private DNS zone not linked
bash
az network private-dns link vnet list \
  --resource-group mic-erp-be-dev-network-rg \
  --zone-name privatelink.redis.cache.windows.net \
  --output table

Expected output:

Name                          VirtualNetworkName     RegistrationEnabled    ProvisioningState
----------------------------  ---------------------  ---------------------  ---------------
dev-redis-dns-link            mic-erp-be-dev-vnet    False                  Succeeded

Common DNS Issues

SymptomLikely CauseResolution
Service resolves to public IPDNS zone not linked to VNetAdd VNet link in Bicep and redeploy
DNS NXDOMAIN for .redis.cache.windows.netPrivate endpoint not createdProvision private endpoint and DNS zone group
Intermittent DNS failuresDNS zone link in Failed stateDelete and recreate the VNet link
Private endpoint A-record missingDNS zone group not attached to PERe-create the privateDnsZoneGroups resource

DNS Zone Scope

Private DNS zones are provisioned in each environment's network resource group:

  • dev: mic-erp-be-dev-network-rg
  • stage: mic-erp-be-stage-network-rg (note: stg may appear in some names)
  • preprod: mic-erp-be-preprod-network-rg
  • uat: mic-erp-be-uat-network-rg
  • production: mic-erp-be-production-network-rg

Note: The orphaned RG mic-erp-bk-dev-network-rg exists from the old bk naming convention. It is safe to ignore but should not be used for new resources.


Auto-Registration vs Manual A-Records

  • registrationEnabled: false on all VNet links — resources in the VNet are not automatically registered in private DNS zones.
  • Private endpoint DNS records (A-records) are created and managed by the privateDnsZoneGroups resource attached to each private endpoint.
  • Do not manually create A-records — they are managed by Azure when private endpoints are created or updated.

ACR DNS Note

ACR has two private endpoint types, both requiring DNS zones:

privatelink.azurecr.io     — Registry data plane
privatelink.azurecr.io     — Registry control plane (same zone, different sub-resource)

Both are handled by a single DNS zone. Ensure the private endpoint specifies both groupIds:

bicep
groupIds: ['registry', 'registry_data_{region}']
// e.g.: 'registry_data_uksouth'

Internal Documentation — Microtec Platform Team