Skip to content

Disaster Recovery e Continuidade#

Plano de recuperação de desastres e continuidade de negócio para o site UNICEF Portugal.

1. Identificação de Riscos#

Risco Probabilidade Impacto Mitigação
App Service crash/hang Alta (atual) Alto Always On + Auto Heal + Health Check
SQL Database corrupção Baixa Crítico Backups automáticos Azure (PITR)
SQL DTU throttling Média Alto Monitorização + escalamento
Storage account indisponível Muito baixa Alto Redundância LRS
Front Door/CDN falha Muito baixa Alto Failover automático Azure
Perda de código fonte Muito baixa Crítico Azure DevOps + GitHub mirror
Credential leak Baixa Crítico Key Vault + rotação

2. Backup e Restauro#

Azure SQL (PITR - Point In Time Restore)#

O Azure SQL Standard tier oferece 14 dias de retenção de backups automáticos. É possível restaurar a base de dados para qualquer ponto nos últimos 14 dias.

# Restaurar para um ponto no tempo
az sql db restore \
  --dest-name uncdb-prd-restored \
  --edition Standard \
  --service-objective S1 \
  --time "2026-04-13T12:00:00Z" \
  --resource-group unc-prd \
  --server uncsqlsrv-prd \
  --name uncdb-prd \
  --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a

Nota

Após o restore, a nova base de dados terá o nome uncdb-prd-restored. Será necessário atualizar a connection string do App Service para apontar para a nova BD, ou renomear as bases de dados.

Blob Storage#

Propriedade Valor
Storage account uncstorageprd
Redundância LRS (Locally Redundant Storage)
Conteúdo Media e imagens do Umbraco

Para backup manual do blob storage:

az storage blob download-batch \
  --destination ./backup \
  --source <container> \
  --account-name uncstorageprd \
  --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a

Recomendação

Ativar soft delete e versioning no blob storage para proteção adicional contra eliminação acidental.

Código fonte#

Localização URL
Azure DevOps (principal) https://dev.azure.com/double-pt/Unicef/_git/Unicef
GitHub (mirror) https://github.com/BetacodeTech/UNC.PublicPortal.git

Importante

Garantir que ambos os repositórios estão sincronizados. Verificar periodicamente que o mirror no GitHub está atualizado.

3. Procedimento de Recuperação Total#

flowchart TD
    A[Incidente detetado] --> B{Identificar o problema}

    B -->|App Service| C[Restart do App Service]
    B -->|Base de dados| D[Verificar SQL Server]
    B -->|Storage| E[Verificar Blob Storage]
    B -->|DNS/Rede| F[Verificar Azure DNS]

    C --> C1{Resolveu?}
    C1 -->|Sim| Z[Monitorizar e documentar]
    C1 -->|Nao| C2[Redeploy do staging slot]
    C2 --> C3{Resolveu?}
    C3 -->|Sim| Z
    C3 -->|Nao| C4[Escalar App Service Plan]
    C4 --> C5{Resolveu?}
    C5 -->|Sim| Z
    C5 -->|Nao| X[Escalar para equipa dev]

    D --> D1{SQL acessivel?}
    D1 -->|Nao| D2[Verificar firewall e estado do servidor]
    D1 -->|Sim mas lento| D3[DTU throttling?]
    D3 -->|Sim| D4[Escalar tier SQL temporariamente]
    D1 -->|Dados corrompidos| D5[PITR Restore]
    D5 --> D6[Criar BD restaurada]
    D6 --> D7[Atualizar connection string]
    D7 --> D8[Restart App Service]
    D8 --> Z
    D4 --> Z
    D2 --> Z

    E --> E1{Container acessivel?}
    E1 -->|Nao| E2[Verificar estado do storage account]
    E1 -->|Ficheiros em falta| E3[Restaurar de backup]
    E2 --> Z
    E3 --> Z

    F --> F1[Verificar registos DNS Azure]
    F1 --> F2{DNS correto?}
    F2 -->|Nao| F3[Corrigir registos DNS]
    F2 -->|Sim| F4[Verificar Front Door / CDN]
    F3 --> Z
    F4 --> Z

    X --> Z

Passo a passo detalhado#

Se o problema é o App Service#

  1. Restart: Ver Runbook de Restart
  2. Redeploy: Swap com staging slot
  3. Escalar: Aumentar tier do App Service Plan temporariamente

