Backups e recovery: testando sua estratégia de desastre

1. Fundamentos de uma Estratégia de Desastre

Uma estratégia de desastre robusta começa com dois conceitos fundamentais: RPO (Recovery Point Objective) e RTO (Recovery Time Objective). O RPO define a quantidade máxima de dados que você pode perder medida em tempo — se seu RPO é de 4 horas, você pode perder no máximo 4 horas de dados. O RTO define o tempo máximo aceitável para restaurar os serviços após um desastre.

É crucial entender a diferença entre backup, replicação e disaster recovery. Backup é a cópia dos dados para recuperação futura. Replicação mantém cópias sincronizadas em tempo real ou quase real. Disaster recovery é o conjunto completo de processos, políticas e ferramentas para recuperar operações após um desastre.

Os desastres se classificam em três categorias principais:
- Falhas lógicas: corrupção de dados, exclusão acidental, ataques ransomware
- Falhas físicas: falha de disco, queda de energia, dano a hardware
- Falhas catastróficas: incêndio, inundação, desastre natural que afeta todo o datacenter

2. Tipos de Backup e Suas Aplicações Práticas

Backup completo, incremental e diferencial

O backup completo copia todos os dados selecionados. O incremental copia apenas dados alterados desde o último backup (completo ou incremental). O diferencial copia dados alterados desde o último backup completo.

Exemplo de trade-offs:

Cenário: 100 GB de dados, 5 GB alterados diariamente

Backup completo diário: 100 GB/dia → 700 GB/semana (rápido restore, caro armazenamento)
Backup completo semanal + incremental diário: 100 GB + 5 GB/dia → 130 GB/semana (restore mais lento)
Backup completo semanal + diferencial diário: 100 GB + 5-25 GB/dia → 175 GB/semana (restore intermediário)

Backup lógico vs. físico

Backup lógico (dump) extrai dados em formato compreensível:

# Backup lógico de banco PostgreSQL
pg_dump -U admin -F c -b -v -f backup_producao_2024-11-01.dump meubanco

# Restore lógico
pg_restore -U admin -d meubanco -v backup_producao_2024-11-01.dump

Backup físico (snapshot) copia o volume inteiro em nível de bloco:

# Snapshot LVM
lvcreate -L 10G -s -n snapshot_producao /dev/vg_producao/lv_dados

# Backup do snapshot
dd if=/dev/vg_producao/snapshot_producao of=/backup/snapshot_2024-11-01.img bs=4M

Estratégia 3-2-1

A regra 3-2-1 recomenda: 3 cópias dos dados, em 2 mídias diferentes, com 1 cópia offsite. Exemplo prático:

Cópia 1: Disco local (backup completo diário)
Cópia 2: NAS local (backup incremental a cada 4 horas)
Cópia 3: Armazenamento em nuvem (backup completo semanal, criptografado)

3. Planejamento de Testes de Recovery

O ciclo de vida de um teste de recovery inclui: planejamento, execução, validação e documentação.

Tipos de teste

Teste de restore completo:
- Restaurar sistema inteiro em ambiente isolado
- Verificar todos os serviços e dados
- Duração típica: 4-8 horas

Teste de restore parcial:
- Restaurar arquivo ou banco específico
- Verificar integridade do dado restaurado
- Duração típica: 30-60 minutos

Teste de failover simulado:
- Desligar servidor primário intencionalmente
- Ativar servidor secundário
- Validar operação contínua
- Duração típica: 1-2 horas

Frequência ideal

Sistemas críticos (RTO < 1 hora): Teste completo semanal, parcial diário
Sistemas importantes (RTO < 4 horas): Teste completo mensal, parcial semanal
Sistemas não críticos (RTO < 24 horas): Teste completo trimestral, parcial mensal

4. Execução de Testes de Restore em Cenários Reais

Restore de banco de dados

-- Verificar integridade antes do restore
pg_verifybackup backup_producao_2024-11-01

-- Executar restore
pg_restore -U admin -d banco_teste -v --exit-on-error backup_producao_2024-11-01.dump

-- Validar consistência
SELECT count(*) FROM information_schema.tables;
SELECT schemaname, tablename, n_live_tup FROM pg_stat_user_tables;

Restore de aplicações

# Passos para restore de aplicação web
1. Restaurar código-fonte do repositório (git checkout v2.3.1)
2. Restaurar dependências (npm install --production)
3. Restaurar configurações (copiar .env do backup)
4. Restaurar estado externalizado (Redis, sessões)
5. Verificar conectividade com banco restaurado
6. Executar testes de integração

