Simular um DR no Azure sem Impacto em Produção

Simular um DR no Azure sem Impacto em Produção

Simular um DR no Azure sem Impacto em Produção

Simular um DR no Azure sem Impacto em Produção

Simular um DR no Azure sem impactar produção é o objetivo deste artigo. Um plano de DR que nunca foi testado não é um plano — é uma hipótese. O Azure Site Recovery oferece o Test Failover, um mecanismo que replica as VMs para uma rede isolada na região de destino sem interromper a replicação em andamento e sem afetar os usuários em produção. Este artigo executa um drill de DR completo no lab: inicia o Test Failover para todas as VMs replicadas, valida conectividade e integridade dos dados, mede o RTO e RPO reais com scripts PowerShell e faz o cleanup dos recursos de teste ao final. O resultado é um relatório com os números reais do seu ambiente.

Série: DR Azure e Landing Zone
  • 📖 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: 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 (este): Simular um DR no Azure sem Impacto em Produção
  • 🔒 Art. 13: Monitoramento do DR no Azure com Azure Monitor

Sumário

Test Failover vs. Failover real

O Azure Site Recovery distingue três modos de failover com impactos completamente diferentes:

Modo Impacto em produção Replicação continua? Uso
Test Failover Nenhum — VMs de teste em rede isolada Sim Drills periódicos, validação de RTO/RPO
Planned Failover VMs primárias são desligadas Não (replicação invertida) Manutenção planejada, migração de região
Unplanned Failover VMs primárias podem estar inacessíveis Não Desastre real, região primária indisponível

O Test Failover cria cópias das VMs replicadas em uma VNet de teste isolada (parte do processo de simular um DR no Azure) — separada da VNet de produção da região secundária — usando o último recovery point disponível. As VMs de produção em Brazil South continuam rodando normalmente e a replicação não é interrompida. Após o drill, um comando de cleanup remove as VMs de teste e libera os recursos.

A frequência recomendada para simular um DR no Azure é pelo menos uma vez por ano pela Microsoft, mas para ambientes críticos o recomendado é trimestral. Cada drill deve gerar um relatório documentando o RTO medido, o RPO medido e eventuais problemas encontrados — que devem ser corrigidos antes do próximo drill.

Checklist pré-drill

  • Comunicar o drill para as equipes relevantes (mesmo sem impacto, o Azure Monitor pode gerar alertas)
  • Verificar que a replicação ASR está com status Healthy para todas as VMs
  • Confirmar que o Storage Account tem geo-replication ativa (GeoReplicationStatus: Live)
  • Preparar uma VNet de teste isolada em East US (ou usar a VNet de spoke com uma subnet separada)
  • Ter os scripts 01 a 05 disponíveis e as credenciais configuradas no .env
  • Registrar o horário de início para cálculo do RTO

Pré-requisitos

  • Art. 07 deployado — RSV rsv-blog-castilho-eastus com VMs replicadas e status Healthy
  • Art. 08 deployado — Storage Account stblogcastilhobrazil com RA-GZRS ativo
  • Módulo Az.RecoveryServices instalado (Install-Module Az.RecoveryServices)
  • Azure CLI ou PowerShell autenticado com permissão de Contributor no RSV
Segurança: Os comandos deste artigo utilizam variáveis de ambiente para credenciais. Nunca insira IDs de subscription, senhas ou chaves diretamente nos comandos. Use um arquivo .env local (não versionado) ou o Azure Key Vault para armazenar segredos.

Passo 1 — Iniciar o Test Failover

O script 01-start-test-failover.ps1 é o ponto de entrada para simular um DR no Azure: conecta ao RSV, obtém todos os itens protegidos no container de Brazil South e dispara o Test Failover em paralelo para todas as VMs. Diferente do Planned Failover, aqui os jobs são criados de forma assíncrona e monitorados em batch:

