Azure Storage com Geo-Replicação para DR

Neste artigo você vai configurar o Azure Storage com geo-replicação para DR: uma Storage Account primária com RA-GZRS em Brazil South — que replica dados automaticamente para East US e permite leitura do endpoint secundário mesmo durante uma interrupção — e uma Storage Account de cache em East US para o Azure Site Recovery do Art. 07. Os recursos são criados com Terraform, com Private Endpoints em ambas as regiões e acesso de rede público desabilitado. Na sequência, você usa PowerShell para verificar o lag de replicação e executar um failover manual controlado. O azure storage geo-replicação dr é a camada de dados que sustenta o ASR, o Velero e as aplicações desta série.
- 📖 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: DNS Privado Multi-Região no Azure
- 📖 Art. 07: Azure Site Recovery para VMs Multi-Região
- ⚙️ Art. 08 (este): 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
- Tipos de replicação do Azure Storage
- Arquitetura do lab
- Pré-requisitos
- Passo 1 — Terraform: Storage Account primária (RA-GZRS)
- Passo 2 — Terraform: Private Endpoints
- Passo 3 — Terraform: Storage Account de cache (LRS)
- Passo 4 — Deploy com Terraform
- Passo 5 — Verificar geo-replicação e Last Sync Time
- Passo 6 — Leitura do endpoint secundário
- Passo 7 — Failover manual do Storage Account
- Troubleshooting
- Limpeza dos recursos
- Próximos passos
Tipos de replicação do Azure Storage
O Azure Storage oferece seis opções de replicação que diferem em número de cópias, distribuição geográfica e capacidade de leitura na região secundária. Para DR multi-região, apenas GRS, RA-GRS, GZRS e RA-GZRS replicam dados fora da região primária:
| SKU | Cópias | Zonas (primária) | Regiões | Leitura secundária | Custo |
|---|---|---|---|---|---|
| LRS | 3 | 1 | 1 | Não | $ |
| ZRS | 3 | 3 | 1 | Não | $$ |
| GRS | 6 | 1 | 2 | Não (failover necessário) | $$ |
| RA-GRS | 6 | 1 | 2 | Sim (endpoint secundário) | $$$ |
| GZRS | 6 | 3 | 2 | Não (failover necessário) | $$$ |
| RA-GZRS | 6 | 3 | 2 | Sim (endpoint secundário) | $$$$ |
O azure storage geo-replicação dr usa RA-GZRS na Storage Account primária: 3 cópias em zonas de disponibilidade diferentes em Brazil South (proteção contra falha de zona) + 3 cópias em East US (proteção contra falha de região) + endpoint secundário de leitura disponível mesmo enquanto Brazil South estiver ativo. A Storage Account de cache do ASR usa LRS — ela é temporária e não precisa sobreviver à falha de região.
Um conceito central para o azure storage geo-replicação dr é o Last Sync Time: o timestamp do último dado confirmado como replicado para a região secundária. A diferença entre o momento atual e o Last Sync Time é o RPO real do Storage — quanto de dado você pode perder se um failover ocorrer agora. Com RA-GZRS em condições normais, esse lag fica abaixo de 15 minutos.
Arquitetura do lab
| Recurso | Nome | Região | Resource Group | Tipo |
|---|---|---|---|---|
| Storage primária | stblogcastilhobrazil | Brazil South | rg-blog-castilho-workload-brazilsouth | Standard RA-GZRS |
| PE blob (BRS) | pep-blob-st-blog-castilho-brazilsouth | Brazil South | rg-blog-castilho-workload-brazilsouth | Private Endpoint |
| PE blob (EUS) | pep-blob-st-blog-castilho-eastus | East US | rg-blog-castilho-workload-eastus | Private Endpoint |
| Storage cache ASR | stblogcastilhocache | East US | rg-blog-castilho-network-eastus | Standard LRS |
O acesso público à Storage primária está desabilitado (public_network_access_enabled = false). Toda operação passa pelos Private Endpoints nas subnets snet-data das Spoke VNets, com resolução DNS via a zona privatelink.blob.core.windows.net criada no Art. 06. O Private Endpoint em East US permite que a réplica secundária seja acessada de VMs nessa região sem tráfego de internet — essencial para validar o DR antes de concluir o failover.
Pré-requisitos
- Arts. 02-06 deployados — as quatro VNets, subnets
snet-datae zona DNSprivatelink.blob.core.windows.netexistentes - Terraform ≥ 1.5 e Azure CLI autenticado
- Storage Account de remote state configurado (bootstrap)
- Módulo Az do PowerShell:
Install-Module -Name Az.Storage -AllowClobber -Scope CurrentUser
Passo 1 — Terraform: Storage Account primária (RA-GZRS)
A Storage Account primária é criada no Resource Group de workload de Brazil South com replicação RA-GZRS e acesso público desabilitado. Três containers são criados: data para dados de aplicação, backups para o Velero (Art. 10) e asr-cache reservado para o Azure Site Recovery:
data "azurerm_resource_group" "workload_brazilsouth" {
name = "rg-blog-castilho-workload-brazilsouth"
}
data "azurerm_subnet" "data_brazilsouth" {
name = "snet-data"
virtual_network_name = "vnet-spoke-blog-castilho-brazilsouth"
resource_group_name = "rg-blog-castilho-network-brazilsouth"
}
data "azurerm_private_dns_zone" "blob" {
name = "privatelink.blob.core.windows.net"
resource_group_name = "rg-blog-castilho-network-brazilsouth"
}
resource "azurerm_storage_account" "this" {
name = "stblogcastilhobrazil"
resource_group_name = data.azurerm_resource_group.workload_brazilsouth.name
location = data.azurerm_resource_group.workload_brazilsouth.location
account_tier = "Standard"
account_replication_type = var.replication_type # "RAGZRS" por padrão
min_tls_version = "TLS1_2"
public_network_access_enabled = false
tags = var.tags
}
resource "azurerm_storage_container" "data" {
name = "data"
storage_account_id = azurerm_storage_account.this.id
container_access_type = "private"
}
resource "azurerm_storage_container" "backups" {
name = "backups"
storage_account_id = azurerm_storage_account.this.id
container_access_type = "private"
}
resource "azurerm_storage_container" "asr_cache" {
name = "asr-cache"
storage_account_id = azurerm_storage_account.this.id
container_access_type = "private"
}
O parâmetro account_replication_type recebe o valor da variável replication_type, que tem default RAGZRS. Isso permite testar com GRS ou LRS passando -var replication_type=GRS sem alterar o código.
Passo 2 — Terraform: Private Endpoints
Dois Private Endpoints são criados para a Storage primária: um em Brazil South (na subnet de dados do Spoke) e um em East US (para acesso ao endpoint secundário durante o DR). Ambos são associados à mesma zona DNS privatelink.blob.core.windows.net criada no Art. 06:
# Private Endpoint em Brazil South
resource "azurerm_private_endpoint" "blob_brazilsouth" {
name = "pep-blob-st-blog-castilho-brazilsouth"
resource_group_name = data.azurerm_resource_group.workload_brazilsouth.name
location = data.azurerm_resource_group.workload_brazilsouth.location
subnet_id = data.azurerm_subnet.data_brazilsouth.id
tags = var.tags
private_service_connection {
name = "psc-blob-brazilsouth"
private_connection_resource_id = azurerm_storage_account.this.id
subresource_names = ["blob"]
is_manual_connection = false
}
private_dns_zone_group {
name = "dns-group-blob-brazilsouth"
private_dns_zone_ids = [data.azurerm_private_dns_zone.blob.id]
}
}
# Private Endpoint em East US (acesso ao endpoint secundário)
resource "azurerm_private_endpoint" "blob_eastus" {
name = "pep-blob-st-blog-castilho-eastus"
resource_group_name = "rg-blog-castilho-workload-eastus"
location = "eastus"
subnet_id = data.azurerm_subnet.data_eastus.id
tags = var.tags
private_service_connection {
name = "psc-blob-eastus"
private_connection_resource_id = azurerm_storage_account.this.id
subresource_names = ["blob"]
is_manual_connection = false
}
private_dns_zone_group {
name = "dns-group-blob-eastus"
private_dns_zone_ids = [data.azurerm_private_dns_zone.blob.id]
}
}
Ao criar o Private Endpoint e associá-lo à DNS zone, o Terraform adiciona automaticamente um registro A na zona privatelink.blob.core.windows.net com o IP privado do endpoint. Uma VM em qualquer VNet linkada à zona vai resolver stblogcastilhobrazil.blob.core.windows.net para o IP privado correspondente — sem tráfego de internet.
Passo 3 — Terraform: Storage Account de cache (LRS)
A Storage Account de cache é simples: LRS em East US, sem Private Endpoint, criada no Resource Group de rede. Ela serve exclusivamente como buffer temporário do Azure Site Recovery durante a replicação contínua das VMs. Dados escritos aqui são transientes — o ASR grava e deleta automaticamente:
data "azurerm_resource_group" "this" {
name = "rg-blog-castilho-network-eastus"
}
resource "azurerm_storage_account" "this" {
name = "stblogcastilhocache"
resource_group_name = data.azurerm_resource_group.this.name
location = data.azurerm_resource_group.this.location
account_tier = "Standard"
account_replication_type = "LRS"
min_tls_version = "TLS1_2"
tags = var.tags
}
O acesso público está habilitado nesta conta porque o agente de mobilidade do ASR, executando nas VMs de Brazil South, precisa escrever diretamente no endpoint de blob. Em produção, avalie restringir o acesso por IP ou service endpoint da VNet Spoke de origem.
Passo 4 — Deploy com Terraform
# Deploy somente do Art. 08 (Storage primária + Private Endpoints + cache)
cd scripts/
bash deploy-infra.sh art-08
# Output esperado:
# ═══ ONDA: Art-08 — Storage Accounts ══════════════════════
# [HH:MM:SS] START st-blog-castilho-primary
# [HH:MM:SS] START st-blog-castilho-cache
# [HH:MM:SS] OK st-blog-castilho-cache
# [HH:MM:SS] OK st-blog-castilho-primary
# Verificar as Storage Accounts criadas
az storage account list \
--query "[?contains(name,'blogcastilho')].{name:name, kind:kind, replication:sku.name, location:location}" \
--output table
# Saída esperada:
# Name Kind Replication Location
# --------------------- -------- ----------- -----------
# stblogcastilhobrazil StorageV2 Standard_RAGZRS brazilsouth
# stblogcastilhocache StorageV2 Standard_LRS eastus
Passo 5 — Verificar geo-replicação e Last Sync Time
Use o script check-replication-lag.ps1 para verificar o status do azure storage geo-replicação dr e o Last Sync Time da Storage Account primária. O Last Sync Time indica o ponto até o qual os dados estão garantidamente na região secundária:
./check-replication-lag.ps1
# Exemplo de output (logo após o deploy — replicação ainda sincronizando):
# Storage Account : stblogcastilhobrazil
# Replicação : Standard_RAGZRS
# Status Geo-Rep : Bootstrap
# Último Sync (UTC):
# Lag aproximado : N/A
# Após alguns minutos (sincronização inicial concluída):
# Storage Account : stblogcastilhobrazil
# Replicação : Standard_RAGZRS
# Status Geo-Rep : Live
# Último Sync (UTC): 2026-06-03 15:28:42
# Lag aproximado : 3 minutos
O status Bootstrap é normal logo após a criação — o Azure está executando a sincronização inicial de todos os dados para East US. O status muda para Live quando a sincronização contínua entra em operação. A partir daí, o Last Sync Time é atualizado a cada poucos minutos.
Você também pode verificar via CLI sem precisar do PowerShell:
az storage account show \
--name stblogcastilhobrazil \
--resource-group rg-blog-castilho-workload-brazilsouth \
--query "{replication:sku.name, geoStatus:geoReplicationStats.status, lastSync:geoReplicationStats.lastSyncTime}" \
--output table
Passo 6 — Leitura do endpoint secundário
Com RA-GZRS, o endpoint secundário de leitura fica disponível sem precisar de failover. O endpoint segue o padrão <nome>-secondary.blob.core.windows.net. Para acessá-lo via PowerShell:
# Obter os endpoints da Storage Account
$storage = Get-AzStorageAccount `
-ResourceGroupName "rg-blog-castilho-workload-brazilsouth" `
-Name "stblogcastilhobrazil"
Write-Host "Endpoint Primário : $($storage.PrimaryEndpoints.Blob)"
Write-Host "Endpoint Secundário: $($storage.SecondaryEndpoints.Blob)"
# Endpoint Primário : https://stblogcastilhobrazil.blob.core.windows.net/
# Endpoint Secundário: https://stblogcastilhobrazil-secondary.blob.core.windows.net/
# Criar contexto de leitura usando o endpoint secundário (somente leitura)
$ctx = New-AzStorageContext `
-StorageAccountName "stblogcastilhobrazil" `
-UseConnectedAccount `
-BlobServiceEndpoint $storage.SecondaryEndpoints.Blob
# Listar blobs via endpoint secundário
Get-AzStorageBlob -Container "data" -Context $ctx | Select-Object Name, LastModified
No azure storage geo-replicação dr, o endpoint secundário é somente leitura — tentativas de escrita retornam erro 403. Isso é intencional: escrever no secundário diretamente conflitaria com a replicação unidirecional. A leitura do secundário é útil para analytics e relatórios que não precisam de dados em tempo real, aliviando a carga no primário.
Passo 7 — Failover manual do Storage Account
O failover manual do Storage Account promove East US a região primária. O processo é irreversível por pelo menos 1 hora e aceita apenas dados já replicados (até o Last Sync Time). Todo dado escrito após o último sync é perdido — por isso é essencial verificar o lag antes de executar:
# 1. Verificar Last Sync Time antes do failover
./check-replication-lag.ps1
# Confirme que o status é "Live" e o lag é aceitável para seu RTO
# 2. Executar o failover manual
./test-storage-failover.ps1
# === Estado ANTES do Failover ===
# Status de Geo-Replicação : Live
# Último Sync : 2026-06-03 15:28:42
# Endpoint Primário : https://stblogcastilhobrazil.blob.core.windows.net/
# Endpoint Secundário : https://stblogcastilhobrazil-secondary.blob.core.windows.net/
#
# Confirmar failover manual? Este processo pode levar minutos e é irreversível por 1h (s/n): s
# Iniciando failover...
# Aguardando conclusão do failover...
# Status: unavailable
# Status: available
#
# === Estado APÓS o Failover ===
# Região Primária : eastus
# Endpoint Primário: https://stblogcastilhobrazil.blob.core.windows.net/
# Replicação atual : Standard_LRS
Observe que após o failover a replicação muda de Standard_RAGZRS para Standard_LRS: East US vira a única região primária sem redundância geográfica. Para restaurar a geo-replicação, você precisa reconfigurar o SKU para RAGZRS manualmente — o Azure não faz isso automaticamente. Também por isso, o failover do Storage Account é considerado uma ação de último recurso, não um teste de rotina. Para testes de DR, use o Test Failover do ASR (Art. 07) ou valide via leitura do endpoint secundário sem promover failover.
Troubleshooting
| Problema | Causa | Solução |
|---|---|---|
AuthorizationFailure ao acessar blob via Private Endpoint | IAM não configurado — acesso público desabilitado requer RBAC | Atribuir role Storage Blob Data Contributor ao identidade que acessa a conta |
| VM não consegue resolver o FQDN da Storage Account | VNet não linkada à zona privatelink.blob.core.windows.net | Verificar Virtual Network Links no Art. 06 — a VNet da VM deve estar linkada |
Status de geo-replicação preso em Bootstrap | Sincronização inicial ainda em andamento (normal para SAs novas) | Aguardar — pode levar minutos a horas dependendo do volume de dados |
Failover falha com StorageAccountIsNotGeoRedundant | Storage Account já está em LRS (pós-failover ou configuração incorreta) | Verificar o SKU atual. Após failover, é necessário reconfigurar para GRS/RAGZRS manualmente |
Deploy paralelo dos dois Storage Accounts falha com Plugin did not respond | Race condition na cache de plugins do Terraform em deploys paralelos | Reexecutar o deploy — erro transiente. Ou executar as duas pastas sequencialmente |
| Escrita no endpoint secundário retorna 403 | Endpoint -secondary é somente leitura por design | Normal — use o endpoint primário para escrita. O secundário serve apenas para leitura |
Limpeza dos recursos
# Destruir Storage primária (com Private Endpoints)
cd scripts/art-08-storage-replication/st-blog-castilho-primary
terraform destroy -var subscription_id="$AZURE_SUBSCRIPTION_ID"
# Remove: Storage Account, 3 containers, 2 Private Endpoints, registros DNS automáticos
# Destruir Storage de cache
cd ../st-blog-castilho-cache
terraform destroy -var subscription_id="$AZURE_SUBSCRIPTION_ID"
# Remove: Storage Account (stblogcastilhocache)
Próximos passos
Com o azure storage geo-replicação dr e os Private Endpoints configurados, a camada de dados do lab de DR está completa. O Art. 09 avança para a camada de containers: AKS em multi-região com Azure Container Registry geo-replicado, Azure CNI e estratégia active-passive com failover via Traffic Manager — usando como base a Landing Zone Hub-Spoke e o DNS privado já configurados nesta série.
- 📖 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: DNS Privado Multi-Região no Azure
- 📖 Art. 07: Azure Site Recovery para VMs Multi-Região
- ⚙️ Art. 08 (este): 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.


