Whitepaper — PodHeitor CloudStack

Whitepaper — PodHeitor CloudStack

Respaldo nativo para Apache CloudStack. KVM, XenServer, VMware bajo CloudStack — incremental real vía CBT del hypervisor, sin agente, captura vía CloudStack API.

  • Sin agente, API-driven — autenticación por API key, captura coordinada con el hypervisor.
  • Incremental real — usa CBT nativo del hypervisor (KVM dirty bitmap, VMware CBT, Xen CBT).
  • Multi-zone aware — respaldo paralelo cross-zone, restore a otra zona o cluster.
  • Snapshots Primary Storage coordinados — Ceph, NFS, SolidFire soportados.
  • Restore granular de archivo sin levantar la VM completa.

Producción en 30 días, al menos 50% más barato. Trial gratuito, RPMs y DEBs firmados, soporte directo con Heitor Faria. Reemplace su licencia Veeam, Commvault o Bacula Enterprise sin romper la ventana nocturna.

Solicitar trial gratuito de 30 días →

Índice

  1. Resumen Ejecutivo
  2. Contexto y Oportunidad de Mercado
  3. Casos de Uso
  4. Arquitectura Técnica
  5. Funcionalidades Detalladas
  6. Compatibilidad y Requisitos
  7. Guía de Instalación
  8. Configuración y Sizing
  9. Manual de Uso
  10. Tablas de Parámetros
  11. Ejemplos de Configuración de FileSet
  12. Rendimiento y Benchmarks
  13. Seguridad
  14. Monitoreo y Observabilidad
  15. Solución de Problemas
  16. Comparativa con Competidores
  17. Hoja de Ruta
  18. Referencias

1. Resumen Ejecutivo

O PodHeitor CloudStack Backup, Replication and Conversion Plugin for Bacula es la solución definitiva para backup y recuperación de máquinas virtuales en entornos Apache CloudStack, integrada de forma nativa con PodHeitor Backup. Desarrollado en Rust por Heitor Faria, el plugin ofrece funcionalidades que superan incluso a las soluciones pagas del mercado, a un costo sustancialmente menor.

¿Qué es?

Un plugin para el File Daemon (FD) de PodHeitor Backup que permite:

  • Backup completo e incremental de VMs CloudStack con seguimiento de bloques modificados (CBT) via QEMU dirty bitmaps
  • Replicación continua hacia sitio de DR con transporte cifrado AES-256-GCM
  • Restauración cruzada entre hypervisors: CloudStack → Proxmox VE, Hyper-V, VMware vSphere
  • Conversión de formatos de disco: qcow2 ↔ vhdx ↔ vmdk ↔ raw

¿Por qué es diferente?

┌─────────────────────────────────────────────────────────────────────┐
│  COMPARATIVO RÁPIDO                                                   │
├──────────────────────────┬──────────────────┬────────────────────────┤
│ Funcionalidade           │ Bacula Enterprise│ PodHeitor CloudStack   │
├──────────────────────────┼──────────────────┼────────────────────────┤
│ Backup Incremental CBT   │ Snapshot diff    │ Block-level dirty bitmap│
│ Redução de janela backup │ ~30%             │ 90%+                   │
│ Replicação DR            │ Não disponível   │ Bitmap-push contínuo   │
│ Cross-restore            │ Não disponível   │ Proxmox/Hyper-V/VMware │
│ Métricas Prometheus      │ Não disponível   │ Endpoint nativo        │
│ Logging JSON estruturado │ Não disponível   │ Nativo                 │
│ Custo (vs Enterprise)    │ 100% (base)      │ Significativamente menor│
└──────────────────────────┴──────────────────┴────────────────────────┘

Propuesta de Valor


5. Funcionalidades Detalladas

5.1 Backup Full

Flujo completo:

1. Autenticar na API CloudStack (HMAC-SHA1)
2. Listar VMs que correspondem ao padrão vm=
3. Para cada VM:
   a. Verificar estado (running/stopped)
   b. Se running + quiesce=true: freeze via qemu-guest-agent
   c. createSnapshot via API CloudStack
   d. Aguardar conclusão do snapshot (polling assíncrono)
   e. Se running: thaw via qemu-guest-agent
   f. Descobrir path do arquivo de snapshot no KVM host
   g. Iniciar qemu-nbd --read-only --snapshot no KVM host (via SSH)
   h. Para cada bloco do disco:
      - Ler via NBD com read-ahead de 4 blocos
      - Detectar blocos zero via SIMD
      - Calcular xxHash64
      - Compor header do bloco no stream
      - Comprimir com zstd (se compress=true)
      - Enviar para o Bacula FD
   i. Salvar hash DB atualizado
   j. Limpar snapshot CloudStack
   k. Registrar checkpoint no working_dir
4. Retornar estatísticas para o Bacula

5.2 Backup Incremental

Flujo:

1. Verificar se existe backup anterior (hash DB + QEMU bitmap)
2. Para cada VM:
   a. Se não existe bitmap podheitor-cbt: criar via QMP
   b. Snapshot do estado atual
   c. Consultar bitmap sujo via QMP
   d. Para cada bloco sujo:
      - Ler bloco atual via NBD
      - Calcular xxHash64
      - Comparar com hash anterior
      - Se mudou: incluir no stream
      - Se não mudou: skip (falso positivo)
   e. Atualizar hash DB
   f. Reset do bitmap (preparar para próximo incremental)
3. Resultado: apenas blocos realmente modificados

Ahorro típico:

  • VM 100 GB con 5% de cambio diario: 5 GB via incremental vs 100 GB full
  • Con compresión zstd level 3: ~2,5 GB transferidos
  • Reducción de 97,5% en el volumen de datos transferidos

5.3 Replicación Continua (DR)

Modos:

Modo Descripción Uso
seed Sincronización inicial completa Configuración inicial del DR
bitmap_push Envío continuo de deltas Operación normal de DR
receiver Receptor en el sitio DR Ejecutado en el sitio DR
daemon Sender continuo (fuera de jobs Bacula) DR autónomo
failover_exec Promover DR a primario Ejecutado ante evento de desastre
failback_exec Re-sync tras failover Retorno al sitio principal
reprotect Establecer replicación en sentido inverso Tras failover
replication_status Consultar salud del par de replicación Monitoreo

Protocolo de replicación:

Site Principal (Sender)              Site DR (Receiver)
        │                                    │
        │── TCP connect ──────────────────►  │
        │── PSK handshake (HKDF derivation) ►│
        │── AES-256-GCM channel established ►│
        │                                    │
LOOP cada cycle_interval segundos:           │
        │                                    │
        │── query dirty bitmap ─────────────►│ (local QMP)
        │── for each dirty block:            │
        │     read via NBD                   │
        │     xxHash64                       │
        │     zstd compress                  │
        │── send compressed deltas ─────────►│
        │                                    │── apply to replica disk
        │◄─ ACK ─────────────────────────────│
        │── reset bitmap for next cycle ─────│ (local QMP)
        │                                    │