# Registrar horário de início do drill
$DrillStart = Get-Date
Write-Output "=== DRILL INICIADO — $($DrillStart.ToString('yyyy-MM-dd HH:mm:ss')) ==="

$vault = Get-AzRecoveryServicesVault `
    -ResourceGroupName "rg-blog-castilho-network-eastus" `
    -Name "rsv-blog-castilho-eastus"
Set-AzRecoveryServicesAsrVaultContext -Vault $vault

$fabric    = Get-AzRecoveryServicesAsrFabric -Name "fabric-brazilsouth"
$container = Get-AzRecoveryServicesAsrProtectionContainer `
    -Fabric $fabric -Name "container-brazilsouth"

$protectedItems = Get-AzRecoveryServicesAsrReplicationProtectedItem `
    -ProtectionContainer $container

$jobs = @()
foreach ($item in $protectedItems) {
    Write-Output "Test Failover: $($item.FriendlyName)"
    $job = Start-AzRecoveryServicesAsrTestFailoverJob `
        -ReplicationProtectedItem $item `
        -Direction PrimaryToRecovery
    $jobs += [pscustomobject]@{ VM = $item.FriendlyName; Job = $job }
    Write-Output "  Job iniciado: $($job.Name)"
}

# Aguardar todos em paralelo
foreach ($entry in $jobs) {
    do {
        Start-Sleep -Seconds 30
        $j = Get-AzRecoveryServicesAsrJob -Job $entry.Job
        Write-Output "  $($entry.VM): $($j.State)"
    } while ($j.State -notin "Succeeded", "Failed", "Cancelled")
}

Write-Output ""
Write-Output "Test Failover concluído — VMs de teste rodando em East US (rede isolada)"

O parâmetro -TestNetworkId (opcional) especifica a VNet de teste isolada. Se omitido, o ASR usa uma VNet temporária criada automaticamente. Para um drill mais realista, passe o ID de uma VNet de teste pré-criada em East US que simule o ambiente de produção:

># Obter ID da VNet de teste (criada manualmente ou via Terraform)
TEST_VNET_ID=$(az network vnet show \
  --resource-group rg-blog-castilho-network-eastus \
  --name vnet-dr-test-eastus \
  --query id -o tsv)

# Passar o ID para o script
./01-start-test-failover.ps1 -TestNetworkId "$TEST_VNET_ID"

Passo 2 — Validar conectividade

Com as VMs de teste rodando, o 02-validate-connectivity.ps1 verifica o estado dos componentes principais da infraestrutura de DR na região East US. Cada verificação retorna OK ou FALHA e gera um resumo no final:

>Write-Output "=== VALIDAÇÃO DE CONECTIVIDADE — $(Get-Date -Format 'HH:mm:ss') ==="

$resultados = @()

function Test-AzResource {
    param([string]$Nome, [scriptblock]$Teste)
    try {
        $ok = & $Teste
        $resultados += [pscustomobject]@{
            Componente = $Nome
            Status     = if ($ok) { "OK" } else { "FALHA" }
        }
        Write-Output "  [$(if ($ok) { 'OK  ' } else { 'FAIL' })] $Nome"
    } catch {
        $resultados += [pscustomobject]@{ Componente = $Nome; Status = "ERRO" }
        Write-Output "  [ERRO] $Nome`: $_"
    }
}

Test-AzResource "AKS East US — API server" {
    $c = Get-AzAksCluster `
        -ResourceGroupName "rg-blog-castilho-workload-eastus" `
        -Name "aks-blog-castilho-eastus"
    $c.ProvisioningState -eq "Succeeded"
}

Test-AzResource "Storage Account — geo-replication" {
    $s = Get-AzStorageAccount `
        -ResourceGroupName "rg-blog-castilho-workload-brazilsouth" `
        -Name "stblogcastilhobrazil"
    ($s | Get-AzStorageAccountGeoReplicationStats).GeoReplicationStatus -eq "Live"
}