Validação pós-restore

# Checagem de logs
grep -i "error\|fail\|exception" /var/log/aplicacao/restore.log

# Verificação de dados de teste
curl -X GET http://localhost:8080/api/health
curl -X POST http://localhost:8080/api/test -d '{"action":"validate"}'

# Métricas de performance
time curl -X GET http://localhost:8080/api/heavy-query
# Comparar com baseline armazenado

5. Automação e Monitoramento da Estratégia

Script automatizado de backup e verificação

#!/bin/bash
# backup_automatizado.sh

DATA=$(date +%Y-%m-%d)
BACKUP_DIR="/backup/${DATA}"
LOG_FILE="/var/log/backup/${DATA}.log"

# Backup completo
pg_dump -U admin -F c -b -f "${BACKUP_DIR}/banco.dump" meubanco >> ${LOG_FILE} 2>&1

# Verificação de checksum
sha256sum "${BACKUP_DIR}/banco.dump" > "${BACKUP_DIR}/banco.dump.sha256"

# Teste de restore sintético (apenas estrutura)
pg_restore -U admin -d banco_teste_sintetico --schema-only \
  "${BACKUP_DIR}/banco.dump" >> ${LOG_FILE} 2>&1

# Alerta em caso de falha
if [ $? -ne 0 ]; then
  curl -X POST -H "Content-Type: application/json" \
    -d '{"text":"Falha no backup de '${DATA}'"}' \
    https://hooks.slack.com/services/TOKEN
fi

Monitoramento contínuo

# Cron job para verificação diária
0 2 * * * /usr/local/bin/backup_automatizado.sh

# Alerta de retenção expirada
find /backup -type d -mtime +30 -exec rm -rf {} \; -exec \
  curl -X POST -d '{"text":"Backups antigos removidos"}' \
  https://hooks.slack.com/services/TOKEN \;

6. Documentação e Melhoria Contínua

Runbook de disaster recovery

RUNBOOK: Recuperação de Banco PostgreSQL
=========================================

1. IDENTIFICAÇÃO DO INCIDENTE
   - Severidade: Crítica
   - Sistema: Banco de Produção
   - Contato: DBA Plantão (55-11-99999-9999)

2. PASSOS DE RECUPERAÇÃO
   a) Isolar servidor afetado
   b) Provisionar novo servidor (se necessário)
   c) Restaurar backup mais recente
   d) Aplicar logs WAL (se disponíveis)
   e) Verificar integridade dos dados
   f) Redirecionar tráfego

3. VALIDAÇÃO
   - Executar query de contagem em tabelas críticas
   - Verificar consistência de dados financeiros
   - Confirmar RPO e RTO atingidos

4. ESCALONAMENTO
   - Se restore falhar: contatar suporte do fornecedor
   - Se RTO excedido: notificar gerência de TI

Lições aprendidas

Incidente: 15/10/2024 - Falha em restore de backup incremental
Causa: Arquivo WAL corrompido não detectado
Ação corretiva: Implementar verificação de checksum diária
Resultado: Tempo de restore reduzido de 6h para 2h

7. Casos de Fronteira e Erros Comuns

Backup corrompido: detecção tardia

# Simulação de detecção de corrupção
pg_verifybackup backup_suspeito.dump
# Saída: WARNING: checksum mismatch at block 1523

# Estratégia de mitigação
# 1. Tentar restore ignorando blocos corrompidos
pg_restore --ignore-blocks backup_suspeito.dump
# 2. Se falhar, usar backup anterior + logs WAL
pg_restore backup_anterior.dump | psql -d banco
pg_wal_replay --timeline previous

Dependências não mapeadas

Erro comum: Restore de banco sem considerar versão de schema

# Cenário de falha
pg_restore -d banco_producao backup_v2.dump
# ERRO: column "novo_campo" does not exist

# Solução: versionar schema e dados separadamente
git tag schema_v2.1
pg_dump --schema-only -f schema_v2.1.sql banco
pg_dump --data-only -f dados_v2.1.sql banco

Testes que nunca falham

Ambientes de teste idênticos à produção mascaram problemas reais. Para evitar essa armadilha:

# Estratégia de teste realista
1. Usar hardware diferente (menos recursos)
2. Simular latência de rede (tc qdisc add dev eth0 root netem delay 100ms)
3. Testar em horário de pico simulado
4. Introduzir falhas parciais (kill -9 processos durante restore)

Referências