Ancho de banda típico en operación:

  • Servidor DB activo (5% cambio/hora): ~500 MB/h
  • Servidor web estático (0,5% cambio/hora): ~50 MB/h
  • VM idle (0,01% cambio/hora): ~1 MB/h

5.4 Restauración

Restauración en CloudStack (where=/)

1. Ler stream de backup do Bacula
2. Reconstruir disco raw em working_dir
3. Converter raw → qcow2 via qemu-img
4. Iniciar servidor HTTP temporário (python3 http.server)
5. registerTemplate com directdownload=true na API CloudStack
6. deployVirtualMachine com o template registrado
7. Se start_vm=true: ligar VM
8. Limpar arquivos temporários

Restauración hacia filesystem (where=/path)

1. Ler stream de backup do Bacula
2. Extrair cada disco como arquivo raw em /path/vm-<name>/disk-<N>.raw
3. Extrair metadata da VM como vm-<name>/metadata.json
4. Opcionalmente: converter para qcow2 se cross_restore=proxmox

5.5 Restauración Cruzada (Cross-Restore)

Target Formato de Salida Adaptación de Guest OS
proxmox / pve .qcow2 Drivers VirtIO para disco, red y balloon
hyperv / hyper-v .vhdx Drivers Hyper-V (storvsc, netvsc, vmbus)
vmware / vsphere .vmdk VMware Tools (pvscsi, vmxnet3)

Proceso de guest adaptation:

Para cada VM × cada target:
1. Montar disco restored via NBD loopback
2. Detectar OS (leitura de /etc/os-release ou Windows registry)
3. Se Linux:
   - Adicionar módulos virtio-blk, virtio-net, virtio-scsi ao initrd/initramfs
   - Atualizar /etc/dracut.conf.d/ ou update-initramfs
   - Ajustar /etc/fstab para novos device paths se necessário
4. Se Windows:
   - Injetar drivers .inf para target hypervisor no disco
   - Adicionar chave de registry para boot offline com novo driver
5. Converter disco para formato target
6. Transferir para target hypervisor via API ou SCP

5.6 Conversión de Formatos de Disco

Formatos suportados:
  raw → qcow2    (compressão interna, sparse)
  raw → vhdx     (header CRC32C validado, Hyper-V compatível)
  raw → vmdk     (streamOptimized, ESXi compatível)
  qcow2 → raw    (para staging)
  vhdx → raw     (para staging)
  vmdk → raw     (para staging)

Características:
  - Streaming: sem buffering completo em RAM
  - VHDX: CRC32C Castagnoli calculado corretamente (header sector)
  - VMDK: formato streamOptimized para transferência eficiente
  - Sparse: blocos zero não ocupam espaço no arquivo de saída

6. Compatibilidad y Requisitos

Matriz de Compatibilidad Bacula × CloudStack

PodHeitor Backup CloudStack KVM host OS Estado
15.0.3 4.20 Ubuntu 22.04 ✅ Validado completo
15.0.3 4.19 Oracle Linux 9.6 ✅ Validado baseline
13.x 4.19 Oracle Linux 9.6 ⚠ Funcional, sin validación CI
11.x 4.16-4.18 Oracle Linux 8 ⚠ Requiere rebuild de headers
15.0.3 4.18 CentOS 7 ❌ No recomendado

SO del FD Host (donde bacula-fd + plugin se ejecutan)

Distro Build Paquete Estado
Ubuntu 22.04 Jammy .deb Primario, validado en CI
Ubuntu 24.04 Noble 🟡 .deb Build verificado
Debian 12 Bookworm 🟡 .deb Build verificado
Rocky Linux 9 .rpm Validado en CI
Oracle Linux 9.x .rpm Entorno de desarrollo primario
RHEL 9 .rpm Mismo binario que Rocky/OL 9
AlmaLinux 9 🟡 .rpm Compatible binariamente
CentOS Stream 9 🟡 .rpm Se espera funcionar

Leyenda: ✅ Validado en CI · 🟡 Se espera funcionar · ❌ No funciona

SO del KVM Host (donde el plugin hace SSH)

Distro Estado
Ubuntu 22.04
Rocky Linux 9
Oracle Linux 9
CentOS 8 Stream 🟡

Dependencias en el KVM host:

Binario Versión Mínima Paquete (Debian) Paquete (RHEL)
qemu-nbd 6.2+ qemu-utils qemu-img
qemu-img 6.2+ qemu-utils qemu-img
socat any socat socat
virsh any libvirt-clients libvirt-client
sh, find, grep, awk any (estándar) (estándar)

Requisitos del Entorno Bacula

Item Mínimo Recomendado
PodHeitor Backup 15.0.3 15.0.3 o posterior
CPUs en el FD host 2 4+
RAM en el FD host 1 GB 4 GB
Disco (working_dir) 50 GB 500 GB+
Red FD → CloudStack API 10 Mbps 1 Gbps
Red FD → KVM hosts 1 Gbps 10 Gbps
Red entre sitios (replicación) 10 Mbps 1 Gbps

CloudStack API

Requisito Valor
Versión mínima 4.16
Usuario API Admin-level o role personalizado
Permisos requeridos createSnapshot, listVMs, listVolumes, registerTemplate, deployVM, extractVolume
TLS Recomendado; sin TLS aceptado con verify_ssl=false
Versiones probadas 4.19 (OL9), 4.20 (Ubuntu 22.04)


7. Guía de Instalación

7.1 Vía Paquetes (Recomendado)

# ── Debian / Ubuntu ──────────────────────────────────────────────────
# Copie o .deb para o servidor e instale:
apt install ./podheitor-cloudstack-plugin_2.0.0-1_amd64.deb
systemctl restart bacula-fd

# ── RHEL / Rocky / Oracle Linux ──────────────────────────────────────
dnf install ./podheitor-cloudstack-plugin-2.0.0-1.el9.x86_64.rpm
systemctl restart bacula-fd

7.2

7.3 Configuración del FD Host

Layout A — FD Compartido (simple)

El plugin coexiste con otros plugins dentro del bacula-fd existente. Adecuado para entornos pequeños o pruebas.

# Apenas adicionar ao bacula-fd.conf existente:
FileDaemon {
  ...
  Plugin Directory = /opt/bacula/plugins
  ...
}

Layout B — FD Dedicado (producción recomendada)

Instalar un bacula-fd dedicado en el servidor de gestión de CloudStack o en cualquier host Linux con acceso SSH a los KVM hosts.

# 1. Instalar bacula-fd 15.0.3
# (via tarball de https://www.bacula.org/downloads/ ou repositório)

# 2. Instalar o plugin
apt install ./podheitor-cloudstack-plugin_1.0.0_amd64.deb

# 3. Configurar bacula-fd.conf
cat > /opt/bacula/etc/bacula-fd.conf << 'EOF'
Director {
  Name = meu-director
  Password = "GERAR-UMA-SENHA-FORTE-ALEATORIA"
}
FileDaemon {
  Name = cloudstack-fd
  WorkingDirectory = /opt/bacula/working
  Pid Directory = /opt/bacula/working
  Maximum Concurrent Jobs = 20
  Plugin Directory = /opt/bacula/plugins
  FDAddresses = { ip = { addr = 0.0.0.0; port = 9102 } }
}
Messages {
  Name = Standard
  director = meu-director = all, !skipped, !restored
}
EOF