Test-AzResource "Traffic Manager — endpoint East US" {
    $ep = Get-AzTrafficManagerEndpoint `
        -ResourceGroupName "rg-blog-castilho-workload-brazilsouth" `
        -ProfileName "tm-blog-castilho" `
        -Type AzureEndpoints `
        -Name "endpoint-eastus"
    $ep.EndpointStatus -eq "Enabled"
}

Test-AzResource "Azure Firewall East US — provisionado" {
    $afw = Get-AzFirewall `
        -ResourceGroupName "rg-blog-castilho-network-eastus" `
        -Name "afw-blog-castilho-eastus"
    $afw.ProvisioningState -eq "Succeeded"
}

$resultados | Format-Table -AutoSize

A verificação do Firewall confirma que o afw-blog-castilho-eastus está provisionado e as regras de rede para o AKS (TCP 9000, UDP 1194, UDP 123 e o FQDN tag AzureKubernetesService) estão aplicadas — sem isso, os pods do AKS não conseguem alcançar a API do Azure para operações de autoscaling e certificados. A verificação do Traffic Manager confirma que o endpoint East US está habilitado e pronto para receber tráfego caso o endpoint primário seja desativado.

Passo 3 — Validar integridade dos dados

O 03-validate-data-integrity.ps1 verifica duas fontes de dados críticas: o lag de geo-replicação do Storage Account RA-GZRS e a idade dos Recovery Points do ASR. Ambos determinam o RPO real do ambiente:

>param([int]$MaxSyncLagMinutes = 5)

Write-Output "--- Storage Geo-Replication ---"
$storage = Get-AzStorageAccount `
    -ResourceGroupName "rg-blog-castilho-workload-brazilsouth" `
    -Name "stblogcastilhobrazil"
$stats = $storage | Get-AzStorageAccountGeoReplicationStats

$lagMinutes = [int]((Get-Date) - $stats.LastSyncTime.ToUniversalTime()).TotalMinutes

Write-Output "  Status      : $($stats.GeoReplicationStatus)"
Write-Output "  Último sync : $($stats.LastSyncTime)"
Write-Output "  Lag (min)   : $lagMinutes"

if ($lagMinutes -le $MaxSyncLagMinutes) {
    Write-Output "  Resultado   : OK (dentro do RPO de $MaxSyncLagMinutes min)"
} else {
    Write-Warning "  Resultado   : ALERTA — lag excede RPO de $MaxSyncLagMinutes min"
}

Write-Output ""
Write-Output "--- ASR — Recovery Points ---"
$vault     = Get-AzRecoveryServicesVault -ResourceGroupName "rg-blog-castilho-network-eastus" -Name "rsv-blog-castilho-eastus"
Set-AzRecoveryServicesAsrVaultContext -Vault $vault
$fabric    = Get-AzRecoveryServicesAsrFabric -Name "fabric-brazilsouth"
$container = Get-AzRecoveryServicesAsrProtectionContainer -Fabric $fabric -Name "container-brazilsouth"
$items     = Get-AzRecoveryServicesAsrReplicationProtectedItem -ProtectionContainer $container

foreach ($item in $items) {
    $rp    = Get-AzRecoveryServicesAsrRecoveryPoint -ReplicationProtectedItem $item | Select-Object -Last 1
    $rpAge = [int]((Get-Date) - $rp.RecoveryPointTime.ToUniversalTime()).TotalMinutes
    Write-Output "  $($item.FriendlyName): RP $($rp.RecoveryPointTime) (${rpAge}min) — $(if ($rpAge -le $MaxSyncLagMinutes) { 'OK' } else { 'ALERTA' })"
}

O GeoReplicationStatus: Live do Storage Account indica que a réplica em East US está sincronizada em tempo real via RA-GZRS. O LastSyncTime mostra o timestamp do último dado confirmado na réplica — qualquer dado gravado após esse momento pode não estar disponível na região secundária em caso de falha catastrófica da região primária. Para o RPO de 5 minutos definido no Art. 01, o lag deve ser consistentemente abaixo desse valor.

