Operador de backup e restauração para Kubernetes · Postgres 15–17 · PostGIS · MySQL 8.4
Cada segundo do seu banco de dados, restaurável.
O Keeper faz backup dos bancos de dados que você roda no Kubernetes para qualquer bucket S3 e transmite cada alteração assim que ela acontece. Escolha um momento das últimas semanas e você recebe exatamente aquele banco em um sandbox descartável, com as verificações já executadas, em menos tempo do que leva para abrir um chamado.
- Restaurar para
- 2026-10-07 09:41:27 UTC
- Backup base
- 20261007T020712Z-4c1e
- Depois reaplicar
- 114
$ keeper restore team/app --at 2026-10-07T09:41:27Z --wait
Arraste pela janela. As marcas âmbar são os backups completos noturnos; a faixa azul é o fluxo de alterações entre eles. Ilustração de uma política prod: completos toda noite, janela de 7 dias.
- 9spara restaurar um banco Postgres de 644 MiB em um sandbox: baixar, descriptografar, recuperar e verificar
- 4.2×menor no bucket: um backup físico de 683 MiB armazenado como 161 MiB
- 72MiB/sde vazão em um backup lógico completo com 4 vCPU, em streaming e sem arquivos temporários
- 20msp99 da visão geral do console com 1.000 bancos e 100.000 backups
Medido com make test-perf e make test-ui no ambiente de testes k3d (4 vCPU, MinIO no cluster). Os números estão em docs/PERF.md no repositório.
Um minuto, do início à restauração.
Comandos reais e o console real sobre um catálogo de demonstração: liste cada banco, veja o que mudou durante a noite e restaure em um sandbox.
O console
A CLI
$ keeper targets TARGET ENGINE ORG/PROJECT/ENV LAST FULL PITR WINDOW STORED HEALTH analytics/events postgres acme/data/staging 2026-10-07 02:11:47Z - 19.1GiB ok auth/users postgres acme/platform/prod 2026-10-07 02:11:06Z 2026-09-23 02:11:06Z → 2026-10-07 18:50:52Z 1.5GiB ok billing/invoices mysql acme/billing/prod 2026-10-07 02:09:03Z 2026-09-23 02:09:03Z → 2026-10-07 18:50:52Z 6.7GiB ok billing/ledger postgres acme/billing/prod 2026-10-07 02:08:22Z 2026-09-23 02:08:22Z → 2026-10-07 18:50:52Z 14.3GiB ok maps/geo postgres acme/maps/prod 2026-10-07 02:10:25Z 2026-09-23 02:10:25Z → 2026-10-07 18:50:52Z 23.3GiB ok shop-dev/orders-db postgres acme/shop/dev 2026-10-07 02:12:28Z - 17.4MiB ok shop/catalog-db postgres acme/shop/prod 2026-10-07 02:07:41Z 2026-09-23 02:07:41Z → 2026-10-07 18:50:52Z 731.0MiB ok shop/orders-db postgres acme/shop/prod 2026-10-07 02:07:00Z 2026-09-23 02:07:00Z → 2026-10-07 18:50:52Z 9.6GiB ok web/wordpress mysql acme/marketing/prod 2026-10-07 02:09:44Z 2026-09-23 02:09:44Z → 2026-10-07 18:50:52Z 607.4MiB ok
$ keeper diff 20261006T020700Z-bd79 20261007T020700Z-6da5 from 20261006T020700Z-bd79 (2026-10-06 02:07:00Z) to 20261007T020700Z-6da5 (2026-10-07 02:07:00Z) 20261007 applied (was 20261006) column orders.gift_note added table audit_log +158,175 rows (+2%) table order_items +62,923 rows (+1%) table orders +15,655 rows (+1%) table coupons −3,120 rows (−100%) table customers +531 rows (+1%) 14 segments in between: 00000001000000A100000000 18:51:32–19:20:32 · 800 commits · audit_log +3348 / ~1116 / −83 · order_items +1327 / ~442 / −33 · orders +330 / ~110 / −8 · customers +11 / ~3 / −0 00000001000000A100000001 19:21:32–19:50:32 · 813 commits · audit_log +3352 / ~1116 / −83 · order_items +1328 / ~442 / −33 · orders +330 / ~110 / −8 · customers +13 / ~3 / −0 00000001000000A100000002 19:51:32–20:20:32 · 826 commits · audit_log +3356 / ~1116 / −83 · order_items +1329 / ~442 / −33 · orders +330 / ~110 / −8 · customers +15 / ~3 / −0
$ keeper restore shop/orders-db --at 20261006T020700Z-bd79 --ttl 6h --reason "coupons truncated" restore orders-db-sandbox-60414a15fc created (sandbox from 20261006T020700Z-bd79, 0 segments) restore shop/orders-db-sandbox-60414a15fc $ keeper sandbox list NAME ENGINE SOURCE OWNER PHASE EXPIRES IN-CLUSTER sbx-7f3a postgres shop/orders-db maria@acme.example Ready 2026-10-08 00:37:32Z keeper-sbx-sbx-7f3a.keeper-sandboxes.svc:5432 sbx-c210 mysql billing/invoices dev@acme.example Provisioning -
Saída do servidor de demonstração do repositório: go run ./hack/demo e aponte a CLI ou um navegador para ele.
Restaure onde quiser, sem tocar na produção.
Uma restauração é um recurso do Kubernetes como qualquer outro. Peça um horário ou um ID de backup e escolha o destino. O Keeper planeja o backup base e as alterações a reaplicar, e roda suas verificações antes de considerar a restauração bem-sucedida.
Uma cópia descartável
Um banco privado com TTL, credenciais e um console de consultas somente leitura. Ele se limpa sozinho.
--to sandbox --ttl 6hUm banco novo
Restaurado e verificado em um sandbox intermediário, depois copiado com um novo nome. Objetos existentes nunca são sobrescritos.
--to new --database app_copyVoltar atrás de verdade
Faz antes um backup de segurança e pede que você digite o nome do alvo. Exige o papel restorer-admin.
--to in-place --confirm appUm arquivo de dump
Um dump lógico descriptografado e comprimido, atrás de um link que expira em uma hora. Auditado.
--to downloadLeve a ponto de você esquecer que está lá.
O Keeper é um único binário Go. O controlador e a API apenas agendam e leem; os dados trafegam em Jobs de vida curta que terminam ao concluir, então entre um backup e outro nada pesado fica no seu cluster.
Working set informado pelo kubelet no cluster de testes k3d (12 bancos) após as suítes end-to-end e de caos; a CPU em repouso fica em poucos milicores. Cada banco com restauração pontual também roda um streamer, cerca de 70 MiB durante o streaming.
Rápido por construção
Pipelines em streaming sem arquivos temporários, uploads multipart em paralelo, zstd multithread e um catálogo em memória por trás de um console que responde em milissegundos.
Confiável por construção
Projeto crash-only: qualquer pod pode morrer a qualquer momento. O estado vive em CRDs e no S3, um backup só existe quando seu manifesto é gravado por último, e nada espera para sempre.
Saiba o que mudou entre duas versões.
Cada backup traz um inventário das tabelas, linhas e tamanhos. Cada segmento de alterações traz um resumo do que fez. Assim, antes de restaurar qualquer coisa, você vê qual versão ainda tinha as linhas perdidas.
- Diffs entre quaisquer dois backups. Mudanças de esquema, contagem de linhas e tamanho por tabela.
- Resumo de alterações por segmento WAL ou binlog. Inserções, atualizações, exclusões e DDL por tabela, para achar fácil um TRUNCATE às 22:48.
- Prévias mascaradas. Linhas de amostra com as colunas que você indicar mascaradas, legíveis com uma chave de catálogo que não descriptografa os dados.
Feito para a noite em que algo dá errado.
Streaming de alterações
O receptor WAL do próprio Keeper em um slot de replicação para Postgres e mysqlbinlog para MySQL. A janela chega ao presente, mesmo com o banco ocioso.
Verificado, não presumido
Restaurações de verificação agendadas rodam suas consultas SQL em uma restauração real e marcam o backup como verificado. O tempo de restauração vira métrica.
Criptografado antes de sair
Cada objeto é criptografado no cliente com age para as suas chaves. O bucket nunca vê texto puro, e a chave de catálogo do console não lê dados.
Comprimido por padrão
zstd no nível que você escolher por política, aplicado uma única vez no pipeline. As ferramentas de dump rodam sem compressão e o servidor de banco não gasta CPU com isso.
Nunca trava
Sem montagens nem dispositivos de bloco; bancos só pela rede. Cada fluxo tem um watchdog de progresso e cada ferramenta roda em seu próprio grupo de processos.
Crash-only
Mate qualquer pod a qualquer momento. Um backup só existe quando o manifesto é gravado por último, e a suíte de caos derruba o Keeper no meio do backup para provar.
Gentil com a produção
Usuários somente leitura com privilégio mínimo. Slots por host, limites de banda e uma proteção de carga que adia o backup quando o servidor está ocupado.
Console, CLI e API
Uma API JSON descrita em OpenAPI, com papéis do Cloudflare Access. Toda escrita e toda consulta são auditadas.
Nativo de GitOps
Stores, políticas, alvos e restaurações são CRDs. Níveis de retenção, alertas e um dashboard do Grafana vêm com o chart.
Os dados trafegam em Jobs, nunca no controlador.
O controlador apenas agenda. Movers e streamers levam os bytes por um único pipeline em streaming direto para o seu bucket, e o restorer os traz de volta.
Mais do que um dump noturno em um bucket.
| Quando você precisa… | script cron + pg_dump | Keeper |
|---|---|---|
| Voltar para 09:41:27 | O dump da noite passada, até 24 h perdidas | Qualquer segundo da janela |
| Provar que um backup restaura | Descobrir durante o incidente | Restaurações de verificação agendadas com suas checagens |
| Achar a versão com as linhas perdidas | Restaurar várias e olhar | Diffs e resumos de alterações no console |
| Olhar sem risco | Restaurar sobre um staging compartilhado | Um sandbox privado com TTL |
| Manter o bucket às cegas | Criptografia no servidor, se configurada | Criptografia age no cliente com suas chaves |
| Sobreviver a um nó que cai no meio | Um arquivo pela metade que parece completo | Nada conta até o manifesto ser gravado por último |
| Saber que continua funcionando | Silêncio | Alertas de backups atrasados, cadeias quebradas e atraso |
Do zero ao restaurável.
Instale o chart
CRDs, o controlador, a API e o console, RBAC, alertas e o dashboard.
helm install keeper charts/keeper -n keeper-system --create-namespace \ --set image.repository=registry.example.com/keeper/keeper --set image.tag=v0.1.0 \ --set 'targetNamespaces={team-a}'Aponte para um bucket e suas chaves
Qualquer armazenamento compatível com S3. Gere uma chave age com age-keygen e guarde uma cópia offline.
apiVersion: keeper.republic.global/v1alpha1 kind: BackupStore metadata: { name: main } spec: s3: endpoint: https://s3.example.com region: us-east-1 bucket: db-backups credentialsSecret: { namespace: keeper-system, name: keeper-s3 } encryption: ageRecipients: [age1…] # só a chave pública; a privada fica offline
Declare um alvo ao lado do banco
Crie os usuários somente leitura com o SQL de docs/sql/ e faça commit do alvo no git.
apiVersion: keeper.republic.global/v1alpha1 kind: BackupTarget metadata: { name: app, namespace: team-a } spec: engine: postgres endpoint: { host: postgres, port: 5432 } databases: [app] policy: prod # completos toda noite, janela de 7 dias credentials: secretRef: { name: keeper-backup-postgres } replicationSecretRef: { name: keeper-repl-postgres }
Restaure algo, de propósito
O primeiro backup completo começa sozinho. Depois teste aquilo que você espera nunca precisar.
keeper targets keeper restore team-a/app --at 2026-10-07T09:41:27Z --wait keeper query <sandbox> -e "select count(*) from orders"
O guia completo, cada campo dos CRDs e a API REST estão na documentação (em inglês).