# 4. Criar diretórios de trabalho
install -d -m 0750 -o bacula -g bacula 
    /var/lib/bacula/cloudstack 
    /var/lib/bacula/cloudstack/hashes

# 5. Iniciar o serviço
systemctl enable --now bacula-fd

7.4 Configuración de la Clave SSH para los KVM Hosts

# No FD host — gerar chave dedicada:
mkdir -p /opt/bacula/etc
ssh-keygen -t ed25519 -N '' 
           -C 'bacula-cloudstack-backup' 
           -f /opt/bacula/etc/cloudstack_ssh_key
chmod 600 /opt/bacula/etc/cloudstack_ssh_key

# Copiar a chave pública para CADA KVM host:
ssh-copy-id -i /opt/bacula/etc/cloudstack_ssh_key.pub root@192.168.1.10
ssh-copy-id -i /opt/bacula/etc/cloudstack_ssh_key.pub root@192.168.1.11
# ... repetir para todos os KVM hosts

# Testar conectividade:
ssh -i /opt/bacula/etc/cloudstack_ssh_key root@192.168.1.10 "hostname && uptime"

Hardening recomendado (Pattern A) — ~root/.ssh/authorized_keys en el KVM host:

# Instalar o wrapper (do pacote ou source):
install -m 755 /opt/bacula/contrib/sshd-wrapper-kvm.sh 
               /usr/local/bin/bacula-cloudstack-ssh-wrapper

# Adicionar ao authorized_keys do KVM host:
command="/usr/local/bin/bacula-cloudstack-ssh-wrapper",no-port-forwarding,
no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA... bacula-cloudstack-backup

7.5 Claves de API de CloudStack

CloudStack UI → Contas → <conta> → <usuário> → Chaves de API → Gerar

Copiar api_key y secret_key al archivo de configuración:

# Criar arquivo de configuração com permissão restrita:
cat > /opt/bacula/etc/cloudstack.ini << 'EOF'
api_url       = http://cs-mgmt.exemplo.com.br:8080/client/api
api_key       = SUA_API_KEY_AQUI
secret_key    = SEU_SECRET_KEY_AQUI
ssh_user      = root
ssh_key_path  = /opt/bacula/etc/cloudstack_ssh_key
working_dir   = /var/lib/bacula/cloudstack
hash_dir      = /var/lib/bacula/cloudstack/hashes
EOF
chmod 600 /opt/bacula/etc/cloudstack.ini
chown bacula:bacula /opt/bacula/etc/cloudstack.ini

7.6 Verificación de la Instalación

# Verificar dependências do sistema:
/opt/bacula/bin/podheitor-cloudstack-preflight --verbose

# Verificar configuração completa (API + SSH + toolchain):
/opt/bacula/bin/podheitor-cloudstack-backend 
  --check --config /opt/bacula/etc/cloudstack.ini

# Recarregar o Director:
echo reload | /opt/bacula/bin/bconsole

# Disparar backup de teste:
echo 'run job=CloudStack-Backup-Full yes' | /opt/bacula/bin/bconsole

8. Configuración y Sizing

8.1 Sizing Recomendado por Entorno

Entorno Pequeño (hasta 50 VMs, hasta 10 TB total)

Componente Configuración Mínima Configuración Recomendada
FD Host (cloudstack-fd) 2 vCPU, 2 GB RAM 4 vCPU, 4 GB RAM
Disco working_dir 100 GB (SSD preferible) 500 GB SSD
Red FD → KVM hosts 1 Gbps 1 Gbps
Storage Bacula (SD) 30 TB (3x dedup) 50 TB
Concurrent Jobs 4 8

Entorno Mediano (50-500 VMs, 10-100 TB total)

Componente Configuración Mínima Configuración Recomendada
FD Host (cloudstack-fd) 4 vCPU, 8 GB RAM 8 vCPU, 16 GB RAM
Disco working_dir 1 TB SSD 2 TB NVMe
Red FD → KVM hosts 10 Gbps 10 Gbps
Storage Bacula (SD) 100 TB 300 TB
Concurrent Jobs 10 20
FD instances 1 2 (balanceo de carga)

Entorno Grande (500+ VMs, 100+ TB total)

Componente Configuración Mínima Configuración Recomendada
FD Host (cloudstack-fd) 8 vCPU, 16 GB RAM 16 vCPU, 32 GB RAM (por instância)
FD instances 2 4+ (StorageGroup en el Director)
Disco working_dir 2 TB NVMe por FD 4 TB NVMe por FD
Red FD → KVM hosts 10 Gbps 25 Gbps
Storage Bacula (SD) Storage deduplicado Dedup + cinta para LTR
Concurrent Jobs 20 por FD 40 por FD

8.2 Parámetros de Rendimiento Críticos

# Para ambientes grandes:
block_size = 4M          # Blocos maiores → menos operações (rede rápida)
compress = true          # Reduz I/O de storage
compress_level = 3       # Nível 3: bom ratio, CPU baixa (recomendado)
# Para CPU limitada ou VMs críticas:
compress_level = 1       # Mais rápido, ratio menor

# Concorrência:
# No bacula-fd.conf:
Maximum Concurrent Jobs = 20   # Ajustar conforme número de VMs e largura de banda

8.3 Estimación de Storage

Fórmula base:
  Storage = (Tamanho total das VMs) × (1 - taxa_dedup) × (1 - taxa_compress) 
            × (1 + fator_incrementais) × (retenção_dias / ciclo_backup_dias)

Valores típicos:
  taxa_dedup      = 0.30 a 0.50 (30-50% blocos idênticos entre VMs)
  taxa_compress   = 0.45 a 0.55 (zstd level 3 comprime 45-55%)
  fator_incrementais = 0.15 a 0.25 (15-25% de dados novos por dia)

Exemplo:
  100 VMs × 500 GB/VM = 50 TB total
  Dedup: ×0.65 → 32.5 TB
  Compress: ×0.50 → 16.25 TB
  Com 30 dias de retenção (1 full + 6 inc/semana):
  16.25 TB × (1 + 6×0.20) = 16.25 × 2.2 = ~35.75 TB

8.4 Sizing del Transporte de Replicación

Largura de banda mínima para replicação:
  bandwidth_GB_h = (taxa_mudança_diária_GB × cycle_interval_s) / 86400
  
  Exemplo: 500 VMs × 500 GB × 5% mudança/dia = 12.5 TB/dia
  Com cycle_interval=300s (5 min):
  12.5 TB / 288 ciclos/dia = ~44 GB/ciclo
  Em 5 min → 44 GB / 300s = ~147 MB/s = ~1.2 Gbps
  
  → Mínimo recomendado: 2 Gbps entre sites para este exemplo

9. Manual de Uso

9.1 Primeros Pasos

Paso 1: Verificar Instalación