Passo 4 — Medir RTO e RPO reais

O 04-measure-rto-rpo.ps1 recebe os horários de início e fim do drill e gera um relatório formatado com os valores de RTO e RPO medidos, comparados com os objetivos definidos no Art. 01:

># Executar com os horários reais do drill
./04-measure-rto-rpo.ps1 `
    -StartTime "2026-06-03 10:00:00" `
    -EndTime "2026-06-03 10:34:00" `
    -RtoObjetivoMin 60 `
    -RpoObjetivoMin 5

O script calcula:

  • RTO medido: diferença entre -StartTime e -EndTime — representa o tempo desde o início do incidente até os serviços estarem disponíveis na região secundária
  • RPO medido: obtido diretamente do LastSyncTime da Storage Account no momento da execução — representa o quanto de dados poderia ser perdido se a falha tivesse ocorrido naquele instante

Exemplo de saída do relatório:

>╔══════════════════════════════════════════════════╗
║         DR DRILL REPORT — blog-castilho          ║
╠══════════════════════════════════════════════════╣
║ Data/Hora Início : 2026-06-03 10:00:00
║ Data/Hora Fim    : 2026-06-03 10:34:00
╠══════════════════════════════════════════════════╣
║ RTO Objetivo : 60 minutos
║ RTO Medido   : 34 minutos
║ RTO Status   : DENTRO DO OBJETIVO
╠══════════════════════════════════════════════════╣
║ RPO Objetivo : 5 minutos
║ RPO Medido   : 2.3 minutos
║ RPO Status   : DENTRO DO OBJETIVO
╚══════════════════════════════════════════════════╝
Relatório salvo em: dr-drill-report-20260603-1034.txt

O RTO de 34 minutos neste exemplo é dominado pelo tempo do Planned Failover do ASR (15–30 min por VM) mais o scale-out do AKS (~5 min). Se o RTO medido exceder o objetivo, os pontos de melhoria mais comuns são: reduzir o número de VMs replicadas pelo ASR, usar instâncias pré-aquecidas na região secundária (warm standby) ou substituir VMs por containers no AKS que sobem em segundos.

Passo 5 — Cleanup do Test Failover

O cleanup é obrigatório após o drill. O 05-cleanup-test-failover.ps1 remove as VMs de teste criadas pelo ASR e retoma a replicação normal. Sem o cleanup, as VMs de teste continuam consumindo recursos (e custos) em East US:

>Write-Output "=== CLEANUP DO TEST FAILOVER — $(Get-Date -Format 'HH:mm:ss') ==="

$vault = Get-AzRecoveryServicesVault `
    -ResourceGroupName "rg-blog-castilho-network-eastus" `
    -Name "rsv-blog-castilho-eastus"
Set-AzRecoveryServicesAsrVaultContext -Vault $vault

$fabric    = Get-AzRecoveryServicesAsrFabric -Name "fabric-brazilsouth"
$container = Get-AzRecoveryServicesAsrProtectionContainer `
    -Fabric $fabric -Name "container-brazilsouth"
$items     = Get-AzRecoveryServicesAsrReplicationProtectedItem `
    -ProtectionContainer $container

foreach ($item in $items) {
    Write-Output "Removendo Test Failover: $($item.FriendlyName)"
    $job = Start-AzRecoveryServicesAsrTestFailoverCleanupJob `
        -ReplicationProtectedItem $item `
        -Comment "Cleanup pós DR Drill $(Get-Date -Format 'yyyy-MM-dd')"

    do {
        Start-Sleep -Seconds 20
        $job = Get-AzRecoveryServicesAsrJob -Job $job
        Write-Output "  Status: $($job.State)"
    } while ($job.State -notin "Succeeded", "Failed", "Cancelled")

    Write-Output "  $($item.FriendlyName): cleanup $($job.State)"
}

