keeper
ES
GitHub

Operador de respaldo y restauración para Kubernetes · Postgres 15–17 · PostGIS · MySQL 8.4

Cada segundo de tu base de datos, restaurable.

Keeper respalda las bases de datos que ejecutas en Kubernetes en cualquier bucket S3 y transmite cada cambio en cuanto ocurre. Elige un momento de las últimas semanas y recuperas exactamente esa base de datos en un sandbox desechable, con las verificaciones ya ejecutadas, en menos tiempo del que tardas en abrir un ticket.

Instalar con Helm Leer la documentación Un binario, un chart. Tu bucket, tus claves.
Ventana de restauración puntual · team/app · política prod ventana 7 días · cadena intacta
Restaurar a
2026-10-07 09:41:27 UTC
Respaldo base
20261007T020712Z-4c1e
Luego reproducir
114
$ keeper restore team/app --at 2026-10-07T09:41:27Z --wait

Arrastra sobre la ventana. Las marcas ámbar son los respaldos completos nocturnos; la banda azul es el flujo de cambios entre ellos. Ilustración de una política prod: completos cada noche, ventana de 7 días.

Medido con make test-perf y make test-ui en el entorno de pruebas k3d (4 vCPU, MinIO en el clúster). Los números están en docs/PERF.md del repositorio.

Verloun minuto

Un minuto, de cero a restaurar.

Comandos reales y la consola real sobre un catálogo de demostración: lista cada base de datos, mira qué cambió durante la noche y restáurala en un sandbox.

0:58 · con sonido · 2,7 MB

La consola

Vista general de la consola de Keeper: nueve bases de datos con su último respaldo completo, ventana de restauración, retraso, tamaño y estado
Todas las bases de un vistazo: último respaldo completo, ventana de restauración, retraso del flujo, tamaño y estado.
Página de una base de datos en la consola de Keeper: la línea de tiempo restaurable, tendencias de filas y tamaño, y la lista de versiones con insignias de verificación
Una base de datos: su línea de tiempo restaurable, sus tendencias y cada versión, con las restauraciones verificadas marcadas.
Diff entre dos respaldos en la consola de Keeper: una columna añadida, una tabla vaciada, filas y tamaño por tabla
Dos versiones lado a lado: qué migración se aplicó, qué columnas cambiaron, filas y tamaño por tabla.

La 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  -

Salida del servidor de demostración del repositorio: go run ./hack/demo y apunta la CLI o un navegador a él.

Restaurarcuatro destinos

Restaura donde quieras, sin tocar producción.

Una restauración es un recurso de Kubernetes como cualquier otro. Pide una hora o un ID de respaldo y elige el destino. Keeper planifica el respaldo base y los cambios a reproducir, y ejecuta tus verificaciones antes de dar la restauración por buena.

SANDBOX

Una copia desechable

Una base privada con TTL, credenciales y una consola de consultas de solo lectura. Se limpia sola.

--to sandbox --ttl 6h
NEW

Una base de datos nueva

Restaurada y verificada en un sandbox intermedio, luego copiada con un nombre nuevo. Nunca sobrescribe objetos existentes.

--to new --database app_copy
IN PLACE

Volver atrás de verdad

Primero hace un respaldo de seguridad y te pide escribir el nombre del destino. Requiere el rol restorer-admin.

--to in-place --confirm app
DOWNLOAD

Un archivo de volcado

Un volcado lógico descifrado y comprimido tras un enlace que caduca en una hora. Auditado.

--to download
Huellapequeña y estable

Tan ligero que olvidarás que está ahí.

Keeper es un único binario de Go. El controlador y la API solo planifican y leen; los datos se mueven en Jobs de vida corta que terminan al acabar, así que entre respaldos no queda nada pesado en tu clúster.

54MBun binario estático: controlador, API y consola, movers, streamers, restorer y CLI
18MBde descarga comprimida, sin runtime que instalar ni sidecars
21MiBde memoria del controlador en reposo, vigilando un clúster de bases de datos
19MiBde memoria de la API y la consola en reposo, con el catálogo en memoria

Working set que informa el kubelet en el clúster de pruebas k3d (12 bases de datos) tras las suites end-to-end y de caos; la CPU en reposo es de unos pocos milicores. Cada base con restauración puntual ejecuta además un streamer, unos 70 MiB mientras transmite.

Rápido por diseño

Pipelines en streaming sin archivos temporales, subidas multiparte en paralelo, zstd multihilo y un catálogo en memoria detrás de una consola que responde en milisegundos.

Fiable por diseño

Diseño crash-only: cualquier pod puede morir en cualquier momento. El estado vive en CRDs y S3, un respaldo existe solo cuando su manifiesto se escribe al final, y nada espera para siempre.

Inspeccionarantes de restaurar

Sabe qué cambió entre dos versiones.

