keeper
PT
GitHub

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.

Instalar com Helm Ler a documentação Um binário, um chart. Seu bucket, suas chaves.
Janela de restauração pontual · team/app · política prod janela 7 dias · cadeia íntegra
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.

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.

Vejaum minuto

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.

0:58 · com som · 2,7 MB

O console

Visão geral do console do Keeper: nove bancos com o último backup completo, janela de restauração, atraso, tamanho e saúde
Todos os bancos de relance: último backup completo, janela de restauração, atraso do fluxo, tamanho e saúde.
Página de um banco no console do Keeper: a linha do tempo restaurável, tendências de linhas e tamanho, e a lista de versões com selos de verificação
Um banco: sua linha do tempo restaurável, suas tendências e cada versão, com as restaurações verificadas marcadas.
Diff entre dois backups no console do Keeper: uma coluna adicionada, uma tabela esvaziada, linhas e tamanho por tabela
Duas versões lado a lado: o que foi aplicado, quais colunas mudaram, linhas e tamanho por tabela.

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.

Restaurarquatro destinos

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.

SANDBOX

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 6h
NEW

Um 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_copy
IN PLACE

Voltar 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 app
DOWNLOAD

Um arquivo de dump

Um dump lógico descriptografado e comprimido, atrás de um link que expira em uma hora. Auditado.

--to download
Pegadapequena e estável

Leve 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.

54MBum binário estático: controlador, API e console, movers, streamers, restorer e CLI
18MBde download comprimido, sem runtime para instalar nem sidecars
21MiBde memória do controlador em repouso, observando um cluster de bancos
19MiBde memória da API e do console em repouso, com o catálogo em memória

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.

Inspecionarantes de restaurar

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.
Recursosinclusos

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.

Arquiteturacaminho dos dados

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.

Postgres · MySQL no seu cluster mover Job backups completos streamer WAL · binlog um pipeline em streaming zstd → age → SHA-256 → 8 × multipart sem arquivos temporários, contrapressão do S3 seu bucket S3 manifest.json por último *.zst.age restorer Job verificar → descriptografar → reaplicar → checar sandbox · banco novo · no lugar · download com TTL, console de consultas e auditoria
Comparadoa um cron

Mais do que um dump noturno em um bucket.

Quando você precisa…script cron + pg_dumpKeeper
Voltar para 09:41:27O dump da noite passada, até 24 h perdidasQualquer segundo da janela
Provar que um backup restauraDescobrir durante o incidenteRestaurações de verificação agendadas com suas checagens
Achar a versão com as linhas perdidasRestaurar várias e olharDiffs e resumos de alterações no console
Olhar sem riscoRestaurar sobre um staging compartilhadoUm sandbox privado com TTL
Manter o bucket às cegasCriptografia no servidor, se configuradaCriptografia age no cliente com suas chaves
Sobreviver a um nó que cai no meioUm arquivo pela metade que parece completoNada conta até o manifesto ser gravado por último
Saber que continua funcionandoSilêncioAlertas de backups atrasados, cadeias quebradas e atraso
Instalarcerca de dez minutos

Do zero ao restaurável.

  1. 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}'
  2. 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
  3. 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 }
  4. 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).

Teste sua restauração antes de precisar dela.