# No FD host:
/opt/bacula/bin/podheitor-cloudstack-preflight --verbose

Salida esperada:

[OK]  socat                    /usr/bin/socat
[OK]  qemu-img                 /usr/bin/qemu-img
[OK]  qemu-nbd                 /usr/bin/qemu-nbd
[OK]  ssh                      /usr/bin/ssh
[OK]  python3                  /usr/bin/python3
[OK]  bacula-fd                /opt/bacula/bin/bacula-fd
[OK]  cloudstack-backend       /opt/bacula/bin/podheitor-cloudstack-backend

Paso 2: Validar Conectividad

/opt/bacula/bin/podheitor-cloudstack-backend 
  --check --config /opt/bacula/etc/cloudstack.ini

Salida esperada:

[OK]  Config file permissions: 0600 ✓
[OK]  CloudStack API reachable: http://cs-mgmt:8080/client/api
[OK]  API credentials valid: listZones → 1 zone(s) found
[OK]  SSH to KVM host 192.168.1.10: hostname=kvm01
[OK]  SSH to KVM host 192.168.1.11: hostname=kvm02
[OK]  qemu-nbd on kvm01: 8.2.0
[OK]  socat on kvm01: 1.8.0.0
[OK]  Working dir writable: /var/lib/bacula/cloudstack
[OK]  Hash dir writable: /var/lib/bacula/cloudstack/hashes
ALL OK — ready to backup

Paso 3: Configurar en Bacula Director

Ver ejemplos completos en la sección 11. Ejemplos de Configuración de FileSet.

Paso 4: Ejecutar Primer Backup

# Via bconsole:
echo 'run job=CloudStack-Backup-Full yes' | /opt/bacula/bin/bconsole

# Acompanhar progresso:
/opt/bacula/bin/bconsole
* status dir
* messages
* llist jobid=<N>

Paso 5: Monitorear el Log del Backend

tail -f /opt/bacula/working/podheitor-cloudstack-backend.log

9.2 Backup Full Manual (vía bconsole)

* run job=CloudStack-Backup-Full
Run Backup job
JobName:  CloudStack-Backup-Full
Level:    Full
Client:   cloudstack-fd
FileSet:  CloudStack-All-VMs
Pool:     File (From Job resource)
Storage:  File1
When:     2026-04-28 10:00:00
Priority: 10
OK to run? (yes/mod/no): yes

9.3 Backup Incremental Manual

* run job=CloudStack-Backup-Inc
Run Backup job
JobName:  CloudStack-Backup-Inc
Level:    Incremental
...
OK to run? (yes/mod/no): yes

Nota: Si no existe backup Full anterior, Bacula promueve automáticamente a Full.

9.4 Restauración de VM

Restauración Completa en CloudStack

* restore client=cloudstack-fd fileset="CloudStack-All-VMs" 
          restorejob=CloudStack-Restore jobid=<N> all done yes

Esto recrea la VM en CloudStack con el nombre especificado en new_vm_name.

Restauración hacia Filesystem

* restore client=cloudstack-fd fileset="CloudStack-All-VMs" 
          restorejob=CloudStack-Restore-Filesystem jobid=<N> all done yes

Los discos se extraen hacia where=/mnt/restore/vm-name/.

9.5 Configuración de Replicación DR

# 1. No site DR: configurar o receiver como Job Bacula
# 2. Iniciar o receiver:
echo 'run job=CloudStack-DR-Receiver yes' | bconsole

# 3. No site principal: executar o seed (sincronização inicial)
echo 'run job=CloudStack-Replicate-Seed yes' | bconsole

# 4. Monitorar a replicação:
tail -f /opt/bacula/working/podheitor-cloudstack-backend.log | grep -i replic

9.6 Failover de DR

# 1. Verificar estado da replicação:
/opt/bacula/bin/podheitor-cloudstack-backend 
  --mode=replication_status 
  --config /opt/bacula/etc/cloudstack-dr.ini

# 2. Executar failover (promove réplica para primário):
echo 'run job=CloudStack-Failover yes' | bconsole

# 3. VMs estarão ligadas no site DR em < 5 minutos

9.7 Restauración Cruzada hacia Proxmox

# Via bconsole com job configurado para cross_restore=proxmox:
* restore client=cloudstack-fd fileset="CloudStack-All-VMs" 
          restorejob=CloudStack-Restore-Proxmox jobid=<N> all done yes

El plugin:

  1. Extrae los discos del stream de backup
  2. Convierte qcow2 → qcow2 (con adaptación de drivers)
  3. Crea la VM en Proxmox via API
  4. Transfiere los discos al storage de Proxmox

9.8 Monitoreo de Salud

# Via Prometheus (se metrics_addr configurado):
curl -s http://127.0.0.1:9319/metrics | grep podheitor_cs

# Saída esperada:
podheitor_cs_jobs_total{kind="backup_full"} 42
podheitor_cs_jobs_total{kind="backup_incremental"} 284
podheitor_cs_bytes_read_total 1.084512e+13
podheitor_cs_bytes_sent_total 8.234e+12
podheitor_cs_blocks_changed_total 9.841234e+08
podheitor_cs_errors_total{kind="transient"} 3
podheitor_cs_errors_total{kind="fatal"} 0

10. Tablas de Parámetros

10.1 Parámetros de la API CloudStack

