DNS Privado Multi-Região no Azure

Neste artigo você vai configurar o DNS privado multi-região no Azure para a Landing Zone Hub-Spoke, criando Private DNS Zones compartilhadas entre as quatro VNets — dois Hubs e dois Spokes em Brazil South e East US. Além disso, vamos criar uma zona interna do lab (blog-castilho.internal) e as zonas de privatelink para os serviços PaaS usados na série: Storage, SQL, ACR, Key Vault, Azure Monitor e Log Analytics. Tudo isso com um módulo Terraform reutilizável que cria a zona e os Virtual Network Links de uma só vez.
- 📖 Art. 01: Planejamento de DR Azure e Landing Zone
- 📖 Art. 02: Hub-Spoke Landing Zone com Terraform
- 📖 Art. 03: Azure Firewall e NSGs na Landing Zone
- 📖 Art. 04: Azure Bastion na Landing Zone sem IP Público
- 📖 Art. 05: Azure Front Door e Traffic Manager para Failover
- ⚙️ Art. 06 (este): DNS Privado Multi-Região no Azure
- 🔒 Art. 07: Azure Site Recovery para VMs Multi-Região
- 🔒 Art. 08: Azure Storage com Geo-Replicação para DR
- 🔒 Art. 09: AKS Multi-Região com Failover no Azure
- 🔒 Art. 10: Velero no AKS para Backup e Restore Cross-Region
- 🔒 Art. 11: Runbooks de Failover no Azure Automation
- 🔒 Art. 12: Simular um DR no Azure sem Impacto em Produção
- 🔒 Art. 13: Monitoramento do DR no Azure com Azure Monitor
Sumário
- Por que DNS privado multi-região é necessário
- Zonas DNS do lab
- Arquitetura: zonas centralizadas no Hub
- Pré-requisitos
- O módulo Terraform private-dns-zone
- Passo 1 — Código Terraform da zona
- Passo 2 — Executar o Terraform
- Passo 3 — Adicionar registros DNS
- Verificar a configuração
- Troubleshooting
- Limpeza dos recursos
- Próximos passos
Por que DNS privado multi-região no Azure é necessário
Sem DNS privado configurado, as VMs da Landing Zone que tentam acessar serviços PaaS como Storage Account ou Azure SQL via Private Endpoint recebem o IP público do serviço — mesmo que o tráfego esteja sendo roteado internamente. Isso ocorre porque o DNS público do Azure resolve os FQDNs dos serviços para IPs públicos por padrão. O DNS privado multi-região no Azure resolve esse problema criando zonas que sobrescrevem a resolução pública dentro das VNets.
| Cenário | Sem Private DNS | Com Private DNS |
|---|---|---|
| VM acessa Storage Account com Private Endpoint | DNS resolve IP público → tráfego sai para internet | DNS resolve IP privado do PE → tráfego fica na VNet |
| VM acessa Azure SQL com PE | Resolução para endpoint público | Resolução para IP do PE na subnet |
| Comunicação cross-região (BRS → EUS) | Sem resolução privada cross-VNet | VNet Links em todas as VNets garantem resolução consistente |
Zonas DNS do lab
Este lab cria sete zonas DNS privadas. As seis primeiras são as zonas de privatelink padrão do Azure para os serviços PaaS usados na série. A sétima é a zona interna do lab para registros A de VMs e serviços internos:
| Zona DNS | Serviço Azure | Uso na série |
|---|---|---|
privatelink.blob.core.windows.net |
Azure Blob Storage | Art. 08 — Storage com geo-replicação |
privatelink.database.windows.net |
Azure SQL Database | Workloads de dados do Spoke |
privatelink.azurecr.io |
Azure Container Registry | Art. 09 — AKS Multi-Região |
privatelink.vaultcore.azure.net |
Azure Key Vault | Segredos e certificados dos workloads |
privatelink.monitor.azure.com |
Azure Monitor | Art. 13 — Monitoramento do DR |
privatelink.ods.opinsights.azure.com |
Log Analytics | Art. 13 — Log Analytics workspace |
blog-castilho.internal |
Zona interna do lab | Registros A para VMs e serviços internos |
Cada zona é linkada às quatro VNets com registration_enabled = false — os registros são criados manualmente ou pelos Private Endpoints, não de forma automática pela VNet. Isso é intencional: o registro automático de VMs é útil mas pode gerar conflitos em ambientes com múltiplas VNets linkadas à mesma zona.
Arquitetura: zonas centralizadas no Hub
A estratégia de DNS privado multi-região no Azure adotada no lab é centralizar todas as zonas no Resource Group de rede do Hub primário (rg-blog-castilho-network-brazilsouth) e linkar cada zona às quatro VNets. Isso garante resolução DNS consistente independentemente de qual VNet originou a query.
| VNet | Região | Virtual Network Link |
|---|---|---|
| vnet-hub-blog-castilho-brazilsouth | Brazil South | link-hub-brazilsouth (em cada zona) |
| vnet-hub-blog-castilho-eastus | East US | link-hub-eastus (em cada zona) |
| vnet-spoke-blog-castilho-brazilsouth | Brazil South | link-spoke-brazilsouth (em cada zona) |
| vnet-spoke-blog-castilho-eastus | East US | link-spoke-eastus (em cada zona) |
Com essa configuração, uma VM no Spoke de East US que tenta resolver meu-storage.blob.core.windows.net via privatelink.blob.core.windows.net vai obter o IP privado do Private Endpoint — mesmo que o PE esteja no Spoke de Brazil South, desde que o registro A aponte para o IP correto.
Pré-requisitos
- Hub-Spoke Landing Zone implantada (Art. 02) — as quatro VNets existentes
- Terraform ≥ 1.5 e Azure CLI autenticado
- Storage Account de remote state configurado (bootstrap do Art. 02)
- Módulo
modules/private-dns-zonepresente emscripts/modules/
O módulo Terraform private-dns-zone
Para implementar DNS privado multi-região no Azure sem repetir o mesmo código Terraform sete vezes, usamos um módulo local que encapsula a criação da zona e os quatro Virtual Network Links. O módulo recebe o nome da zona e um mapa de VNets como entrada:
# modules/private-dns-zone/main.tf
resource "azurerm_private_dns_zone" "this" {
name = var.zone_name
resource_group_name = var.resource_group_name
tags = var.tags
}
resource "azurerm_private_dns_zone_virtual_network_link" "this" {
for_each = var.vnet_links
name = "link-${each.key}"
resource_group_name = var.resource_group_name
private_dns_zone_name = azurerm_private_dns_zone.this.name
virtual_network_id = each.value
registration_enabled = false
tags = var.tags
}
O for_each = var.vnet_links itera sobre o mapa de VNets e cria um link para cada uma. O nome do link usa o each.key — por exemplo, link-hub-brazilsouth, link-spoke-eastus. Assim, um único módulo cria a zona + 4 links com um único bloco module.
Passo 1 — Código Terraform da zona
O main.tf do recurso pdnsz-blog-castilho define os data sources para as quatro VNets, o mapa de links e chama o módulo com for_each para criar as sete zonas de DNS privado multi-região no Azure em paralelo:
data "azurerm_resource_group" "this" {
name = "rg-blog-castilho-network-brazilsouth"
}
data "azurerm_virtual_network" "hub_brazilsouth" {
name = "vnet-hub-blog-castilho-brazilsouth"
resource_group_name = "rg-blog-castilho-network-brazilsouth"
}
data "azurerm_virtual_network" "hub_eastus" {
name = "vnet-hub-blog-castilho-eastus"
resource_group_name = "rg-blog-castilho-network-eastus"
}
data "azurerm_virtual_network" "spoke_brazilsouth" {
name = "vnet-spoke-blog-castilho-brazilsouth"
resource_group_name = "rg-blog-castilho-network-brazilsouth"
}
data "azurerm_virtual_network" "spoke_eastus" {
name = "vnet-spoke-blog-castilho-eastus"
resource_group_name = "rg-blog-castilho-network-eastus"
}
locals {
vnet_links = {
hub-brazilsouth = data.azurerm_virtual_network.hub_brazilsouth.id
hub-eastus = data.azurerm_virtual_network.hub_eastus.id
spoke-brazilsouth = data.azurerm_virtual_network.spoke_brazilsouth.id
spoke-eastus = data.azurerm_virtual_network.spoke_eastus.id
}
zones = [
"privatelink.blob.core.windows.net",
"privatelink.database.windows.net",
"privatelink.azurecr.io",
"privatelink.vaultcore.azure.net",
"privatelink.monitor.azure.com",
"privatelink.ods.opinsights.azure.com",
"blog-castilho.internal",
]
}
module "dns_zones" {
source = "../../../modules/private-dns-zone"
for_each = toset(local.zones)
zone_name = each.value
resource_group_name = data.azurerm_resource_group.this.name
vnet_links = local.vnet_links
tags = var.tags
}
O for_each = toset(local.zones) cria uma instância do módulo para cada zona. O Terraform cria todas as sete zonas em paralelo, cada uma com seus quatro Virtual Network Links — totalizando 7 zonas + 28 links (7 × 4) em um único terraform apply.
Passo 2 — Executar o Terraform
export AZURE_SUBSCRIPTION_ID="<SUBSCRIPTION_ID>"
export TF_STATE_RG="rg-blog-castilho-tfstate"
export TF_STATE_SA="<storage-account-name>"
export TF_STATE_CONTAINER="tfstate"
cd scripts/art-06-dns-privado/pdnsz-blog-castilho
cat > backend.hcl <<EOF
resource_group_name = "$TF_STATE_RG"
storage_account_name = "$TF_STATE_SA"
container_name = "$TF_STATE_CONTAINER"
key = "pdnsz-blog-castilho.tfstate"
EOF
terraform init -backend-config=backend.hcl -reconfigure
terraform apply -var subscription_id="$AZURE_SUBSCRIPTION_ID"
O apply cria 35 recursos (7 zonas + 28 links) da solução de DNS privado multi-região no Azure e leva cerca de 3 a 5 minutos. A criação é rápida porque Private DNS Zones são recursos leves, sem necessidade de provisionamento de instância.
# Exemplo de output esperado:
Apply complete! Resources: 35 added, 0 changed, 0 destroyed.
# Recursos criados (exemplo para uma zona):
# module.dns_zones["privatelink.blob.core.windows.net"].azurerm_private_dns_zone.this
# module.dns_zones["privatelink.blob.core.windows.net"].azurerm_private_dns_zone_virtual_network_link.this["hub-brazilsouth"]
# module.dns_zones["privatelink.blob.core.windows.net"].azurerm_private_dns_zone_virtual_network_link.this["hub-eastus"]
# module.dns_zones["privatelink.blob.core.windows.net"].azurerm_private_dns_zone_virtual_network_link.this["spoke-brazilsouth"]
# module.dns_zones["privatelink.blob.core.windows.net"].azurerm_private_dns_zone_virtual_network_link.this["spoke-eastus"]
Passo 3 — Adicionar registros DNS
Após criar as zonas, você pode adicionar registros manualmente para serviços internos do lab. Os registros de Private Endpoint são criados automaticamente pelo Azure quando o PE é provisionado — mas para a zona interna blog-castilho.internal, os registros A precisam ser criados explicitamente:
# Exemplo: adicionar registro A para uma VM de gerenciamento
az network private-dns record-set a add-record \
--resource-group rg-blog-castilho-network-brazilsouth \
--zone-name blog-castilho.internal \
--record-set-name mgmt-brazilsouth \
--ipv4-address 10.0.0.200
# Verificar o registro
az network private-dns record-set a show \
--resource-group rg-blog-castilho-network-brazilsouth \
--zone-name blog-castilho.internal \
--name mgmt-brazilsouth
# Agora uma VM em qualquer VNet linkada resolve:
# mgmt-brazilsouth.blog-castilho.internal → 10.0.0.200
Verificar a configuração do DNS privado multi-região no Azure
# Listar todas as zonas DNS privadas no Resource Group
az network private-dns zone list \
--resource-group rg-blog-castilho-network-brazilsouth \
--query "[].{name:name, numberOfRecords:numberOfRecordSets}" \
--output table
# Exemplo de output esperado:
# Name NumberOfRecords
# ----------------------------------------- ---------------
# blog-castilho.internal 1
# privatelink.azurecr.io 1
# privatelink.blob.core.windows.net 1
# privatelink.database.windows.net 1
# privatelink.monitor.azure.com 1
# privatelink.ods.opinsights.azure.com 1
# privatelink.vaultcore.azure.net 1
# Verificar Virtual Network Links de uma zona
az network private-dns link vnet list \
--resource-group rg-blog-castilho-network-brazilsouth \
--zone-name "privatelink.blob.core.windows.net" \
--query "[].{name:name, vnet:virtualNetwork.id, status:provisioningState}" \
--output table
# Exemplo de output esperado:
# Name VNet (parcial) Status
# -------------------- -------------------------------------------- ---------
# link-hub-brazilsouth .../vnet-hub-blog-castilho-brazilsouth Succeeded
# link-hub-eastus .../vnet-hub-blog-castilho-eastus Succeeded
# link-spoke-brazilsouth .../vnet-spoke-blog-castilho-brazilsouth Succeeded
# link-spoke-eastus .../vnet-spoke-blog-castilho-eastus Succeeded
Troubleshooting
| Problema | Causa | Solução |
|---|---|---|
| VM resolve IP público mesmo com Private Endpoint | VNet não está linkada à zona DNS privada | Confirme que o VNet Link existe e está Succeeded para a VNet da VM |
ZoneAlreadyExists |
Zona criada anteriormente por outro processo | Importe a zona existente: terraform import e re-execute o apply |
Link com registration_enabled = true duplica registros |
Conflito entre registro automático e manual | Use registration_enabled = false e gerencie registros explicitamente |
Módulo não encontrado no terraform init |
Caminho relativo incorreto em source |
Verifique o caminho relativo de pdnsz-blog-castilho/ até modules/private-dns-zone/ — deve ser ../../../modules/private-dns-zone |
Resolução DNS falha para zona .internal |
Sufixo não reconhecido pelo DNS resolver da VNet | Zonas .internal são válidas no Azure Private DNS — confirme que a VNet está linkada |
Limpeza dos recursos
cd scripts/art-06-dns-privado/pdnsz-blog-castilho
terraform destroy -var subscription_id="$AZURE_SUBSCRIPTION_ID"
# Remove 35 recursos: 7 zonas + 28 links
Próximos passos
Com o DNS privado multi-região no Azure configurado, as zonas de privatelink estão prontas para receber os registros automáticos dos Private Endpoints criados nos próximos artigos. O Art. 07 aborda o Azure Site Recovery para proteger VMs contra falha de região, configurando replicação contínua de Brazil South para East US com Terraform.
- 📖 Art. 01: Planejamento de DR Azure e Landing Zone
- 📖 Art. 02: Hub-Spoke Landing Zone com Terraform
- 📖 Art. 03: Azure Firewall e NSGs na Landing Zone
- 📖 Art. 04: Azure Bastion na Landing Zone sem IP Público
- 📖 Art. 05: Azure Front Door e Traffic Manager para Failover
- ⚙️ Art. 06 (este): DNS Privado Multi-Região no Azure
- 🔒 Art. 07: Azure Site Recovery para VMs Multi-Região
- 🔒 Art. 08: Azure Storage com Geo-Replicação para DR
- 🔒 Art. 09: AKS Multi-Região com Failover no Azure
- 🔒 Art. 10: Velero no AKS para Backup e Restore Cross-Region
- 🔒 Art. 11: Runbooks de Failover no Azure Automation
- 🔒 Art. 12: Simular um DR no Azure sem Impacto em Produção
- 🔒 Art. 13: Monitoramento do DR no Azure com Azure Monitor
Interessado em saber mais sobre artigos relacionados ao Microsoft Azure CLIQUE AQUI
🚀 Vamos nos conectar?
Não perca nenhuma oportunidade! Cadastre-se nas minhas redes e no canal do YouTube para receber conteúdos de TI, Cloud, Azure, Kubernetes e DevOps em primeira mão.
Dica: No Facebook, todos os artigos do blog são publicados automaticamente. Vale a pena curtir!
💬 Dúvidas ou Problemas?
Com o intuito de ajudar a comunidade, caso você tenha dúvidas ou encontre problemas na execução dos comandos deste artigo, deixe um comentário abaixo. Responderei o mais breve possível!
Muito obrigado pela visita e até o próximo post!
Jefferson Castilho Especialista em Cloud & DevOps.Este guia técnico é exclusivo do Blog do Castilho. Explore nossa para mais conteúdos sobre IA e Cloud.