Cada respaldo lleva un inventario de sus tablas, filas y tamaños. Cada segmento de cambios lleva un resumen de lo que hizo. Así, antes de restaurar nada, ves qué versión aún tenía las filas que perdiste.

  • Diffs entre dos respaldos cualesquiera. Cambios de esquema, número de filas y tamaño por tabla.
  • Resumen de cambios por segmento WAL o binlog. Inserciones, actualizaciones, borrados y DDL por tabla, para encontrar fácilmente un TRUNCATE a las 22:48.
  • Vistas previas enmascaradas. Filas de muestra con las columnas que indiques enmascaradas, legibles con una clave de catálogo que no puede descifrar los datos.
Funcionesincluidas

Hecho para la noche en que algo sale mal.

Streaming de cambios

El receptor WAL propio de Keeper sobre un slot de replicación para Postgres y mysqlbinlog para MySQL. La ventana llega al presente, incluso con una base inactiva.

Verificado, no supuesto

Restauraciones de verificación programadas ejecutan tus consultas SQL contra una restauración real y marcan el respaldo como verificado. Su tiempo de restauración se exporta como métrica.

Cifrado antes de salir

Cada objeto se cifra en el cliente con age para tus claves. El bucket nunca ve texto plano, y la clave de catálogo de la consola no puede leer datos.

Comprimido por defecto

zstd con el nivel que elijas por política, aplicado una sola vez en el pipeline. Las herramientas de volcado trabajan sin comprimir y el servidor de base de datos no gasta CPU en ello.

Nunca se cuelga

Sin montajes ni dispositivos de bloque; bases de datos solo por la red. Cada flujo tiene un watchdog de progreso y cada herramienta corre en su propio grupo de procesos.

Crash-only

Mata cualquier pod en cualquier momento. Un respaldo existe solo cuando su manifiesto se escribe al final, y la suite de caos mata a Keeper a mitad de un respaldo para demostrarlo.

Cuidadoso con producción

Usuarios de solo lectura con privilegios mínimos. Turnos por host, límites de ancho de banda y una protección de carga que pospone el respaldo si el servidor está ocupado.

Consola, CLI y API

Una API JSON descrita con OpenAPI, con roles de Cloudflare Access. Cada escritura y cada consulta se auditan.

Nativo de GitOps

Stores, políticas, targets y restauraciones son CRDs. Niveles de retención, alertas y un dashboard de Grafana vienen con el chart.

Arquitecturaruta de datos

Los datos se mueven en Jobs, nunca en el controlador.

El controlador solo planifica. Movers y streamers llevan los bytes por un único pipeline en streaming directo a tu bucket, y el restorer los trae de vuelta.

Postgres · MySQL en tu clúster mover Job respaldos completos streamer WAL · binlog un pipeline en streaming zstd → age → SHA-256 → 8 × multipart sin archivos temporales, contrapresión de S3 tu bucket S3 manifest.json al final *.zst.age restorer Job verificar → descifrar → reproducir → comprobar sandbox · base nueva · in situ · descarga con TTL, consola de consultas y auditoría
Comparadocon un cron

Más que un volcado nocturno en un bucket.

Cuando necesitas…script cron + pg_dumpKeeper
Volver a las 09:41:27El volcado de anoche, hasta 24 h perdidasCualquier segundo de la ventana
Demostrar que un respaldo se restauraDescubrirlo durante el incidenteRestauraciones de verificación programadas con tus comprobaciones
Encontrar la versión con las filas perdidasRestaurar varias y mirarDiffs y resúmenes de cambios en la consola
Mirar sin riesgoRestaurar sobre un staging compartidoUn sandbox privado con TTL
Que el bucket no vea nadaCifrado en el servidor, si se configuróCifrado age en el cliente con tus claves
Sobrevivir a un nodo que muere a mitadUn archivo a medias que parece completoNada cuenta hasta que el manifiesto se escribe al final
Saber que sigue funcionandoSilencioAlertas por respaldos atrasados, cadenas rotas y retraso
Instalarunos diez minutos

De cero a restaurable.

  1. Instala el chart

    CRDs, el controlador, la API y la consola, RBAC, alertas y el 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. Apúntalo a un bucket y a tus claves

    Cualquier almacenamiento compatible con S3. Genera una clave age con age-keygen y guarda una copia 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…]   # solo la clave pública; la privada queda offline
  3. Declara un target junto a la base de datos

    Crea los usuarios de solo lectura con el SQL de docs/sql/ y sube el target a 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 cada noche, ventana de 7 días
      credentials:
        secretRef: { name: keeper-backup-postgres }
        replicationSecretRef: { name: keeper-repl-postgres }
  4. Restaura algo, a propósito

    El primer respaldo completo empieza solo. Luego prueba eso que esperas no necesitar nunca.

    keeper targets
    keeper restore team-a/app --at 2026-10-07T09:41:27Z --wait
    keeper query <sandbox> -e "select count(*) from orders"

La guía completa, cada campo de los CRD y la API REST están en la documentación (en inglés).

Prueba tu restauración antes de necesitarla.