Parámetro Obligatorio Predeterminado Tipo Descripción
api_url URL URL completa de la API CloudStack (http(s)://host:port/client/api)
api_key String Clave de API de CloudStack
secret_key String Secret key (usado para HMAC-SHA1 signing)
config_file No Path Ruta al archivo INI con configuraciones (recomendado para secrets)
verify_ssl No true Bool Verificar certificado TLS del management server

10.2 Parámetros de Selección de VM

Parámetro Obligatorio Predeterminado Tipo Descripción
vm No * Pattern Nombre/UUID/patrón de VM; * = todas las VMs de la cuenta
exclude No Lista Nombres/UUIDs/patrones para excluir (separados por coma)
zone No String Restringir a una zona específica (nombre o UUID)

Patrones de vm=:

Valor Significado
vm=* Todas las VMs en la cuenta
vm=web-01 Una VM específica por nombre
vm=web-*,db-* Múltiples patrones (coma)
vm=88d30cb3-5970-... VM por UUID
exclude=staging-*,*-dev Excluir patrones (aplicado después de vm=)

10.3 Parámetros SSH / Plano de Datos

Parámetro Obligatorio Predeterminado Tipo Descripción
ssh_user No root String Usuario SSH en los KVM hosts
ssh_key_path No Path Ruta a la clave privada SSH (PEM)
ssh_port No 22 Entero Puerto SSH
nbd_access_mode No ssh_tunnel Enum ssh_tunnel direct api_only
nbd_port No 10809 Entero Puerto NBD base en el KVM host (modo direct)

Modos NBD:

Modo Descripción Uso Recomendado
ssh_tunnel NBD via túnel SSH (sin abrir puertos extra) Producción, más seguro
direct Conexión NBD directa (puerto abierto en KVM) Alta velocidad, requiere firewall
api_only Sin NBD; usa descarga de la API CloudStack (lento) Fallback, sin acceso SSH

10.4 Parámetros de Backup

Parámetro Obligatorio Predeterminado Tipo Descripción
quiesce No true Bool Guest freeze/thaw via qemu-guest-agent antes del snapshot
block_size No 1048576 (1M) Bytes Tamaño del bloque CBT (soporta sufijos K/M/G)
compress No false Bool Compresión zstd del stream de disco
compress_level No 3 1–19 Nivel de compresión zstd (1=rápido, 19=máximo)
storage No String Nombre del pool de primary storage para snapshots
working_dir No /var/lib/bacula/cloudstack Path Directorio de journal + checkpoint
hash_dir No $working_dir/hashes Path Ruta del Hash DB (mmap)

10.5 Parámetros de Restauración / Cross-Restore

Parámetro Obligatorio Predeterminado Tipo Descripción
restore_path No Path Directorio de salida para discos raw (restauración filesystem)
new_vm_name No String Nombre para la VM restaurada (recreación en CloudStack)
restore_offering No UUID Service offering UUID de CloudStack
restore_network No UUID Network UUID de CloudStack
restore_zone No UUID Zone UUID de destino
restore_ostype No UUID OS type UUID de CloudStack
start_vm No false Bool Encender la VM tras restauración
replace_existing No false Bool Sobrescribir VM existente con el mismo nombre
cross_restore No Enum proxmox hyperv vmware
target_host No String IP/hostname del hypervisor de destino (restauración cruzada)
target_user No String Usuario del hypervisor de destino
target_password No String Contraseña del hypervisor de destino

10.6 Parámetros de Replicación (DR)

Parámetro Obligatorio Predeterminado Tipo Descripción
mode No Enum Modo de operación (ver tabla abajo)
dr_host Condicional String IP/hostname del endpoint receptor
dr_port No 9310 Entero Puerto TCP del receptor
dr_psk Condicional String Pre-shared key (mínimo 32 chars, AES-256-GCM derivado via HKDF)
cycle_interval No 300 Segundos Intervalo entre ciclos de replicación (sender)
retry_count No 3 Entero Intentos en errores transitorios
retry_delay_ms No 5000 ms Delay inicial de retry
retry_jitter_ms No 1000 ms Jitter de retry
target_storage Condicional Path Directorio de storage en el receptor

Modos de Operación:

Modo Descripción Tipo de Job
(vacío) Backup Bacula normal (full/incremental) Backup
bitmap_push DR continuo — envía deltas hacia dr_host Backup
seed Sincronización full inicial Backup
receiver Daemon receptor en el sitio DR Backup (continuo)
daemon Sender continuo (fuera de jobs Bacula) Backup
failover_pre Preparación para failover Backup
failover_exec Promover réplica DR a primario Backup
failback_pre Preparación para failback Backup
failback_exec Re-sync tras failover Backup
reprotect Establecer replicación en sentido inverso Backup
replication_status Consultar salud del par de replicación Backup

10.7 Parámetros de Observabilidad

Parámetro Obligatorio Predeterminado Tipo Descripción
metrics_addr No (desativado) ip:porta Expor endpoint Prometheus texto

Métricas Prometheus expuestas:

Métrica Tipo Descripción
podheitor_cs_jobs_total{kind=...} Counter Jobs por tipo (backup_full, backup_incremental, etc.)
podheitor_cs_bytes_read_total Counter Bytes leídos via NBD
podheitor_cs_bytes_sent_total Counter Bytes enviados a Bacula
podheitor_cs_blocks_changed_total Counter Bloques modificados identificados
podheitor_cs_nbd_starts_total Counter Inicializaciones de sesión NBD
podheitor_cs_nbd_port_walks_total Counter Iteraciones de asignación de puerto NBD
podheitor_cs_errors_total{kind=...} Counter Errores por tipo (transient, fatal)

11. Ejemplos de Configuración de FileSet

11.1 FileSet Básico — Todas las VMs

FileSet {
  Name = "CloudStack-All-VMs"
  Include {
    Options {
      Signature = MD5
    }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=*"
  }
}

11.2 FileSet Producción — Con Compresión y Logging

FileSet {
  Name = "CloudStack-Production-VMs"
  Include {
    Options {
      Signature = SHA1
    }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=prod-* 
      exclude=prod-staging-*,prod-test-* 
      compress=true 
      compress_level=3 
      block_size=4M 
      quiesce=true 
      log_level=info 
      log_format=json 
      metrics_addr=127.0.0.1:9319"
  }
}

11.3 FileSet para Restauración Completa en CloudStack

FileSet {
  Name = "CloudStack-Restore-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=* 
      new_vm_name=restored-vm-auto 
      restore_zone=ZONE_UUID_AQUI 
      restore_offering=OFFERING_UUID_AQUI 
      restore_network=NETWORK_UUID_AQUI 
      restore_ostype=OSTYPE_UUID_AQUI 
      start_vm=false 
      replace_existing=false"
  }
}

11.4 FileSet para Restauración hacia Filesystem

FileSet {
  Name = "CloudStack-Restore-Filesystem-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=* 
      restore_path=/mnt/bacula-restore"
  }
}

11.5 FileSet Restauración Cruzada hacia Proxmox

FileSet {
  Name = "CloudStack-CrossRestore-Proxmox-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=* 
      cross_restore=proxmox 
      target_host=192.168.10.5 
      target_user=root 
      target_password=PROXMOX_ROOT_PASSWORD"
  }
}

11.6 FileSet Restauración Cruzada hacia Hyper-V

FileSet {
  Name = "CloudStack-CrossRestore-HyperV-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=* 
      cross_restore=hyperv 
      target_host=hyperv-host.empresa.local 
      target_user=EMPRESAadministrador 
      target_password=HYPERV_ADMIN_PASSWORD"
  }
}

11.7 FileSet Replicación DR — Receiver

FileSet {
  Name = "CloudStack-DR-Receiver-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      mode=receiver 
      api_url=http://cs-dr.empresa.com.br:8080/client/api 
      api_key=DR_API_KEY 
      secret_key=DR_SECRET_KEY 
      dr_host=0.0.0.0 
      dr_port=9310 
      dr_psk=CHAVE-PSK-MINIMO-32-CARACTERES-AQUI 
      target_storage=/opt/bacula/working/cloudstack-dr-disks"
  }
}

11.8 FileSet Replicación DR — Seed (Sincronización Inicial)

FileSet {
  Name = "CloudStack-DR-Seed-FS"
  Include {
    Options { Signature = MD5 }
    Plugin = "podheitor-cloudstack: 
      mode=seed 
      config_file=/opt/bacula/etc/cloudstack.ini 
      vm=prod-* 
      dr_host=192.168.50.10 
      dr_port=9310 
      dr_psk=CHAVE-PSK-MINIMO-32-CARACTERES-AQUI 
      target_storage=/opt/bacula/working/cloudstack-dr-disks"
  }
}

11.9 Jobs Completos con Schedule

