Whitepaper técnico — PodHeitor MongoDB para Bacula

Arquitetura cdylib + backend, modos dump/oplog incremental, point-in-time replay, manifest assinado em Ed25519, exporter Prometheus e isolamento de licença para Bacula Community 15.0.3+ e Bacularis.

Documento técnico complementar à página do plugin PodHeitor MongoDB.

1. Problema: backup de MongoDB com Bacula stock é um furo

O Bacula File Daemon, sozinho, faz backup de arquivos. MongoDB, em produção, não é um conjunto de arquivos coerentes em ponto algum do tempo: mover /var/lib/mongo com o mongod ativo produz um snapshot inconsistente que falha o --repair ou — pior — abre silenciosamente em estado corrompido. As alternativas tradicionais têm cada uma seu custo:

  • Bacula Enterprise MongoDB plugin — só faz mongodump full; não tem oplog incremental, não tem PITR, não tem manifest assinado, não tem exporter de métricas.
  • Veeam / Commvault — preço por TB protegido escala mal em clusters MongoDB grandes; PITR ainda depende de oplog manual.
  • Scripts caseiros de mongodump — ignoram o read preference, hammeram o PRIMARY, não detectam rotation gap de oplog, e o operador descobre só na hora do desastre.

O PodHeitor MongoDB endereça esses pontos com paralelismo cross-DB e cross-collection, oplog tip persistente, replay PIT por timestamp ou contador de incremental, e empacotamento RPM/DEB com unit systemd hardenizada.

2. Modelo arquitetural

O plugin segue o padrão PodHeitor de cdylib + backend standalone, com PTCOMM (length-tagged framing em stdin/stdout) entre os processos:

                      bacula-fd (root, daemon)
                            │
                            │ dlopen
                            ▼
     /opt/bacula/plugins/podheitor-mongodb-fd.so   (Rust cdylib)
                            │
                            │ fork+exec, PTCOMM stdin/stdout
                            ▼
 /opt/bacula/bin/podheitor-mongodb-backend       (per-job subprocess)
     ├── mongodump / mongorestore
     ├── stats sidecar  →  /opt/bacula/working/podheitor-mongodb-<r>-stats.json
     ├── oplog tip file  →  ...-tip.json
     └── manifest + topology + RestoreObject  →  Bacula catalog (FT_RESTORE_FIRST=25)
                                                       │
                                                       ▼
                          /opt/bacula/bin/podheitor-mongodb-exporter
                          (HTTP :9105/metrics, bacula:bacula, hardened systemd)

O motivo do split é o mesmo do HPC: crash isolation (um panic no driver MongoDB não wedga bacula-fd), liberdade de paralelismo (o backend hospeda tokio + threadpools cross-DB sem violar o contrato Bacula de “uma thread por bpContext“), e license firewall (o subprocesso nunca toca o ABI do Bacula; o cdylib o faz exclusivamente via crate bacula-fd-abi com extern "C" independente).

3. Modos de backup suportados (v1.0)

Modo Mecanismo Status v1.0
dump mongodump lógico streaming, BSON over PTCOMM GA — JobId 7984/7985 validados
dump multi-DB pipelined N DBs em paralelo, com cap configurável (parallel_dbs=4) GA — JobId 7906
dump per-collection chunking Particiona collection grande por _id via $bucketAuto GA — JobId 7925/7927
Oplog incremental (level=I) applyOps over the wire — incrementais reais, não diff de dump GA — JobId 8037-8041
PIT replay second / RFC 3339 / :inc / @inc GA — JobId 8065-8099
snapshot (LVM/ZFS) Stub de código Phase 3 — pendente lab LVM/ZFS-backed
hot_backup (Percona createBackup) Stub de código Phase 4 — pendente Percona Server lab
Sharded cluster orchestration Stub de código Phase 6 — pendente
replicate (DR clone) Stub de código Phase 7 — pendente

4. SECONDARY-aware source picker

Backup que martela o PRIMARY é backup que custa SLA. O plugin parseia o replicaSet connection string, executa rs.status() no driver, e escolhe um SECONDARY saudável (readPreference=secondaryPreferred respeitado). Se nenhum SECONDARY estiver acessível, cai para PRIMARY com warning explícito no job log — comportamento documentado, não silencioso.

Validado em campo: JobId 7728/7996.

5. Oplog incremental — a peça que falta no Bacula Enterprise

Incrementais “de verdade” em MongoDB exigem o oplog. O plugin mantém um oplog tip persistente em /opt/bacula/working/podheitor-mongodb-<resource>-tip.json: a cada job level=I, lê o tip do job anterior, abre cursor tailable em local.oplog.rs a partir desse timestamp, e streama todos os applyOps até o tip atual.

