DR Restore Drill - Akira
Esercitazione disaster recovery per validare che i backup PostgreSQL/TimescaleDB siano ripristinabili e che RPO/RTO osservati restino entro i target dichiarati.
Questo runbook copre il drill periodico su VM isolata. Per incidenti reali usare
anche docs/runbooks/dr-restore-procedure.md.
Scope
- PostgreSQL 16 + TimescaleDB restore da
pg_dump --format=custom. - Hypertable
cdr, tabelle applicative, ENUM e funzioni critiche. - Misura RTO: provisioning VM, download dump, restore, sanity check.
- Misura RPO: differenza tra failure time e timestamp backup, oppure confronto con sorgente live se configurata nello script.
- Redis: recovery best-effort da stato ricostruibile; cache, idempotency keys e rate limit non sono source of truth.
- NATS JetStream: verifica backlog separata; restore dello stato JetStream resta low priority e fuori dallo script del drill.
Pre-requisiti
- Accesso Hetzner Cloud con
hcloudeHCLOUD_TOKEN. - VM scratch on-demand, default
akira-dr-scratchinfsn1. - SSH key Hetzner gia' registrata, default
akira-staging. - Storage Box BX11 raggiungibile via SFTP.
- Dump PostgreSQL in
/backups/pg/akira-*.dump. infra/cloud-init/dr-scratch.ymldisponibile sul runner.- Tool locali:
bash,hcloud,ssh,scp,sftp,jq,date,curlopzionale per notifiche.
Target
Target canonici Fase 1 da ADR-0012:
| Ambiente | RPO | RTO |
|---|---|---|
| Staging | 5 minuti | 15 minuti |
| Produzione futura | da confermare | da confermare |
Target pilot operativo per TASK-200:
| Metrica | Target |
|---|---|
| Provisioning VM scratch | < 10 minuti |
| Restore dump staging | < 2 ore |
| RTO totale drill | < 4 ore |
| RPO massimo pilot | < 1 ora |
Se ADR e task divergono, prevale ADR-0012. Il drill TASK-200 mantiene i target pilot piu' larghi solo come soglie reportistiche.
Procedura Step-by-step
1. Preparare baseline e failure time
Scegliere il timestamp simulato dell'incidente. Se non impostato, lo script usa l'ora di avvio del drill.
export DR_FAILURE_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
Opzionale: configurare confronto con database sorgente live per calcolare delta CDR e RPO sui dati reali.
export DR_SOURCE_DB_HOST=akira-db-01-staging
export DR_SOURCE_DB_NAME=akira
2. Eseguire il drill automatizzato
HCLOUD_TOKEN=... \
STORAGEBOX_HOST=... \
STORAGEBOX_USER=... \
STORAGEBOX_SSH_KEY=/root/.ssh/storagebox_ed25519 \
DR_SSH_KEY_NAME=akira-staging \
./scripts/dr-restore-drill.sh
Lo script:
- seleziona l'ultimo dump
akira-*.dumpsu Storage Box; - crea VM scratch Hetzner con cloud-init PostgreSQL/TimescaleDB;
- scarica il dump via SFTP;
- carica dump e helper sanity sulla VM;
- ripristina in database isolato;
- esegue sanity check;
- scrive
reports/<drill-id>/REPORT.md; - distrugge la VM, salvo
DR_KEEP_VM=1.
3. Verificare integrita'
Il drill e' valido solo se il report mostra:
tables_count >= 70;enums_count >= 20;hypertable_cdr_exists = true;fn_resolve_agent_fee_exists = true;pg_restorecompletato senza exit code non-zero.
Per debug manuale sulla VM scratch:
sudo -u postgres psql -d akira_dr_test -c \
"SELECT COUNT(*), MIN(call_start_ts), MAX(call_start_ts) FROM cdr;"
sudo -u postgres psql -d akira_dr_test -c \
"SELECT hypertable_name, num_chunks FROM timescaledb_information.hypertables;"
Se il modello CDR usa un nome colonna diverso da call_start_ts, usare il JSON
del sanity helper come fonte minima e registrare la discrepanza nel report.
4. Misurare RPO/RTO
- RTO provisioning =
vm_ready_ts - drill_start_ts. - RTO restore =
restore_complete_ts - restore_start_ts. - RTO totale =
sanity_complete_ts - drill_start_ts. - RPO da backup =
failure_ts - backup_ts. - RPO da confronto live, se configurato =
source_latest_cdr_ts - restored_latest_cdr_ts.
Per drill mensili senza sorgente live, il valore autoritativo e' l'RPO da timestamp dump/WAL policy, non il delta CDR.
5. Cleanup
Lo script elimina la VM a fine esecuzione. Se e' stato usato DR_KEEP_VM=1,
eliminarla manualmente dopo il debug:
hcloud server delete akira-dr-scratch
Notifiche
Impostare DRILL_NOTIFY_WEBHOOK per inviare l'esito a Slack o webhook
compatibile:
export DRILL_NOTIFY_WEBHOOK=https://hooks.slack.com/services/...
Il payload contiene drill id, verdict, RTO, RPO e path report.
Cadence
- Pilot: mensile, primo giorno del mese alle 04:00 UTC.
- GA: trimestrale, salvo diversa decisione ADR.
- Post-incidente: drill ad-hoc entro 2 settimane dalla RCA.
Postmortem Template
Per drill fallito o degradato registrare:
- data e drill id;
- dump selezionato;
- RPO/RTO osservati;
- sanity JSON;
- log
pg_restore; - causa del fallimento;
- remediation owner e scadenza;
- decisione su retry.
Se disponibile, usare docs/runbooks/postmortem-template.md; altrimenti
appendere una nota strutturata in docs/runbooks/_drill-log.md.