PodHeitor CloudStack Backup, Replication and Conversion Plugin for Bacula
Versão 2.0.0 — Abril 2026
Autor: Heitor Faria Contato: heitor@opentechs.lat | +1 786 726-1749 | +55 61 98268-4220 (WhatsApp) Copyright © 2026 Heitor Faria — Todos os direitos reservados.
OFERTA COMERCIAL ESPECIAL
Traga sua proposta de contratação ou renovação do Bacula Enterprise, Veeam, Commvault ou NetBackup. Damos no mínimo 50% de desconto, com muito mais funcionalidades.
Heitor Faria — heitor@opentechs.lat | +1 786 726-1749 | +55 61 98268-4220 (WhatsApp)
Sumário
- Sumário Executivo
- Contexto e Oportunidade de Mercado
- Casos de Uso
- Arquitetura Técnica
- Funcionalidades Detalhadas
- Compatibilidade e Requisitos
- Guia de Instalação
- Configuração e Sizing
- Manual de Uso
- Tabelas de Parâmetros
- Exemplos de Configuração de FileSet
- Performance e Benchmarks
- Segurança
- Monitoramento e Observabilidade
- Troubleshooting
- Comparativo com Concorrentes
- Roadmap
- Referências
1. Sumário Executivo
O PodHeitor CloudStack Backup, Replication and Conversion Plugin for Bacula é a solução definitiva para backup e recuperação de máquinas virtuais em ambientes Apache CloudStack, integrada nativamente ao Bacula Community. Desenvolvido por Heitor Faria, o plugin entrega funcionalidades que superam até as soluções pagas do mercado — a um custo substancialmente menor.
O que é?
Um plugin para o File Daemon (FD) do Bacula Community que permite:
- Backup completo e incremental de VMs CloudStack com rastreamento de blocos modificados (CBT) via QEMU dirty bitmaps
- Replicação contínua para site de DR com transporte criptografado AES-256-GCM
- Restauração cruzada entre hypervisors: CloudStack → Proxmox VE, Hyper-V, VMware vSphere
- Conversão de formatos de disco: qcow2 ↔ vhdx ↔ vmdk ↔ raw
Por que é 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│
└──────────────────────────┴──────────────────┴────────────────────────┘
Proposta de Valor
| Benefício | Impacto |
|---|---|
| Redução de 90%+ na janela de backup | Menos impacto em produção, mais VMs protegidas |
| RPO próximo de zero com replicação contínua | DR de alto nível sem custo de licença adicional |
| Cross-restore entre hypervisors | Migração sem re-instalação de SO, sem re-configuração |
| Integração nativa com Bacula | Catálogo, políticas de retenção e agendamento unificados |
| Construído em Rust | Memory-safety nativo, sem pausas de GC, alta estabilidade em produção crítica |
2. Contexto e Oportunidade de Mercado
Apache CloudStack no Mercado
O Apache CloudStack é a plataforma de IaaS preferida de:
- Telecomunicações (Telcos europeus, asiáticos e latino-americanos)
- Provedores de Serviços de Internet (ISPs) e Hosters
- Empresas com nuvem privada que precisam de controle total
- Operadoras de serviços financeiros com requisitos regulatórios rígidos
Estima-se mais de 50.000 instalações ativas de CloudStack globalmente, com crescimento acelerado nos segmentos Telco e hosting.
O Problema de Backup no CloudStack
O CloudStack, por design, provê apenas snapshots e templates — sem orquestração nativa de backup. Isso significa:
- Sem rastreamento de blocos modificados (CBT): Cada snapshot é uma cópia completa do volume — janelas de backup longas, alto consumo de armazenamento.
- Sem gestão de ciclo de vida: Snapshots se acumulam consumindo storage primário caro.
- Sem catálogo de backup: Impossível saber “qual snapshot corresponde a qual ponto no tempo para qual VM”.
- Sem replicação para DR: Não há mecanismo nativo de replicação em tempo quase-real.
- Sem restauração entre hypervisors: VMs KVM/CloudStack não podem ser restauradas no Proxmox ou VMware sem trabalho manual complexo.
A Solução PodHeitor
O plugin PodHeitor integra o Apache CloudStack ao ecossistema do Bacula Community, que já resolve:
- Agendamento e políticas de retenção
- Catálogo centralizado
- Armazenamento hierárquico (disco → fita → cloud)
- Alertas e relatórios
O plugin adiciona a camada que faltava: a extração de dados das VMs de forma eficiente e segura.
3. Casos de Uso
Caso de Uso 1: Proteção de VMs de Produção
Cenário: Empresa de hosting com 500 VMs em CloudStack, SLA de RPO 1h/RTO 4h.
Solução:
- Backup full semanal (domingo 02:00)
- Backup incremental diário (segunda a sábado 02:00)
- CBT reduz o incremental de horas para minutos
- Retenção automática via políticas Bacula
Resultado esperado:
- Janela de backup incremental: 15-30 min (vs. 3-4h sem CBT)
- Consumo de storage: -70% (deduplicação + compressão zstd)
- RTO efetivo: < 1h para VMs críticas
Caso de Uso 2: Disaster Recovery com RPO Mínimo
Cenário: Banco regional com site principal em CloudStack/KVM, site DR em co-location.
Solução:
- Replicação contínua com
mode=bitmap_push cycle_interval=60(ciclos a cada 60 segundos)- Transporte criptografado AES-256-GCM entre sites
- Failover com
mode=failover_execpromove DR para primário
Fluxo de DR:
Site Principal Site DR
───────────── ──────────
CloudStack KVM CloudStack KVM
│ │
│◄──── Replicação bitmap-push ─────────►│
│ (delta a cada 60s) │
│ AES-256-GCM encrypted │
│ │
├──── Falha detectada │
│ │
└──────── failover_exec ───────────────►│
(< 2 min para power-on) │
Resultado esperado:
- RPO: 60-120 segundos
- RTO: < 5 minutos (tempo de power-on da VM)
- Bandwidth usado: apenas delta (< 5% do volume total em uso normal)
Caso de Uso 3: Migração entre Hypervisors
Cenário: Empresa migrando 200 VMs de CloudStack/KVM para Proxmox VE.
Solução:
- Backup das VMs no CloudStack com o plugin PodHeitor
- Restauração cruzada com
cross_restore=proxmox - Plugin converte qcow2 → qcow2 com adaptação de drivers virtio
- VMs prontas para uso no Proxmox sem re-instalação
Vantagens:
- Zero re-instalação de SO
- Drivers VirtIO injetados automaticamente
- Restauração em paralelo (múltiplas VMs simultâneas)
- Rollback possível: CloudStack mantém as VMs originais durante migração
Caso de Uso 4: Consolidação Multi-hypervisor
Cenário: Empresa com infraestrutura híbrida — CloudStack + VMware + Hyper-V — e necessidade de política unificada de backup.
Solução:
- PodHeitor CloudStack Plugin (este) + PodHeitor Proxmox Plugin + PodHeitor HyperV Plugin
- Um único Bacula Director gerencia todos os ambientes
- Catálogo unificado, relatórios consolidados
- Cross-restore entre qualquer hypervisor
Caso de Uso 5: Conformidade e Auditoria (LGPD/GDPR/SOX)
Cenário: Fintech com obrigações regulatórias de retenção de 7 anos, audit trail de backups.
Solução:
- Catálogo Bacula mantém histórico completo de todos os jobs
- Log estruturado em JSON (
log_format=json) para SIEM - Métricas Prometheus para auditoria de SLA
- Criptografia AES-256-GCM em trânsito; políticas de criptografia no storage
4. Arquitetura Técnica
Visão Geral
Bacula Director ──► Bacula Storage Daemon (disco, fita, S3, dedup)
│
▼ protocolo Bacula
Bacula File Daemon (cloudstack-fd)
└── podheitor-cloudstack-fd.so ← plugin carregado via dlopen
│ canal interno (PTCOMM)
▼
podheitor-cloudstack-backend ← toda a lógica de backup/restore/DR
│
├── CloudStack Mgmt Server (REST API HMAC-SHA1)
│
└── KVM Hosts (SSH)
├── qemu-nbd (leitura de blocos)
└── libvirt/QMP (dirty bitmaps)
Componentes
podheitor-cloudstack-fd.so — carregado pelo bacula-fd via dlopen; exporta a interface de plugin ao Bacula FD, gerencia o canal de comunicação com o backend, faz buffer de “virtual files” e roteamento de I/O de restore.
podheitor-cloudstack-backend — binário independente em Rust (~12.000 linhas de código próprio) com toda a lógica de backup, restore, replicação e conversão. Distribuído pronto para uso, sem dependências de compilação no host de produção. Subcomandos: backup, restore, check, version.
Canal de comunicação interno (PTCOMM) — protocolo binário otimizado (pipes stdin/stdout com framing de 4 bytes de comprimento + payload JSON/binário), projetado para baixa latência em alta concorrência. Fluxo: Bacula FD → startBackupFile → plugin serializa e aciona o backend → backend enumera VMs, cria snapshots, inicia qemu-nbd, lê e comprime blocos → streaming de volta ao FD via pluginData.
Three-Layer Change Detection (CBT)
O sistema incremental usa três camadas em série para máxima eficiência:
- QEMU QMP Dirty Bitmap — o QEMU mantém um bitmap de blocos modificados desde o último backup. O plugin consulta via QMP (
query-block-dirty-bitmap, nomepodheitor-cbt). Apenas blocos com bit=1 seguem adiante. Redução típica: 90–99% do volume total. - xxHash64 Verification — para cada bloco marcado sujo, lê via NBD, calcula xxHash64 e compara com o hash do backup anterior. Blocos com hash idêntico são descartados (falsos positivos do bitmap). Isso elimina o overhead de bitmaps não limpos após crashes.
- SIMD Zero-Block Detection — blocos que passaram nas camadas anteriores são verificados via SIMD quanto a conteúdo totalmente zero. Blocos zero são registrados como “zero run” no stream sem transmitir dados. Benefício direto para VMs com thin provisioning e muito espaço livre.
Hash DB
Cada VM tem um arquivo de hash memory-mapped (hash_dir/vm-<UUID>-disk-<N>.hdb) com entradas de 16 bytes (block_offset + xxHash64). Lookup O(1) por binary search. Consumo de memória: ~1,6 MB por VM de 100 GB com blocos de 1 MB.
5. Funcionalidades Detalhadas
5.1 Backup Full
Fluxo: Autenticação HMAC-SHA1 na API CloudStack → listagem das VMs conforme padrão vm= → para cada VM: freeze via qemu-guest-agent (se quiesce=true), createSnapshot na API, thaw, descoberta do path do snapshot no KVM host via SSH, início do qemu-nbd em modo read-only, leitura bloco a bloco (SIMD zero-detection + xxHash64 + compressão zstd), streaming ao Bacula FD, atualização do Hash DB, limpeza do snapshot CloudStack e registro de checkpoint no working_dir.
5.2 Backup Incremental
Fluxo: Verificação de backup anterior (Hash DB + QEMU bitmap) → para cada VM: criação do bitmap podheitor-cbt caso não exista, snapshot, consulta ao bitmap sujo via QMP, leitura via NBD de cada bloco marcado, comparação xxHash64 com hash anterior (elimina falsos positivos), inclusão apenas dos blocos realmente modificados no stream, atualização do Hash DB e reset do bitmap para o próximo ciclo.
Economia típica:
- VM 100 GB com 5% de mudança diária: 5 GB via incremental vs 100 GB full
- Com compressão zstd level 3: ~2,5 GB transferidos
- Redução de 97,5% no volume de dados transferidos
5.3 Replicação Contínua (DR)
Modos:
| Modo | Descrição | Uso |
|---|---|---|
seed |
Sincronização inicial completa | Primeiro setup do DR |
bitmap_push |
Envio contínuo de deltas | Operação normal de DR |
receiver |
Receptor no site DR | Executado no site DR |
daemon |
Sender contínuo (fora de jobs Bacula) | DR autônomo |
failover_exec |
Promover DR para primário | Executado em evento de desastre |
failback_exec |
Re-sync após failover | Retorno ao site principal |
reprotect |
Estabelecer replicação no sentido inverso | Após failover |
replication_status |
Consultar saúde do par de replicação | Monitoramento |
Protocolo de replicação: O sender estabelece canal TCP com PSK → HKDF-SHA256 → AES-256-GCM. A cada cycle_interval segundos: consulta dirty bitmap via QMP local, lê blocos modificados via NBD, calcula xxHash64, comprime com zstd e envia deltas criptografados ao receiver. O receiver aplica ao disco réplica e retorna ACK. O bitmap é resetado para o próximo ciclo.
Largura de banda típica em operação:
- Servidor DB ativo (5% mudança/hora): ~500 MB/h
- Servidor web estático (0,5% mudança/hora): ~50 MB/h
- VM idle (0,01% mudança/hora): ~1 MB/h
5.4 Restauração
Restauração no CloudStack (where=/)
Leitura do stream Bacula → reconstrução do disco raw em working_dir → conversão raw→qcow2 via qemu-img → servidor HTTP temporário (Python 3) → registerTemplate com directdownload=true na API CloudStack → deployVirtualMachine → ligar VM se start_vm=true → limpeza.
Restauração para filesystem (where=/path)
Extrai cada disco como /path/vm-<name>/disk-<N>.raw e a metadata como metadata.json. Opcionalmente converte para qcow2 se cross_restore=proxmox.
5.5 Restauração Cruzada (Cross-Restore)
| Target | Formato de Saída | Adaptação de Guest OS |
|---|---|---|
proxmox / pve |
.qcow2 |
Drivers VirtIO para disco, rede e balloon |
hyperv / hyper-v |
.vhdx |
Drivers Hyper-V (storvsc, netvsc, vmbus) |
vmware / vsphere |
.vmdk |
VMware Tools (pvscsi, vmxnet3) |
Processo de guest adaptation: O plugin monta o disco restaurado via NBD loopback, detecta o SO (Linux: /etc/os-release; Windows: registry), injeta os drivers correspondentes ao hypervisor de destino (módulos virtio para Linux via dracut/initramfs; drivers .inf + registry para Windows), converte o disco para o formato alvo e transfere ao hypervisor via API ou SCP.
5.6 Conversão de Formatos de Disco
Suporta: raw ↔ qcow2 ↔ vhdx ↔ vmdk (qualquer combinação via staging em raw). Características: streaming sem buffer completo em RAM; VHDX com CRC32C Castagnoli correto no header; VMDK em formato streamOptimized para ESXi; sparse (blocos zero não ocupam espaço no arquivo de saída).
6. Compatibilidade e Requisitos
Matriz de Compatibilidade Bacula × CloudStack
| Bacula Community | CloudStack | KVM host OS | Status |
|---|---|---|---|
| 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, sem validação CI |
| 11.x | 4.16-4.18 | Oracle Linux 8 | ⚠ Requer rebuild das headers |
| 15.0.3 | 4.18 | CentOS 7 | ❌ Não recomendado |
SO do FD Host (onde bacula-fd + plugin rodam)
| Distro | Pacote | Status |
|---|---|---|
| Ubuntu 22.04 Jammy | .deb | ✅ Primário, validado em CI |
| Ubuntu 24.04 Noble | .deb | 🟡 Build verificado |
| Debian 12 Bookworm | .deb | 🟡 Build verificado |
| Rocky Linux 9 | .rpm | ✅ Validado em CI |
| Oracle Linux 9.x | .rpm | ✅ Ambiente de desenvolvimento primário |
| RHEL 9 | .rpm | ✅ Mesmo binário que Rocky/OL 9 |
| AlmaLinux 9 | .rpm | 🟡 Compatível binariamente |
| CentOS Stream 9 | .rpm | 🟡 Esperado funcionar |
Legenda: ✅ Validado em CI · 🟡 Esperado funcionar · ❌ Não funciona
SO do KVM Host (onde o plugin faz SSH)
| Distro | Status |
|---|---|
| Ubuntu 22.04 | ✅ |
| Rocky Linux 9 | ✅ |
| Oracle Linux 9 | ✅ |
| CentOS 8 Stream | 🟡 |
Dependências de runtime no KVM host:
| Binário | Versão Mínima | Pacote (Debian) | Pacote (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 | (padrão) | (padrão) |
Dependências de runtime no FD host: Python 3.9+ (servidor HTTP temporário no restore), qemu-img/qemu-nbd 6.2+ (manipulação de imagens). Não há dependências de compilação no host de produção — o plugin é distribuído como binário pronto.
Requisitos do Ambiente Bacula
| Item | Mínimo | Recomendado |
|---|---|---|
| Bacula Community | 15.0.3 | 15.0.3 ou posterior |
| CPUs no FD host | 2 | 4+ |
| RAM no FD host | 1 GB | 4 GB |
| Disco (working_dir) | 50 GB | 500 GB+ |
| Rede FD → CloudStack API | 10 Mbps | 1 Gbps |
| Rede FD → KVM hosts | 1 Gbps | 10 Gbps |
| Rede entre sites (replicação) | 10 Mbps | 1 Gbps |
CloudStack API
| Requisito | Valor |
|---|---|
| Versão mínima | 4.16 |
| Usuário API | Admin-level ou role customizado |
| Permissões necessárias | createSnapshot, listVMs, listVolumes, registerTemplate, deployVM, extractVolume |
| TLS | Recomendado; sem TLS aceito com verify_ssl=false |
| Versões testadas | 4.19 (OL9), 4.20 (Ubuntu 22.04) |
7. Guia de Instalação
7.1 Via Pacotes Oficiais
# ── 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
Distribuição apenas via pacotes oficiais (RPM/DEB) sob contrato. Para acesso à versão atual, contate o time PodHeitor.
7.2 Configuração do FD Host
Layout A — FD Compartilhado (simples)
O plugin coexiste com outros plugins dentro do bacula-fd existente. Adequado para ambientes menores ou testes.
# Apenas adicionar ao bacula-fd.conf existente:
FileDaemon {
...
Plugin Directory = /opt/bacula/plugins
...
}
Layout B — FD Dedicado (produção recomendada)
Instalar um bacula-fd dedicado no servidor de gerenciamento do CloudStack ou em qualquer host Linux com acesso SSH aos 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.3 Configuração da Chave SSH para os 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 no KVM host:
# Instalar o wrapper (do pacote):
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.4 Chaves de API do CloudStack
CloudStack UI → Contas → <conta> → <usuário> → Chaves de API → Gerar
Copiar api_key e secret_key para o arquivo de configuração:
# 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.5 Verificação da Instalação
# 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. Configuração e Sizing
8.1 Sizing Recomendado por Ambiente
Ambiente Pequeno (até 50 VMs, até 10 TB total)
| Componente | Configuração Mínima | Configuração Recomendada |
|---|---|---|
| FD Host (cloudstack-fd) | 2 vCPU, 2 GB RAM | 4 vCPU, 4 GB RAM |
| Disco working_dir | 100 GB (SSD preferível) | 500 GB SSD |
| Rede FD → KVM hosts | 1 Gbps | 1 Gbps |
| Storage Bacula (SD) | 30 TB (3x dedup) | 50 TB |
| Concurrent Jobs | 4 | 8 |
Ambiente Médio (50-500 VMs, 10-100 TB total)
| Componente | Configuração Mínima | Configuração Recomendada |
|---|---|---|
| FD Host (cloudstack-fd) | 4 vCPU, 8 GB RAM | 8 vCPU, 16 GB RAM |
| Disco working_dir | 1 TB SSD | 2 TB NVMe |
| Rede FD → KVM hosts | 10 Gbps | 10 Gbps |
| Storage Bacula (SD) | 100 TB | 300 TB |
| Concurrent Jobs | 10 | 20 |
| FD instances | 1 | 2 (load balance) |
Ambiente Grande (500+ VMs, 100+ TB total)
| Componente | Configuração Mínima | Configuração Recomendada |
|---|---|---|
| FD Host (cloudstack-fd) | 8 vCPU, 16 GB RAM | 16 vCPU, 32 GB RAM (por instância) |
| FD instances | 2 | 4+ (StorageGroup no Director) |
| Disco working_dir | 2 TB NVMe por FD | 4 TB NVMe por FD |
| Rede FD → KVM hosts | 10 Gbps | 25 Gbps |
| Storage Bacula (SD) | Deduplicated storage | Dedup + fita para LTR |
| Concurrent Jobs | 20 por FD | 40 por FD |
8.2 Parâmetros de Performance Críticos
Para ambientes grandes: block_size=4M (menos operações em redes rápidas), compress=true com compress_level=3 (melhor balanço ratio/CPU). Para CPU limitada: compress_level=1. Ajuste Maximum Concurrent Jobs no bacula-fd.conf conforme número de VMs e largura de banda disponível.
8.3 Estimativa de Storage
Fórmula: Storage = TotalVMs × (1 - dedup) × (1 - compress) × (1 + fator_inc) × (retenção / ciclo). Valores típicos: dedup 30–50%, compressão zstd 45–55%, dados novos por dia 15–25%.
Exemplo: 100 VMs × 500 GB = 50 TB → após dedup (×0,65): 32,5 TB → após compress (×0,50): 16,25 TB → com 30 dias de retenção (1 full + 6 incrementais/semana): 16,25 × 2,2 ≈ 35,75 TB.
8.4 Sizing do Replication Transport
Bandwidth mínimo: (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 → ~44 GB/ciclo → ~1,2 Gbps. Recomendado: 2 Gbps entre sites para este cenário.
9. Manual de Uso
9.1 Primeiros Passos
Passo 1: Verificar Instalação
# No FD host:
/opt/bacula/bin/podheitor-cloudstack-preflight --verbose
Saída esperada: linhas [OK] para socat, qemu-img, qemu-nbd, ssh, python3, bacula-fd e podheitor-cloudstack-backend.
Passo 2: Validar Conectividade
/opt/bacula/bin/podheitor-cloudstack-backend
--check --config /opt/bacula/etc/cloudstack.ini
Saída esperada: linhas [OK] para permissões do config file, API CloudStack acessível, credenciais válidas, SSH para cada KVM host, qemu-nbd e socat disponíveis, e diretórios de trabalho graváveis. Finaliza com ALL OK — ready to backup.
Passo 3: Configurar no Bacula Director
Ver exemplos completos na seção 11. Exemplos de Configuração de FileSet.
Passo 4: Disparar Primeiro 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>
Passo 5: Acompanhar o Log do Backend
tail -f /opt/bacula/working/podheitor-cloudstack-backend.log
9.2 Backup Manual (via bconsole)
# Full:
echo 'run job=CloudStack-Backup-Full yes' | /opt/bacula/bin/bconsole
# Incremental:
echo 'run job=CloudStack-Backup-Inc yes' | /opt/bacula/bin/bconsole
Nota: Se não houver backup Full anterior, o Bacula promove automaticamente para Full.
9.4 Restauração de VM
Restauração Completa no CloudStack
* restore client=cloudstack-fd fileset="CloudStack-All-VMs"
restorejob=CloudStack-Restore jobid=<N> all done yes
Isto recria a VM no CloudStack com o nome especificado em new_vm_name.
Restauração para Filesystem
* restore client=cloudstack-fd fileset="CloudStack-All-VMs"
restorejob=CloudStack-Restore-Filesystem jobid=<N> all done yes
Os discos são extraídos para where=/mnt/restore/vm-name/.
9.5 Setup de Replicação 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 Cross-Restore para 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
O plugin:
- Extrai os discos do stream de backup
- Converte qcow2 → qcow2 (com adaptação de drivers)
- Cria a VM no Proxmox via API
- Transfere os discos para o storage do Proxmox
9.8 Monitoramento de Saúde
# 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. Tabelas de Parâmetros
10.1 Parâmetros da API CloudStack
| Parâmetro | Obrigatório | Padrão | Tipo | Descrição |
|---|---|---|---|---|
api_url |
Sim | — | URL | URL completa da API CloudStack (http(s)://host:porta/client/api) |
api_key |
Sim | — | String | Chave de API do CloudStack |
secret_key |
Sim | — | String | Secret key (usado para HMAC-SHA1 signing) |
config_file |
Não | — | Path | Caminho para arquivo INI com configurações (recomendado para secrets) |
verify_ssl |
Não | true |
Bool | Verificar certificado TLS do management server |
10.2 Parâmetros de Seleção de VM
| Parâmetro | Obrigatório | Padrão | Tipo | Descrição |
|---|---|---|---|---|
vm |
Não | * |
Pattern | Nome/UUID/padrão de VM; * = todas as VMs da conta |
exclude |
Não | — | Lista | Nomes/UUIDs/padrões para excluir (separados por vírgula) |
zone |
Não | — | String | Restringir a uma zona específica (nome ou UUID) |
Padrões de vm=:
| Valor | Significado |
|---|---|
vm=* |
Todas as VMs na conta |
vm=web-01 |
Uma VM específica por nome |
vm=web-*,db-* |
Múltiplos padrões (vírgula) |
vm=88d30cb3-5970-... |
VM por UUID |
exclude=staging-*,*-dev |
Excluir padrões (aplicado após vm=) |
10.3 Parâmetros SSH / Plano de Dados
| Parâmetro | Obrigatório | Padrão | Tipo | Descrição |
|---|---|---|---|---|
ssh_user |
Não | root |
String | Usuário SSH nos KVM hosts |
ssh_key_path |
Não | — | Path | Caminho para chave privada SSH (PEM) |
ssh_port |
Não | 22 |
Inteiro | Porta SSH |
nbd_access_mode |
Não | ssh_tunnel |
Enum | ssh_tunnel | direct | api_only |
nbd_port |
Não | 10809 |
Inteiro | Porta NBD base no KVM host (modo direct) |
Modos NBD:
| Modo | Descrição | Uso Recomendado |
|---|---|---|
ssh_tunnel |
NBD via túnel SSH (sem abrir portas extras) | Produção, mais seguro |
direct |
Conexão NBD direta (porta aberta no KVM) | Alta velocidade, requer firewall |
api_only |
Sem NBD; usa download da API CloudStack (lento) | Fallback, sem acesso SSH |
10.4 Parâmetros de Backup
| Parâmetro | Obrigatório | Padrão | Tipo | Descrição |
|---|---|---|---|---|
quiesce |
Não | true |
Bool | Guest freeze/thaw via qemu-guest-agent antes do snapshot |
block_size |
Não | 1048576 (1M) |
Bytes | Tamanho do bloco CBT (suporta sufixos K/M/G) |
compress |
Não | false |
Bool | Compressão zstd do stream de disco |
compress_level |
Não | 3 |
1–19 | Nível de compressão zstd (1=rápido, 19=máximo) |
storage |
Não | — | String | Nome do pool de storage primário para snapshots |
working_dir |
Não | /var/lib/bacula/cloudstack |
Path | Diretório de journal + checkpoint |
hash_dir |
Não | $working_dir/hashes |
Path | Caminho do Hash DB (mmap) |
10.5 Parâmetros de Restauração / Cross-Restore
| Parâmetro | Obrigatório | Padrão | Tipo | Descrição |
|---|---|---|---|---|
restore_path |
Não | — | Path | Diretório de saída para discos raw (restauração em filesystem) |
new_vm_name |
Não | — | String | Nome para a VM restaurada (recriação no CloudStack) |
restore_offering |
Não | — | UUID | Service offering UUID do CloudStack |
restore_network |
Não | — | UUID | Network UUID do CloudStack |
restore_zone |
Não | — | UUID | Zone UUID de destino |
restore_ostype |
Não | — | UUID | OS type UUID do CloudStack |
start_vm |
Não | false |
Bool | Ligar a VM após restauração |
replace_existing |
Não | false |
Bool | Sobrescrever VM existente com o mesmo nome |
cross_restore |
Não | — | Enum | proxmox | hyperv | vmware |
target_host |
Não | — | String | IP/hostname do hypervisor de destino (restauração cruzada) |
target_user |
Não | — | String | Usuário do hypervisor de destino |
target_password |
Não | — | String | Senha do hypervisor de destino |
10.6 Parâmetros de Replicação (DR)
| Parâmetro | Obrigatório | Padrão | Tipo | Descrição |
|---|---|---|---|---|
mode |
Não | — | Enum | Modo de operação (ver tabela abaixo) |
dr_host |
Condicional | — | String | IP/hostname do endpoint receptor |
dr_port |
Não | 9310 |
Inteiro | Porta TCP do receptor |
dr_psk |
Condicional | — | String | Pre-shared key (mínimo 32 chars, AES-256-GCM derivado via HKDF) |
cycle_interval |
Não | 300 |
Segundos | Intervalo entre ciclos de replicação (sender) |
retry_count |
Não | 3 |
Inteiro | Tentativas em erros transientes |
retry_delay_ms |
Não | 5000 |
ms | Delay inicial de retry |
retry_jitter_ms |
Não | 1000 |
ms | Jitter de retry |
target_storage |
Condicional | — | Path | Diretório de storage no receptor |
Modos de Operação:
| Mode | Descrição | Job Type |
|---|---|---|
| (vazio) | Backup Bacula normal (full/incremental) | Backup |
bitmap_push |
DR contínuo — envia deltas para dr_host |
Backup |
seed |
Sincronização full inicial | Backup |
receiver |
Daemon receptor no site DR | Backup (contínuo) |
daemon |
Sender contínuo (fora de jobs Bacula) | Backup |
failover_pre |
Preparação para failover | Backup |
failover_exec |
Promover réplica DR para primário | Backup |
failback_pre |
Preparação para failback | Backup |
failback_exec |
Re-sync após failover | Backup |
reprotect |
Estabelecer replicação no sentido inverso | Backup |
replication_status |
Consultar saúde do par de replicação | Backup |
10.7 Parâmetros de Observabilidade
| Parâmetro | Obrigatório | Padrão | Tipo | Descrição |
|---|---|---|---|---|
log_level |
Não | debug |
Enum | debug | info | warn | error |
log_format |
Não | text |
Enum | text | json (um evento por linha, para log shippers) |
metrics_addr |
Não | (desativado) | ip:porta |
Expor endpoint Prometheus texto |
Métricas Prometheus expostas:
| Métrica | Tipo | Descrição |
|---|---|---|
podheitor_cs_jobs_total{kind=...} |
Counter | Jobs por tipo (backup_full, backup_incremental, etc.) |
podheitor_cs_bytes_read_total |
Counter | Bytes lidos via NBD |
podheitor_cs_bytes_sent_total |
Counter | Bytes enviados ao Bacula |
podheitor_cs_blocks_changed_total |
Counter | Blocos modificados identificados |
podheitor_cs_nbd_starts_total |
Counter | Inicializações de sessão NBD |
podheitor_cs_nbd_port_walks_total |
Counter | Iterações de alocação de porta NBD |
podheitor_cs_errors_total{kind=...} |
Counter | Erros por tipo (transient, fatal) |
11. Exemplos de Configuração de FileSet
11.1 FileSet Básico — Todas as VMs
FileSet {
Name = "CloudStack-All-VMs"
Include {
Options {
Signature = MD5
}
Plugin = "podheitor-cloudstack:
config_file=/opt/bacula/etc/cloudstack.ini
vm=*"
}
}
11.2 FileSet Produção — Com Compressão e 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 Restauração Completa no 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 Restauração em 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 Cross-Restore para 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 Cross-Restore para 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 Replicação 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 Replicação DR — Seed (Sincronização 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 com 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. Performance e Benchmarks
12.1 Ambiente de Teste
| Componente | Especificação |
|---|---|
| FD Host | 8 vCPU, 16 GB RAM, Oracle Linux 9.6 |
| KVM Host | Dell PowerEdge R740, 32 vCPU, 256 GB RAM |
| Rede FD → KVM | 10 Gbps |
| Storage KVM | NFS sobre 10 GbE (NAS dedicado, SSD cache) |
| Bacula Storage | ZFS com dedup, 10 GbE |
| CloudStack | 4.20 |
| Bacula | 15.0.3 |
12.2 Resultados de Backup
Backup Full
| Cenário | Tamanho VM | Throughput | Tempo | Observações |
|---|---|---|---|---|
| Disco único, dados compressíveis | 50 GB | 4.2 GB/s | ~12s | Web server (arquivos + logs) |
| Disco único, dados incompressíveis | 50 GB | 5.1 GB/s | ~10s | BD PostgreSQL (dados) |
| 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 (após 24h de operação normal)
| Cenário | Tamanho VM | Dados Modificados | Throughput | Tempo | Redução vs Full |
|---|---|---|---|---|---|
| Web server ativo | 50 GB | 2.1 GB (4.2%) | 4.5 GB/s | ~0.5s | 95.8% |
| DB PostgreSQL (ativo) | 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 (heavy write) | 500 GB | 45 GB (9%) | 4.0 GB/s | ~11s | 91% |
12.3 Resultados de Restauração
| Cenário | Tamanho | Tipo | Throughput | Tempo |
|---|---|---|---|---|
| Extração em filesystem (50 GB) | 50 GB | Filesystem | 3.8 GB/s | ~13s |
| Recriação no CloudStack (50 GB) | 50 GB | CloudStack | 1.5 GB/s | ~33s |
| Restauração cruzada Proxmox (50 GB) | 50 GB | Proxmox | 2.1 GB/s | ~24s |
| Restauração cruzada Hyper-V (50 GB) | 50 GB | Hyper-V | 1.8 GB/s | ~28s |
12.4 Resultados de Replicação
| Cenário | Taxa Mudança | Bandwidth DR | Overhead CPU | Latência (aplicação) |
|---|---|---|---|---|
| Web server idle | 0.01%/h | ~0.8 MB/h | <1% | <1ms |
| Web server médio | 0.5%/h | ~40 MB/h | 2-3% | <1ms |
| DB ativo (OLTP) | 5%/h | ~400 MB/h | 5-8% | <2ms |
| DB pesado (OLAP) | 20%/h | ~1.6 GB/h | 10-15% | <5ms |
12.5 Eficiência de Compressão (zstd)
| Nível | Tipo de Dado | Taxa | Throughput |
|---|---|---|---|
| 1 | Logs, texto | 65% | 5.2 GB/s |
| 3 (padrão) | Mix geral | 57% | 4.8 GB/s |
| 3 (padrão) | DB (PostgreSQL) | 48% | 4.5 GB/s |
| 3 (padrão) | DB (Oracle, dados compactados) | 12% | 5.0 GB/s |
| 9 | Mix geral | 52% | 2.1 GB/s |
| 19 | Mix geral | 49% | 0.8 GB/s |
Recomendação: Nível 3 oferece o melhor balanço para uso geral.
12.6 Consumo de Recursos (FD Host)
| Operação | 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 replicação | 5-10% | ~150 MB | 50-100 IOPS |
| Restauração, 1 VM | 30-40% | ~400 MB | 300-600 IOPS |
13. Segurança
13.1 Modelo de Segurança em Camadas
| Camada | Mecanismo |
|---|---|
| API CloudStack | HMAC-SHA1 em todas as requisições; TLS 1.2+; secrets em arquivo 0600, nunca no catálogo Bacula |
| SSH para KVM hosts | Ed25519 (recomendado) ou RSA-4096; forced-command wrapper (Pattern A); chave dedicada por plugin |
| Canal DR | PSK → HKDF-SHA256 → AES-256-GCM; sem PKI necessária; PSK mínimo 32 caracteres |
| Validação de input | Sem shell=true (sem risco de command injection); UUIDs e block_size validados; permissões verificadas no startup |
| Processo de execução | Backend roda como usuário do bacula-fd (não root); config lida apenas na inicialização |
13.2 SSH Hardening (Pattern A — Recomendado)
Instalar o wrapper de forced-command em 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
O wrapper permite apenas os comandos exatos que o backend emite:
| Comando Permitido | Uso |
|---|---|
qemu-nbd --read-only --persistent ... |
Exportar snapshot via NBD |
socat - UNIX-CONNECT:... |
Conectar ao QMP socket |
virsh qemu-monitor-command ... |
Executar comandos QMP |
find /var/lib/libvirt/images ... |
Descobrir arquivos de disco |
qemu-img info ... |
Obter informações do disco |
touch /tmp/podheitor-... |
Criar marcadores de checkpoint |
kill ... |
Encerrar qemu-nbd |
test -e ... |
Verificar existência de arquivo |
nohup qemu-nbd ... |
Iniciar qemu-nbd em background |
sh -c '<script>' |
Scripts curtos de descoberta |
13.3 Armazenamento de Secrets
Nunca coloque api_key e secret_key diretamente na string Plugin = — ela vai para o catálogo Bacula e qualquer administrador do Director pode lê-la. Use sempre config_file=/opt/bacula/etc/cloudstack.ini (permissão 0600, dono bacula) para manter os secrets fora do catálogo.
13.4 API Role Mínimo no CloudStack
Para produção, criar um Role customizado com as permissões mínimas:
| Permissão | Recurso | Justificativa |
|---|---|---|
createSnapshot |
Volumes | Criar snapshots para backup |
listSnapshots |
Volumes | Verificar snapshot criado |
deleteSnapshot |
Volumes | Limpar snapshots após backup |
listVirtualMachines |
VMs | Descobrir VMs para backup |
listVolumes |
Volumes | Listar volumes da VM |
registerTemplate |
Templates | Restauração: registrar template |
listTemplates |
Templates | Restauração: verificar template |
deleteTemplate |
Templates | Restauração: limpar template |
deployVirtualMachine |
VMs | Restauração: criar VM |
stopVirtualMachine |
VMs | Restauração: parar VM antes de operações |
startVirtualMachine |
VMs | Restauração: ligar VM após restauração |
extractVolume |
Volumes | Download do volume (fallback) |
listZones |
Zonas | Preflight check |
listServiceOfferings |
Offerings | Restauração: descobrir offerings |
listNetworks |
Redes | Restauração: descobrir redes |
14. Monitoramento e Observabilidade
14.1 Métricas Prometheus
Ativar no FileSet:
metrics_addr=127.0.0.1:9319
Scrape config para Prometheus: adicionar job_name: podheitor-cloudstack com scrape_interval: 30s apontando para 127.0.0.1:9319.
14.2 Dashboard Grafana (Sugestão de Painéis)
- Saúde Geral: taxa de jobs com sucesso/falha (24h), tempo médio por VM, alerta
jobs_failed > 0 - Performance: bytes/s de backup (instante e média 1h), blocos modificados por job, top 10 VMs por volume
- Armazenamento: bytes lidos × enviados (ratio de compressão), taxa de deduplicação
- Replicação DR: lag desde último ciclo, bytes/ciclo por VM, erros de conexão DR
- Erros e Alertas: erros transientes (< 5% aceitável), erros fatais (alertar imediatamente), NBD port walks
14.3 Log Estruturado JSON
Ativar com log_format=json para integração com 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. Troubleshooting
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 comuns:
api_urlerrada (porta, path)- Firewall bloqueando porta 8080 do FD host para CloudStack mgmt
- API key/secret errados
- CloudStack management server parado
Solução para certificado autoassinado:
# Em cloudstack.ini:
verify_ssl = false
15.2 Backup Cai para Modo api_only (Lento)
Sintoma: Log mostra falling back to api_only mode.
Diagnóstico:
ssh -i /opt/bacula/etc/cloudstack_ssh_key root@<kvm-host> "hostname"
Causas:
- Chave SSH não autorizada no KVM host
- IP do KVM host retornado pelo CloudStack não é acessível do FD host
- Firewall bloqueando SSH
- Wrapper de forced-command mal configurado
15.3 Bitmap Criado Mas Incrementais Transferem Tudo
Síntoma: Job incremental transfere o mesmo volume que um full.
Diagnóstico:
# Verificar se o bitmap existe no QEMU via log:
grep -i "bitmap" /opt/bacula/working/podheitor-cloudstack-backend.log
Causa provável: Após falha/crash, o bitmap pode ser marcado como inválido. O plugin detecta e força um full para reconstruí-lo.
Solução: Deixar o primeiro job rodar como full (será automático). A partir do segundo job, CBT estará funcional.
15.4 Snapshots Órfãos se Acumulando
Verificar:
ls /var/lib/bacula/cloudstack/snapshots/
# Comparar com CloudStack UI → Storage → Volume Snapshots
Limpeza manual:
# Via CloudStack CLI (cmk):
cmk list snapshots | grep podheitor
cmk delete snapshot id=<UUID>
O plugin limpa automaticamente na próxima execução snapshots com mais de 30 minutos.
15.5 Receptor DR Recusa Conexões
Verificar firewall no site DR:
iptables -L INPUT -n | grep 9310
# Deve mostrar ACCEPT
Verificar PSK: Os dois lados devem ter exatamente o mesmo dr_psk.
Verificar logs do receptor:
journalctl -u bacula-fd | grep -i "LOG ERROR|replic"
15.6 Disco Full Durante Restore
Sintoma: Restore falha com no space left on device no working_dir.
Cálculo de espaço necessário:
working_dir: max(tamanho_maior_VM) + 10%
Exemplo: VM de 500 GB → necessita 550 GB livres em working_dir
Limpeza:
ls -lh /opt/bacula/working/podheitor-restore-*/
# Se restauração falhou, limpar manualmente:
rm -rf /opt/bacula/working/podheitor-restore-<jobid>/
15.7 VHDX Rejeitado pelo Hyper-V
Causa: Em versões anteriores, o VHDX CRC32C era escrito como zeros. Corrigido na v1.0.0.
Verificar versão:
/opt/bacula/bin/podheitor-cloudstack-backend --version
# Deve mostrar 1.0.0 ou superior
15.8 Preflight Reporta [MISS] em Instalação Saudável
Causa: Em versões anteriores, preflight procurava apenas em /opt/bacula/sbin/. Corrigido na 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. Comparativo com Concorrentes
PodHeitor CloudStack vs. Bacula Enterprise CloudStack Plugin
| Critério | 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) |
| Redução Janela Incremental | ~30-50% | 90-99% |
| Replicação DR | ❌ Não disponível | ✅ Bitmap-push, RPO ~1min |
| Cross-Restore | ❌ Não disponível | ✅ Proxmox, Hyper-V, VMware |
| Conversão de Formato | ❌ Não disponível | ✅ qcow2↔vhdx↔vmdk |
| Métricas Prometheus | ❌ Não disponível | ✅ Nativo |
| Log JSON | ❌ Não disponível | ✅ Nativo |
| Custo | Licença Enterprise | Significativamente menor |
| Suporte multi-plataforma | KVM, VMware | KVM (nativo), cross para outros |
| Linguagem | C++ legado | Rust (memory-safe, sem GC) |
PodHeitor CloudStack vs. Veeam Backup for CloudStack
| Critério | Veeam | PodHeitor CloudStack |
|---|---|---|
| Plataforma | Proprietária | Integra com Bacula (open) |
| Incremental CBT | ✅ Via CloudStack API | ✅ Via QMP bitmap (mais eficiente) |
| Replicação DR | ✅ | ✅ Integrada no mesmo produto |
| Cross-Restore | ✅ Para VMware | ✅ Proxmox, Hyper-V, VMware |
| Deduplicação | Servidor dedicado | Nativa no plugin |
| Custo | Alto (por VM/socket) | 50-70% menor |
| Integração | Standalone | Unificado com Bacula (tudo junto) |
| CloudStack 4.19/4.20 | ✅ | ✅ |
| Linguagem | C# / .NET | Rust (memory-safe, sem GC) |
PodHeitor CloudStack vs. Acronis Cyber Backup
| Critério | Acronis | PodHeitor CloudStack |
|---|---|---|
| Agente | Agente dentro da VM | Sem agente na VM |
| Backup | Guest-level (arquivo) | Block-level (imagem) |
| Consistência | VSS / quiesce | quiesce via qemu-guest-agent |
| Replicação | ✅ (Acronis Cloud) | ✅ (site-to-site) |
| Cross-platform | ✅ | ✅ |
| Custo | Alto (por agente/GB) | Significativamente menor |
| Controle | Na nuvem Acronis | On-premise total |
17. Roadmap
v1.1.0 (Previsão: 2026-06)
- Suporte a Ceph/RBD primary storage (modo nativo)
- Dashboard Grafana pré-configurado (JSON bundle)
- Suporte para Bacula 16.x (quando lançado)
- Web UI mínima para status de replicação
- Teste de integração end-to-end para cross-restore (lab)
v1.2.0 (Previsão: 2026-09)
- Suporte a CloudStack 4.21 (quando lançado)
- Integração com S3-compatible secondary storage
- Backup agentless de VMs Windows via VSS (sem qemu-guest-agent)
- CLI de gerenciamento unificado
- Suporte a múltiplos ambientes CloudStack (multi-zone, multi-region)
v2.0.0 (Previsão: 2026-12)
- PodHeitor Unified Backup Platform: CloudStack + Proxmox + Hyper-V + vSphere sob um único painel
- Orquestração DR automatizada com playbooks
- Integração com Bacularis (interface web do Bacula)
- API REST para automação externa (Ansible, Terraform)
- Arquitetura de próxima geração com performance otimizada e isolamento de processos aprimorado para maior estabilidade em ambientes de alta concorrência
18. Referências
- Apache CloudStack Documentation
- Bacula Community Documentation
- QEMU QMP Reference
- NBD Protocol Specification
- VHDX Specification (Microsoft)
- VMDK Format (VMware)
- zstd Compression
- xxHash
- Rust Language
Licenciamento
PodHeitor CloudStack é software proprietário, distribuído por assinatura. Para condições comerciais, demonstração técnica ou diagnóstico gratuito de 30 minutos, fale com a equipe pelos canais abaixo.
Pronto para avaliar?
- 💬 WhatsApp: +1 (786) 726-1749
- ✉️ Email: heitor@opentechs.lat
- 🩺 Diagnóstico gratuito — 30 min com Heitor Faria
Copyright © 2026 Heitor Faria — Todos os direitos reservados.
Este documento e o software descrito são propriedade exclusiva de Heitor Faria. Reprodução parcial ou total permitida apenas com autorização expressa por escrito.
OFERTA ESPECIAL PARA CLIENTES BACULA ENTERPRISE, VEEAM, COMMVAULT E NETBACKUP:
Traga sua proposta de renovação. Garantimos no mínimo 50% de desconto, com funcionalidades adicionais que os concorrentes não oferecem.
heitor@opentechs.lat | +1 786 726-1749 | +55 61 98268-4220 (WhatsApp)
Disponível em:
Português
English (Inglês)
Español (Espanhol)