Detecção de rotation gap é mandatória: se o oplog deu wrap entre dois jobs, o tip antigo não existe mais. O plugin detecta isso comparando o ts do primeiro entry vs o tip esperado e aborta com mensagem clara — operador deve rodar Full novo. Validado em JobId 8047-8050.

6. Point-in-time replay

Restore granular para um instante arbitrário, sem precisar restaurar a chain inteira na máquina destino:

# Por timestamp absoluto (RFC 3339)
pluginoptions "podheitor-mongodb: mode=restore pit=2026-04-15T14:30:00Z dry_run=true"

# Por contador de incremental dentro do dia
pluginoptions "podheitor-mongodb: mode=restore pit=:inc=12"

# Por segundo Unix
pluginoptions "podheitor-mongodb: mode=restore pit=1713187800"

O dry_run=true faz o plugin computar a chain (Full + N incrementais) e emite preview no job log sem aplicar — útil para operador verificar antes de executar restore destrutivo. Validado em JobId 8097/8099.

O per-restore sidecar JSON elimina a necessidade de reiniciar o FD para mudar parâmetros de restore — o sidecar é lido a cada job e descartado depois (Phase 5ε, JobId 8090/8092).

7. Manifest assinado e verificação BLAKE3

Cada backup emite um manifest JSON que catalogo o que foi salvo: lista de DBs, collections, contagens de documentos, oplog tip, topologia do replica set no momento do backup. O manifest é hashado com BLAKE3 e assinado com Ed25519 via chave configurada por env var (PODHEITOR_MONGODB_SIGNING_KEY).

No restore, o plugin verifica a assinatura antes de aplicar — protege contra tampering pós-backup (ransomware que tenta reescrever backups antes de detonar). A chave fica fora do FD; os artefatos podem ser auditados independentemente via verify-artifacts.sh.

8. Empacotamento e exporter Prometheus

v1.0 ships RPM (EL9) + DEB (Debian 12 / Ubuntu 22.04), assinados (RPM in-archive + DEB detached GPG), validados em smoke matrix de 5 distros via podman (5/5 PASS). O exporter Prometheus expõe em :9105/metrics:

  • podheitor_mongodb_exporter_scrapes_total
  • podheitor_mongodb_backup_duration_seconds{resource}
  • podheitor_mongodb_oplog_lag_seconds{resource}
  • podheitor_mongodb_last_success_timestamp{resource}

O exporter roda como bacula:bacula sob unit systemd hardenizada (ProtectSystem=strict, NoNewPrivileges=yes, PrivateTmp=yes), lendo apenas os stats sidecars no working dir.

9. FileSet exemplo (replica set)

FileSet {
  Name = "MongoDB-RS-Dump"
  Include {
    Options { Signature = SHA256 }
    Plugin = "podheitor-mongodb: mode=dump uri=mongodb://backup_user@rs0-1,rs0-2,rs0-3/?replicaSet=rs0&readPreference=secondaryPreferred&authSource=admin database=* parallel_dbs=4 verify=true"
  }
}

Job {
  Name     = "MongoDB-Backup"
  Type     = Backup
  Client   = mongo-fd
  FileSet  = "MongoDB-RS-Dump"
  Storage  = File1
  Pool     = Default
  Schedule = "WeeklyCycle"
}

10. Versões suportadas (v1.0)

  • MongoDB Community 4.4, 5.0, 6.0, 7.0, 8.0
  • Percona Server for MongoDB 6.0, 7.0, 8.0 (modo hot_backup em Phase 4 — code-stub)
  • MongoDB Enterprise 7.0+ ($backupCursor) — Phase 9 / v1.5
  • Bacula Community 15.0.3+ e Bacularis

11. License posture

O plugin distribui sob licença PROPRIETARY single-license. O backend nunca toca o ABI do Bacula.

Pronto para avaliar?

Trial gratuito de 30 dias para clusters MongoDB qualificados (Community, Percona, Enterprise). Garantimos no mínimo 50% de desconto vs Bacula Enterprise, Veeam ou Commvault, com mais funcionalidades inclusas — incluindo PIT replay e manifest assinado que nenhum competidor entrega out-of-the-box.

Heitor Faria — Fundador, PodHeitor International
[email protected]
☎ +1 (789) 726-1749 · +55 (61) 98268-4220 (WhatsApp)
🔗 Página do plugin PodHeitor MongoDB

Disponível em: pt-brPortuguêsenEnglish (Inglês)esEspañol (Espanhol)

Deixe um comentário