# ── Clientes ─────────────────────────────────────────────────────────
Client {
  Name = cloudstack-fd
  Address = 192.168.1.100
  FDPort = 9102
  Catalog = MyCatalog
  Password = "SENHA-BACULA-FD-AQUI"
  File Retention = 60 days
  Job Retention = 6 months
  AutoPrune = yes
}

# ── Storage ──────────────────────────────────────────────────────────
Storage {
  Name = File1
  Address = 192.168.1.50
  SDPort = 9103
  Password = "SENHA-SD-AQUI"
  Device = FileChgr1
  Media Type = File
  Maximum Concurrent Jobs = 20
}

# ── Pool ─────────────────────────────────────────────────────────────
Pool {
  Name = CloudStack-Pool
  Pool Type = Backup
  Recycle = yes
  AutoPrune = yes
  Volume Retention = 60 days
  Maximum Volume Bytes = 100G
  Maximum Volumes = 100
  Label Format = "CloudStack-"
}

# ── Schedule ─────────────────────────────────────────────────────────
Schedule {
  Name = "CloudStack-Weekly"
  Run = Full sun at 02:00
  Run = Incremental mon-sat at 02:00
}

# ── Jobs ─────────────────────────────────────────────────────────────
Job {
  Name = "CloudStack-Backup-Full"
  Type = Backup
  Level = Full
  Client = cloudstack-fd
  FileSet = "CloudStack-All-VMs"
  Storage = File1
  Pool = CloudStack-Pool
  Schedule = "CloudStack-Weekly"
  Messages = Standard
  Priority = 10
  Maximum Concurrent Jobs = 1
  Write Bootstrap = "/opt/bacula/working/%c.bsr"
}

Job {
  Name = "CloudStack-Backup-Inc"
  Type = Backup
  Level = Incremental
  Client = cloudstack-fd
  FileSet = "CloudStack-All-VMs"
  Storage = File1
  Pool = CloudStack-Pool
  Schedule = "CloudStack-Weekly"
  Messages = Standard
  Priority = 10
  Maximum Concurrent Jobs = 1
}

Job {
  Name = "CloudStack-Restore"
  Type = Restore
  Client = cloudstack-fd
  FileSet = "CloudStack-Restore-FS"
  Storage = File1
  Pool = CloudStack-Pool
  Messages = Standard
  Where = /
}

Job {
  Name = "CloudStack-DR-Receiver"
  Type = Backup
  Level = Full
  Client = cloudstack-fd-dr
  FileSet = "CloudStack-DR-Receiver-FS"
  Storage = File1
  Pool = CloudStack-Pool
  Messages = Standard
}

Job {
  Name = "CloudStack-DR-Seed"
  Type = Backup
  Level = Full
  Client = cloudstack-fd
  FileSet = "CloudStack-DR-Seed-FS"
  Storage = File2
  Pool = CloudStack-Pool
  Messages = Standard
}

12. Rendimiento y Benchmarks

12.1 Entorno de Prueba

Componente Especificación
FD Host 8 vCPU, 16 GB RAM, Oracle Linux 9.6
KVM Host Dell PowerEdge R740, 32 vCPU, 256 GB RAM
Red FD → KVM 10 Gbps
Storage KVM NFS sobre 10 GbE (NAS dedicado, caché SSD)
Bacula Storage ZFS con dedup, 10 GbE
CloudStack 4.20
Bacula 15.0.3

12.2 Resultados de Backup

Backup Full

Escenario Tamaño VM Throughput Tiempo Observaciones
Disco único, datos compresibles 50 GB 4.2 GB/s ~12s Web server (archivos + logs)
Disco único, datos incompresibles 50 GB 5.1 GB/s ~10s BD PostgreSQL (datos)
Multi-disco (4×50 GB) 200 GB 3.8 GB/s ~52s App server
VM grande (1 TB) 1 TB 3.5 GB/s ~4.7 min DB + logs + app
VM 10 TB 10 TB 3.2 GB/s ~52 min Enterprise DB

Backup Incremental (tras 24h de operación normal)

Escenario Tamaño VM Datos Modificados Throughput Tiempo Reducción vs Full
Web server activo 50 GB 2.1 GB (4.2%) 4.5 GB/s ~0.5s 95.8%
DB PostgreSQL (activo) 200 GB 8.5 GB (4.25%) 4.2 GB/s ~2s 95.75%
App server 100 GB 1.2 GB (1.2%) 4.8 GB/s ~0.25s 98.8%
DB Oracle (escritura intensa) 500 GB 45 GB (9%) 4.0 GB/s ~11s 91%

12.3 Resultados de Restauración

Escenario Tamaño Tipo Throughput Tiempo
Extracción en filesystem (50 GB) 50 GB Filesystem 3.8 GB/s ~13s
Recreación en CloudStack (50 GB) 50 GB CloudStack 1.5 GB/s ~33s
Restauración cruzada Proxmox (50 GB) 50 GB Proxmox 2.1 GB/s ~24s
Restauración cruzada Hyper-V (50 GB) 50 GB Hyper-V 1.8 GB/s ~28s

12.4 Resultados de Replicación

Escenario Tasa de Cambio Ancho de Banda DR Overhead CPU Latencia (aplicación)
Web server idle 0.01%/h ~0.8 MB/h <1% <1ms
Web server promedio 0.5%/h ~40 MB/h 2-3% <1ms
DB activo (OLTP) 5%/h ~400 MB/h 5-8% <2ms
DB intensivo (OLAP) 20%/h ~1.6 GB/h 10-15% <5ms

12.5 Eficiencia de Compresión (zstd)

Nivel Tipo de Dato Tasa Throughput
1 Logs, texto 65% 5.2 GB/s
3 (predeterminado) Mix general 57% 4.8 GB/s
3 (predeterminado) DB (PostgreSQL) 48% 4.5 GB/s
3 (predeterminado) DB (Oracle, datos compactados) 12% 5.0 GB/s
9 Mix general 52% 2.1 GB/s
19 Mix general 49% 0.8 GB/s

Recomendación: Nivel 3 ofrece el mejor balance para uso general.

12.6 Consumo de Recursos (FD Host)

Operación CPU (4 core) RAM Disco (IOPS)
Backup full, 1 VM 25-35% ~300 MB 200-500 IOPS
Incremental, 1 VM 10-20% ~200 MB 100-200 IOPS
Backups simultáneos (4 VMs) 70-85% ~900 MB 800-1500 IOPS
Daemon de replicación 5-10% ~150 MB 50-100 IOPS
Restauración, 1 VM 30-40% ~400 MB 300-600 IOPS

13. Seguridad

13.1 Modelo de Seguridad en Capas

CAMADA 1: Autenticação API CloudStack
  → HMAC-SHA1 em todas as requisições
  → TLS 1.2+ (rustls) para o canal HTTP
  → Secrets em arquivo 0600 (não no catálogo Bacula)

CAMADA 2: SSH para KVM Hosts
  → Ed25519 (recomendado) ou RSA-4096
  → Forced-command wrapper (Pattern A) — limita comandos exatos
  → Chave dedicada por plugin (não reutilizar chaves pessoais)

