Whitepaper técnico — PodHeitor MongoDB para Bacula

Arquitectura cdylib + backend, modos dump e incremental por oplog, replay point-in-time, manifest firmado con Ed25519, exporter Prometheus y aislamiento de licencia para Bacula Community 15.0.3+ y Bacularis.

Documento técnico complementario a la página del plugin PodHeitor MongoDB.

1. El problema: Bacula stock no respalda MongoDB de forma segura

El File Daemon de Bacula, por sí solo, respalda archivos. MongoDB en producción no es un conjunto coherente de archivos en un punto único del tiempo: copiar /var/lib/mongo con mongod activo produce un snapshot inconsistente que falla en --repair o — peor — abre silenciosamente en estado corrupto. Las alternativas tradicionales tienen cada una su costo:

  • Bacula Enterprise MongoDB plugin — solo hace mongodump full; no tiene incrementales por oplog, ni PITR, ni manifest firmado, ni exporter de métricas.
  • Veeam / Commvault — el precio por TB protegido escala mal en clusters MongoDB grandes; PITR sigue dependiendo de oplog manual.
  • Scripts caseros de mongodump — ignoran read preference, martillan al PRIMARY, no detectan rotation gap del oplog, y el operador se entera solo en el momento del desastre.

PodHeitor MongoDB cubre esos huecos con paralelismo cross-DB y cross-collection, oplog tip persistente, replay PIT por timestamp o contador de incremental, y empaquetado RPM/DEB con unit systemd hardened.

2. Modelo arquitectónico

El plugin sigue el patrón PodHeitor de cdylib + backend standalone, con PTCOMM (framing length-tagged sobre stdin/stdout):

                      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       (subproceso por job)
     ├── mongodump / mongorestore
     ├── stats sidecar  →  /opt/bacula/working/podheitor-mongodb-<r>-stats.json
     ├── oplog tip file  →  ...-tip.json
     └── manifest + topology + RestoreObject  →  catálogo Bacula (FT_RESTORE_FIRST=25)
                                                       │
                                                       ▼
                          /opt/bacula/bin/podheitor-mongodb-exporter
                          (HTTP :9105/metrics, bacula:bacula, systemd hardened)

El motivo del split es el mismo que en HPC: crash isolation (un panic en código que toca MongoDB no bloquea bacula-fd), libertad de paralelismo (el backend hospeda tokio + threadpools cross-DB sin violar el contrato Bacula de «un thread por bpContext«), y firewall de licencia (el subproceso nunca toca el ABI de Bacula; solo el cdylib lo hace, exclusivamente vía el crate bacula-fd-abi con extern "C" independiente).

3. Modos de backup soportados (v1.0)

Modo Mecanismo Estado v1.0
dump mongodump lógico streaming, BSON sobre PTCOMM GA — JobId 7984/7985 validados
dump multi-DB pipelined N DBs en paralelo, cap configurable (parallel_dbs=4) GA — JobId 7906
dump chunking por collection Particiona collection grande por _id vía $bucketAuto GA — JobId 7925/7927
Incremental por oplog (level=I) applyOps over the wire — incrementales reales, no diff de dump GA — JobId 8037-8041
Replay PIT second / RFC 3339 / :inc / @inc GA — JobId 8065-8099
snapshot (LVM/ZFS) Stub de código Phase 3 — pendiente lab LVM/ZFS-backed
hot_backup (Percona createBackup) Stub de código Phase 4 — pendiente Percona Server lab
Orquestación de cluster sharded Stub de código Phase 6 — pendiente
replicate (DR clone) Stub de código Phase 7 — pendiente

4. Selector de fuente SECONDARY-aware

Un backup que martilla al PRIMARY es un backup que cuesta SLA. El plugin parsea el connection string replicaSet, ejecuta rs.status() en el driver, y elige un SECONDARY saludable (readPreference=secondaryPreferred respetado). Si ningún SECONDARY está accesible, cae a PRIMARY con warning explícito en el job log — comportamiento documentado, no silencioso.

Validado en campo: JobId 7728/7996.

5. Incremental por oplog — la pieza que le falta a Bacula Enterprise

Incrementales «de verdad» en MongoDB exigen el oplog. El plugin mantiene un oplog tip persistente en /opt/bacula/working/podheitor-mongodb-<resource>-tip.json: en cada job level=I, lee el tip del job anterior, abre cursor tailable en local.oplog.rs desde ese timestamp, y streama todos los applyOps hasta el tip actual.

La detección de rotation gap es obligatoria: si el oplog dio wrap entre dos jobs, el tip antiguo ya no existe. El plugin lo detecta comparando el ts del primer entry vs el tip esperado y aborta con mensaje claro — el operador debe correr Full nuevo. Validado en JobId 8047-8050.

6. Replay point-in-time

Restore granular a un instante arbitrario, sin tener que restaurar la chain entera en la 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 del día
pluginoptions "podheitor-mongodb: mode=restore pit=:inc=12"

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

dry_run=true hace que el plugin compute la chain (Full + N incrementales) y emita preview en el job log sin aplicar — útil para que el operador verifique antes de ejecutar restore destructivo. Validado en JobId 8097/8099.

El sidecar JSON per-restore elimina la necesidad de reiniciar el FD para cambiar parámetros de restore — el sidecar se lee en cada job y se descarta después (Phase 5ε, JobId 8090/8092).

7. Manifest firmado y verificación BLAKE3

Cada backup emite un manifest JSON que cataloga lo respaldado: lista de DBs, collections, conteos de documentos, oplog tip, topología del replica set al momento del backup. El manifest se hashea con BLAKE3 y se firma con Ed25519 usando una llave configurada por env var (PODHEITOR_MONGODB_SIGNING_KEY).

En el restore, el plugin verifica la firma antes de aplicar — protege contra tampering post-backup (ransomware que intenta reescribir backups antes de detonar). La llave vive fuera del FD; los artefactos se pueden auditar independientemente vía verify-artifacts.sh.

8. Empaquetado y exporter Prometheus

v1.0 entrega RPM (EL9) + DEB (Debian 12 / Ubuntu 22.04), firmados (RPM in-archive + DEB detached GPG), validados en smoke matrix de 5 distros vía podman (5/5 PASS). El exporter Prometheus expone en :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}

El exporter corre como bacula:bacula bajo unit systemd hardened (ProtectSystem=strict, NoNewPrivileges=yes, PrivateTmp=yes), leyendo solo los stats sidecars en el working dir.

9. FileSet de ejemplo (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. Versiones soportadas (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 en Phase 4 — code-stub)
  • MongoDB Enterprise 7.0+ ($backupCursor) — Phase 9 / v1.5
  • Bacula Community 15.0.3+ y Bacularis

11. Postura de licencia

El plugin se distribuye bajo licencia PROPRIETARY single-license. El backend nunca toca el ABI de Bacula.

¿Listo para evaluar?

Trial gratuito de 30 días para clusters MongoDB calificados (Community, Percona, Enterprise). Garantizamos al menos 50% de descuento vs Bacula Enterprise, Veeam o Commvault, con más funcionalidades incluidas — incluyendo replay PIT y manifest firmado que ningún competidor entrega out-of-the-box.

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

Disponível em: pt-brPortuguês (Portugués, Brasil)enEnglish (Inglés)esEspañol

Deja una respuesta