Se o problema é a base de dados#

  1. Verificar acesso:

    az sql db show \
      --name uncdb-prd \
      --server uncsqlsrv-prd \
      --resource-group unc-prd \
      --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a
    

  2. PITR Restore (se necessário):

    az sql db restore \
      --dest-name uncdb-prd-restored \
      --edition Standard \
      --service-objective S1 \
      --time "2026-04-13T12:00:00Z" \
      --resource-group unc-prd \
      --server uncsqlsrv-prd \
      --name uncdb-prd \
      --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a
    

  3. Atualizar connection string do App Service:

    az webapp config connection-string set \
      --name uncwebprd \
      --resource-group unc-prd \
      --connection-string-type SQLAzure \
      --settings umbracoDbDSN="Server=tcp:uncsqlsrv-prd.database.windows.net,1433;Database=uncdb-prd-restored;..." \
      --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a
    

Se o problema é o storage#

  1. Verificar estado:

    az storage account show \
      --name uncstorageprd \
      --resource-group unc-prd \
      --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a
    

  2. Listar containers:

    az storage container list \
      --account-name uncstorageprd \
      --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a
    

Se o problema é DNS#

  1. Verificar registos DNS no Azure Portal
  2. Confirmar que o domínio www.unicef.pt aponta para o App Service correto
  3. Verificar certificado SSL

4. Monitorização Proativa (A IMPLEMENTAR)#

As seguintes medidas de monitorização devem ser implementadas para detetar problemas antes que afetem os utilizadores.

Application Insights#

Ativar Application Insights no App Service para recolha de telemetria:

  • Tempo de resposta dos pedidos
  • Taxa de erros
  • Exceções do servidor
  • Utilização de memória e CPU

Availability Tests (Testes de Disponibilidade)#

Configurar testes automáticos de disponibilidade:

Teste 1 - Homepage Ping:

  • URL: https://www.unicef.pt
  • Frequência: A cada 5 minutos
  • Localizações: 5 regiões diferentes
  • Timeout: 120 segundos
az monitor app-insights web-test create \
  --web-test-name "Homepage-Ping" \
  --resource-group unc-prd \
  --location northeurope \
  --defined-web-test-name "Homepage Ping Test" \
  --web-test-kind "ping" \
  --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a \
  --urls "https://www.unicef.pt" \
  --frequency 300 \
  --timeout 120 \
  --enabled true

Teste 2 - API Ping:

  • URL: https://www.unicef.pt/umbraco/Api/ContentApi/GetData/?url=/
  • Frequência: A cada 5 minutos
  • Validação: Resposta HTTP 200 com conteúdo JSON
az monitor app-insights web-test create \
  --web-test-name "API-Ping" \
  --resource-group unc-prd \
  --location northeurope \
  --defined-web-test-name "API Ping Test" \
  --web-test-kind "ping" \
  --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a \
  --urls "https://www.unicef.pt/umbraco/Api/ContentApi/GetData/?url=/" \
  --frequency 300 \
  --timeout 120 \
  --enabled true

Alert Rules (Regras de Alerta)#

Configurar os seguintes alertas:

Métrica Condição Ação
Response time > 10s durante 5 minutos Email equipa
Failed requests > 10% durante 5 minutos Email equipa
Server exceptions > 0 Email equipa
Memory > 80% Email equipa
Health Check failures Consecutivas Auto restart (via Auto Heal)

Monitorização externa#

Recomenda-se complementar a monitorização Azure com um serviço externo independente como backup:

  • Serviços recomendados: UptimeRobot, Better Stack ou Checkly
  • Endpoints a monitorizar:
    • https://www.unicef.pt — homepage carrega
    • https://www.unicef.pt/umbraco/Api/ContentApi/GetData/?url=/ — API responde com JSON
  • Alertas: Via Slack ou email se indisponível por mais de 2 minutos
  • Vantagem: Funciona mesmo que toda a infraestrutura Azure tenha problemas

5. RPO e RTO#

Métrica Valor Notas
RPO (Recovery Point Objective) ~5 minutos Azure SQL PITR com backups contínuos
RTO - App crash ~3-5 minutos Restart simples do App Service
RTO - DB restore ~30-60 minutos PITR restore + atualização de connection string
RTO - Full redeploy ~1-2 horas Rebuild + deploy + configuração

O que significa#

  • RPO de 5 minutos: Em caso de perda de dados, perdem-se no máximo os últimos 5 minutos de alterações na base de dados
  • RTO de 3-5 minutos: Para o cenário mais comum (app crash), o site pode ser restaurado em 3-5 minutos com um restart
  • RTO de 1-2 horas: No pior cenário (perda total), o site pode ser reconstruído em 1-2 horas a partir do código fonte e backups

Checklist de verificação periódica#

Executar mensalmente:

  • [ ] Verificar que o mirror GitHub está sincronizado com Azure DevOps
  • [ ] Confirmar que os backups SQL estão ativos (14 dias de retenção)
  • [ ] Testar que o staging slot tem uma versão funcional
  • [ ] Verificar que o soft delete está ativo no blob storage
  • [ ] Rever os alertas configurados e confirmar que os emails estão atualizados
  • [ ] Testar o procedimento de restart documentado