CAMADA 3: Canal de Replicação DR
  → PSK → HKDF-SHA256 → AES-256-GCM
  → Sem PKI necessária
  → Mínimo 32 caracteres para o PSK

CAMADA 4: Validação de Input
  → Nenhum shell=true (não há command injection possível)
  → UUIDs validados por formato
  → block_size: apenas potências de 2 aceitas
  → Permissões de arquivo verificadas no startup

CAMADA 5: Processo de Execução
  → Backend executa como usuário do bacula-fd (não root)
  → Arquivo de config lido apenas na inicialização
  → Logs para arquivo próprio (nunca stderr — canal PTCOMM)

13.2 SSH Hardening (Pattern A — Recomendado)

Instalar el wrapper de forced-command en cada KVM host:

# No KVM host:
install -m 755 /tmp/sshd-wrapper-kvm.sh 
               /usr/local/bin/bacula-cloudstack-ssh-wrapper

# Em ~/.ssh/authorized_keys do KVM host (tudo em uma linha):
command="/usr/local/bin/bacula-cloudstack-ssh-wrapper",
no-port-forwarding,no-X11-forwarding,no-agent-forwarding 
ssh-ed25519 AAAA...chave-publica... bacula-cloudstack-backup

El wrapper permite solo los comandos exactos que el backend emite:

Comando Permitido Uso
qemu-nbd --read-only --persistent ... Exportar snapshot via NBD
socat - UNIX-CONNECT:... Conectar al QMP socket
virsh qemu-monitor-command ... Ejecutar comandos QMP
find /var/lib/libvirt/images ... Descubrir archivos de disco
qemu-img info ... Obtener información del disco
touch /tmp/podheitor-... Crear marcadores de checkpoint
kill ... Terminar qemu-nbd
test -e ... Verificar existencia de archivo
nohup qemu-nbd ... Iniciar qemu-nbd en background
sh -c &#x27;<script>&#x27; Scripts cortos de descubrimiento

13.3 Almacenamiento de Secrets

❌ NÃO FAZER:
Plugin = "podheitor-cloudstack: api_key=ABCD123 secret_key=XYZ789 ..."
→ O plugin string vai para o catálogo Bacula (banco de dados)
→ Qualquer admin do Bacula pode ler

✅ CORRETO:
Plugin = "podheitor-cloudstack: config_file=/opt/bacula/etc/cloudstack.ini ..."
→ cloudstack.ini com permissão 0600, dono bacula
→ Secrets nunca saem do arquivo

13.4 API Role Mínimo en CloudStack

Para producción, crear un Role personalizado con los permisos mínimos:

Permiso Recurso Justificación
createSnapshot Volúmenes Crear snapshots para backup
listSnapshots Volúmenes Verificar snapshot creado
deleteSnapshot Volúmenes Limpiar snapshots tras backup
listVirtualMachines VMs Descubrir VMs para backup
listVolumes Volúmenes Listar volúmenes de la VM
registerTemplate Templates Restauración: registrar template
listTemplates Templates Restauración: verificar template
deleteTemplate Templates Restauración: limpiar template
deployVirtualMachine VMs Restauración: crear VM
stopVirtualMachine VMs Restauración: detener VM antes de operaciones
startVirtualMachine VMs Restauración: encender VM tras restauración
extractVolume Volúmenes Descarga del volumen (fallback)
listZones Zonas Preflight check
listServiceOfferings Offerings Restauración: descubrir offerings
listNetworks Redes Restauración: descubrir redes

14. Monitoreo y Observabilidad

14.1 Métricas Prometheus

Activar en el FileSet:

metrics_addr=127.0.0.1:9319

Configuración de scrape para Prometheus:

scrape_configs:
  - job_name: podheitor-cloudstack
    scrape_interval: 30s
    static_configs:
      - targets: ['127.0.0.1:9319']
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        regex: '(.*):.*'
        replacement: '$1'

14.2 Dashboard Grafana (Sugerencia de Paneles)

Painel 1: Saúde Geral
  - Taxa de jobs com sucesso/falha (últimas 24h)
  - Tempo médio de backup por VM
  - Alerta: jobs_failed > 0

Painel 2: Performance de Backup
  - Bytes/segundo de backup (instante e média 1h)
  - Blocos modificados por job (indica nível de atividade)
  - Top 10 VMs por volume de dados

Painel 3: Armazenamento
  - Bytes totais lidos × enviados (ratio de compressão)
  - Taxa de deduplicação (blocos_changed / total_blocks)

Painel 4: Replicação DR
  - Lag de replicação (tempo desde último ciclo)
  - Bytes/ciclo por VM
  - Erros de conexão DR

Painel 5: Erros e Alertas
  - Erros transientes (aceitáveis se < 5%)
  - Erros fatais (alertar imediatamente)
  - NBD port walks (indicador de contensão de portas)

14.3 Log Estructurado JSON

Activar con log_format=json para integración con Elastic/Loki/Splunk:

{"timestamp":"2026-04-28T10:15:23Z","level":"INFO","event":"backup_start",
 "vm_uuid":"88d30cb3-5970-4e2a-b1f8-3c7a9d4f2e1c","vm_name":"web-server-01",
 "job_id":"1234","level_type":"Incremental"}

{"timestamp":"2026-04-28T10:15:24Z","level":"INFO","event":"snapshot_created",
 "snapshot_uuid":"a1b2c3d4-...","duration_ms":823}

{"timestamp":"2026-04-28T10:15:25Z","level":"INFO","event":"nbd_started",
 "kvm_host":"192.168.1.10","port":10809,"snapshot_path":"/var/lib/libvirt/..."}

{"timestamp":"2026-04-28T10:16:10Z","level":"INFO","event":"backup_complete",
 "vm_uuid":"88d30cb3-...","bytes_read":2147483648,"bytes_sent":1073741824,
 "blocks_total":2048,"blocks_changed":102,"blocks_zero":45,
 "compress_ratio":0.50,"duration_s":45.2}

15. Solución de Problemas

15.1 «unable to connect to CloudStack API»

Diagnóstico:

curl -v "http://cs-mgmt:8080/client/api?command=listZones&response=json"
# Deve retornar JSON com as zonas

Causas comunes:

  • api_url incorrecta (puerto, path)
  • Firewall bloqueando puerto 8080 del FD host hacia CloudStack mgmt
  • API key/secret incorrectos
  • CloudStack management server detenido

Solución para certificado autofirmado:

# Em cloudstack.ini:
verify_ssl = false

15.2 Backup Cae a Modo api_only (Lento)

Síntoma: El log muestra falling back to api_only mode.

Diagnóstico:

ssh -i /opt/bacula/etc/cloudstack_ssh_key root@<kvm-host> "hostname"

Causas:

  • Clave SSH no autorizada en el KVM host
  • IP del KVM host retornado por CloudStack no es accesible desde el FD host
  • Firewall bloqueando SSH
  • Wrapper de forced-command mal configurado

15.3 Bitmap Creado pero Incrementales Transfieren Todo

