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.
- 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.
- 9spara restaurar una base Postgres de 644 MiB en un sandbox: descargar, descifrar, recuperar y ejecutar verificaciones
- 4.2×más pequeño en el bucket: un respaldo físico de 683 MiB guardado como 161 MiB
- 72MiB/sde rendimiento en un respaldo lógico completo con 4 vCPU, en streaming y sin archivos temporales
- 20msp99 de la vista general de la consola con 1.000 bases de datos y 100.000 respaldos
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.
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.
La consola
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.
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.
Una copia desechable
Una base privada con TTL, credenciales y una consola de consultas de solo lectura. Se limpia sola.
--to sandbox --ttl 6hUna 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_copyVolver 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 appUn archivo de volcado
Un volcado lógico descifrado y comprimido tras un enlace que caduca en una hora. Auditado.
--to downloadTan 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.
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.
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.
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.
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.
Más que un volcado nocturno en un bucket.
| Cuando necesitas… | script cron + pg_dump | Keeper |
|---|---|---|
| Volver a las 09:41:27 | El volcado de anoche, hasta 24 h perdidas | Cualquier segundo de la ventana |
| Demostrar que un respaldo se restaura | Descubrirlo durante el incidente | Restauraciones de verificación programadas con tus comprobaciones |
| Encontrar la versión con las filas perdidas | Restaurar varias y mirar | Diffs y resúmenes de cambios en la consola |
| Mirar sin riesgo | Restaurar sobre un staging compartido | Un sandbox privado con TTL |
| Que el bucket no vea nada | Cifrado en el servidor, si se configuró | Cifrado age en el cliente con tus claves |
| Sobrevivir a un nodo que muere a mitad | Un archivo a medias que parece completo | Nada cuenta hasta que el manifiesto se escribe al final |
| Saber que sigue funcionando | Silencio | Alertas por respaldos atrasados, cadenas rotas y retraso |
De cero a restaurable.
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}'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
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 }
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).