Write-Output ""
Write-Output "Cleanup concluído — ambiente de produção não foi afetado"

O parâmetro -Comment registra uma nota no histórico do job do ASR — útil para auditoria e relatórios de compliance. Após o cleanup, verifique no portal que o estado de replicação voltou a Healthy antes de encerrar o drill oficialmente.

Interpretando os resultados

Resultado O que significa Ação
RTO dentro do objetivo O processo de failover é suficientemente rápido para o SLA definido Documentar e agendar próximo drill
RTO excedido O failover demora mais que o acordado com o negócio Identificar o gargalo (ASR, AKS scale-out, DNS TTL) e otimizar
RPO dentro do objetivo A replicação está sincronizada dentro da janela aceitável de perda de dados Manter a configuração atual
RPO excedido (Storage lag alto) A geo-replicação do Storage está com lag acima do esperado Verificar throttling na conta de storage, largura de banda disponível e alertas do Art. 13
Componente FALHA na validação Um serviço crítico não está acessível na região secundária Investigar antes de considerar o DR válido — o failover real falharia nesse ponto

O relatório do drill deve ser arquivado e revisado pelo time. Qualquer item com status FALHA ou ALERTA deve ter um plano de ação com prazo antes do próximo drill. Drills frequentes constroem confiança no processo e revelam problemas antes que um incidente real os exponha.

Troubleshooting

Problema Causa Solução
Test Failover falha com ReplicationNotHealthy A replicação ASR está com erro antes do drill Resolver o problema de replicação primeiro. Ver: RSV → Itens Replicados → VM → Replication Health
GeoReplicationStatus: Bootstrap no Storage A geo-replicação ainda está sendo inicializada Aguardar até o status ficar Live. Pode levar horas na primeira configuração dependendo do volume de dados
VMs de teste criadas mas sem IP acessível A VNet de teste não tem conectividade com o Bastion ou VPN Usar o Bastion da região East US para acessar as VMs de teste (Art. 04). O Bastion acessa qualquer VNet peerada na região
Cleanup falha com JobAlreadyRunning Outro job está rodando no ASR para o mesmo item Aguardar o job em andamento completar e tentar novamente. Ver jobs ativos: Get-AzRecoveryServicesAsrJob -State Running
RTO muito alto por causa do ASR Muitas VMs em failover sequencial O script processa VMs em paralelo (jobs assíncronos). Se ainda for lento, considerar reduzir o número de VMs protegidas pelo ASR e mover workloads stateless para o AKS
Velero BSL Unavailable — TLS handshake timeout para o Storage Account DNS split-horizon ausente: a zona privatelink.blob.core.windows.net tinha um único A record apontando para o Private Endpoint da região errada. Pods do BrazilSouth tentavam conectar no PEP do EastUS (10.3.3.4) em vez do PEP local (10.2.3.4) Criar uma zona DNS privada por região. A zona BRS deve ter A record → IP do PEP BRS; a zona EastUS deve ter A record → IP do PEP EastUS. Linkar cada zona somente aos VNets da própria região (hub + spoke). Padrão documentado no Art. 06

Próximos passos

Com o exercício de simular um DR no Azure documentado e os RTO/RPO reais em mãos, o Art. 13 fecha a série com a camada de observabilidade contínua do DR: Log Analytics Workspaces em ambas as regiões, alertas críticos para replicação ASR não saudável e lag de storage acima do RPO, além de Workbooks consolidando visibilidade de todos os componentes em um único painel — para que você saiba o estado do DR em tempo real, não apenas durante os drills.

Série: DR Azure e Landing Zone
  • 📖 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: 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 (este): 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.

 

Deixe uma resposta

Rolar para cima

Descubra mais sobre Blog do Castilho - Tecnologia | FinOps | DevOps | Cloud

Assine agora mesmo para continuar lendo e ter acesso ao arquivo completo.

Continue reading