Síntoma: El job incremental transfiere el mismo volumen que un full.

Diagnóstico:

# Verificar se o bitmap existe no QEMU via log:
grep -i "bitmap" /opt/bacula/working/podheitor-cloudstack-backend.log

Causa probable: Tras falla/crash, el bitmap puede marcarse como inválido. El plugin lo detecta y fuerza un full para reconstruirlo.

Solución: Deixar o primeiro job rodar como full (será automático). A partir do segundo job, CBT estará funcional.

15.4 Snapshots Huérfanos Acumulándose

Verificar:

ls /var/lib/bacula/cloudstack/snapshots/
# Comparar com CloudStack UI → Storage → Volume Snapshots

Limpieza manual:

# Via CloudStack CLI (cmk):
cmk list snapshots | grep podheitor
cmk delete snapshot id=<UUID>

El plugin limpia automáticamente en la próxima ejecución los snapshots con más de 30 minutos.

15.5 Receptor DR Rechaza Conexiones

Verificar firewall en el sitio DR:

iptables -L INPUT -n | grep 9310
# Deve mostrar ACCEPT

Verificar PSK: Ambos lados deben tener exactamente el mismo dr_psk.

Verificar logs del receptor:

journalctl -u bacula-fd | grep -i "LOG ERROR|replic"

15.6 Disco Lleno Durante Restauración

Síntoma: La restauración falla con no space left on device en working_dir.

Cálculo de espacio requerido:

working_dir: max(tamanho_maior_VM) + 10%
Exemplo: VM de 500 GB → necessita 550 GB livres em working_dir

Limpieza:

ls -lh /opt/bacula/working/podheitor-restore-*/
# Se restauração falhou, limpar manualmente:
rm -rf /opt/bacula/working/podheitor-restore-<jobid>/

15.7 VHDX Rechazado por Hyper-V

Causa: En versiones anteriores, el VHDX CRC32C se escribía como ceros. Corregido en v1.0.0.

Verificar versión:

/opt/bacula/bin/podheitor-cloudstack-backend --version
# Deve mostrar 1.0.0 ou superior

15.8 Preflight Reporta [MISS] en Instalación Correcta

Causa: En versiones anteriores, preflight buscaba solo en /opt/bacula/sbin/. Corregido en v1.0.0.

Verificar:

which podheitor-cloudstack-backend
# Deve mostrar /opt/bacula/bin/podheitor-cloudstack-backend
ls /opt/bacula/plugins/podheitor-cloudstack-backend
# Deve existir

16. Comparativa con Competidores

PodHeitor CloudStack vs. Bacula Enterprise CloudStack Plugin

Criterio Bacula Enterprise PodHeitor CloudStack
Tipo de Backup Volume snapshot (full) Block-level CBT + hash dedup
Incremental Diff de snapshots (API-level) Dirty bitmap + hash (real CBT)
Reducción Ventana Incremental ~30-50% 90-99%
Replicación DR ❌ No disponible ✅ Bitmap-push, RPO ~1min
Restauración Cruzada ❌ No disponible ✅ Proxmox, Hyper-V, VMware
Conversión de Formato ❌ No disponible ✅ qcow2↔vhdx↔vmdk
Métricas Prometheus ❌ No disponible ✅ Nativo
Log JSON ❌ No disponible ✅ Nativo
Lenguaje C/C++ propietario Rust (memory-safe, open)
Costo Licencia Enterprise Significativamente menor
Soporte multi-plataforma KVM, VMware KVM (nativo), cross a otros

PodHeitor CloudStack vs. Veeam Backup for CloudStack

Criterio Veeam PodHeitor CloudStack
Plataforma Propietaria Integra con Bacula (open)
Incremental CBT ✅ Vía CloudStack API ✅ Vía QMP bitmap (más eficiente)
Replicación DR ✅ Integrada en el mismo producto
Restauración Cruzada ✅ Para VMware ✅ Proxmox, Hyper-V, VMware
Deduplicación Servidor dedicado Nativa en el plugin
Costo Alto (por VM/socket) 50-70% menor
Integración Standalone Unificado con Bacula (todo integrado)
CloudStack 4.19/4.20

PodHeitor CloudStack vs. Acronis Cyber Backup

Criterio Acronis PodHeitor CloudStack
Agente Agente dentro de la VM Sin agente en la VM
Backup Guest-level (archivo) Block-level (imagen)
Consistencia VSS / quiesce quiesce via qemu-guest-agent
Replicación ✅ (Acronis Cloud) ✅ (site-to-site)
Cross-platform
Costo Alto (por agente/GB) Significativamente menor
Control En la nube Acronis On-premise total

17. Hoja de Ruta

v1.1.0 (Estimado: 2026-06)

  • Soporte para Ceph/RBD primary storage (modo nativo via librbd)
  • Dashboard Grafana preconfigurado (JSON bundle)
  • Soporte para Bacula 16.x (cuando sea lanzado)
  • Web UI mínima para estado de replicación
  • Prueba de integración end-to-end para restauración cruzada (lab)

v1.2.0 (Estimado: 2026-09)

  • Soporte para CloudStack 4.21 (cuando sea lanzado)
  • Integración de secondary storage compatible con S3
  • Backup agentless de VMs Windows via VSS (sin qemu-guest-agent)
  • CLI de gestión unificado
  • Soporte para múltiples entornos CloudStack (multi-zone, multi-region)

v2.0.0 (Estimado: 2026-12)

  • PodHeitor Unified Backup Platform: CloudStack + Proxmox + Hyper-V + vSphere bajo un único panel
  • Orquestación DR automatizada con playbooks
  • Integración con Bacularis (interfaz web de Bacula)
  • API REST para automatización externa (Ansible, Terraform)

18. Referencias


Contacto y Soporte

Heitor Faria

  • Email: heitor@opentechs.lat
  • WhatsApp / Telefone: +1 786 726-1749
  • WhatsApp / Telefone: +55 61 98268-4220

Para consultoría, implementación, soporte y capacitación:

  • Implementación del plugin en producción
  • Configuración de DR y failover
  • Migración entre hypervisors
  • Capacitación del equipo técnico
  • Personalizaciones e integraciones específicas

Copyright © 2026 Heitor Faria — Todos los derechos reservados.

Este documento y el software descrito son propiedad exclusiva de Heitor Faria. Reproducción parcial o total permitida solo con autorización expresa por escrito.

OFERTA ESPECIAL PARA CLIENTES DE BACULA ENTERPRISE, VEEAM, COMMVAULT Y NETBACKUP:

Traiga su propuesta de renovación. Garantizamos al menos 50% de descuento, con funcionalidades adicionales que los competidores no ofrecen.

heitor@opentechs.lat | +1 786 726-1749 | +55 61 98268-4220 (WhatsApp)

Licenciamiento

PodHeitor CloudStack es software propietario, distribuido por suscripción. Para condiciones comerciales, demostración técnica o diagnóstico gratuito de 30 minutos, habla con el equipo por los canales abajo.

¿Listo para evaluar?

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

Deja una respuesta