keeper
DE
GitHub

Backup- und Restore-Operator für Kubernetes · Postgres 15–17 · PostGIS · MySQL 8.4

Jede Sekunde Ihrer Datenbank, wieder­herstell­bar.

Keeper sichert die Datenbanken, die Sie in Kubernetes betreiben, in jeden S3-Bucket und streamt jede Änderung, sobald sie passiert. Wählen Sie einen Moment der letzten Wochen, und Sie bekommen genau diese Datenbank in einer Wegwerf-Sandbox zurück, Prüfungen bereits ausgeführt, schneller als Sie ein Ticket eröffnen.

Mit Helm installieren Dokumentation lesen Ein Binary, ein Chart. Ihr Bucket, Ihre Schlüssel.
Point-in-Time-Fenster · team/app · Richtlinie prod Fenster 7 Tage · Kette intakt
Wiederherstellen auf
2026-10-07 09:41:27 UTC
Basis-Backup
20261007T020712Z-4c1e
Danach einspielen
114
$ keeper restore team/app --at 2026-10-07T09:41:27Z --wait

Ziehen Sie über das Fenster. Die bernsteinfarbenen Marken sind die nächtlichen Vollsicherungen, das blaue Band ist der Änderungsstrom dazwischen. Illustration einer prod-Richtlinie: nächtliche Vollsicherung, 7-Tage-Fenster.

Gemessen mit make test-perf und make test-ui in der k3d-Testumgebung (4 vCPU, MinIO im Cluster). Die Zahlen stehen in docs/PERF.md im Repository.

Anseheneine Minute

Eine Minute, vom Start bis zur Wiederherstellung.

Echte Befehle und die echte Konsole auf einem Demo-Katalog: alle Datenbanken auflisten, sehen, was sich über Nacht geändert hat, und in eine Sandbox zurückholen.

0:58 · mit Ton · 2,7 MB

Die Konsole

Übersicht der Keeper-Konsole: neun Datenbanken mit letzter Vollsicherung, Wiederherstellungsfenster, Verzögerung, Größe und Zustand
Alle Datenbanken auf einen Blick: letzte Vollsicherung, Wiederherstellungsfenster, Stream-Verzögerung, Größe und Zustand.
Datenbankseite der Keeper-Konsole: die wiederherstellbare Zeitleiste, Trends für Zeilen und Größe und die Versionsliste mit Prüfabzeichen
Eine Datenbank: ihre wiederherstellbare Zeitleiste, ihre Trends und jede Version, geprüfte Wiederherstellungen markiert.
Diff zwischen zwei Backups in der Keeper-Konsole: eine Spalte hinzugefügt, eine Tabelle geleert, Zeilen und Größe je Tabelle
Zwei Versionen nebeneinander: was eingespielt wurde, welche Spalten sich änderten, Zeilen und Größe je Tabelle.

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

Ausgabe des Demo-Servers im Repository: go run ./hack/demo, dann die CLI oder einen Browser darauf richten.

Wiederherstellenvier Ziele

Überall wiederherstellen, ohne die Produktion anzufassen.

Eine Wiederherstellung ist eine Kubernetes-Ressource wie jede andere. Geben Sie eine Zeit oder eine Backup-ID an und wählen Sie das Ziel. Keeper plant das Basis-Backup und die einzuspielenden Änderungen und führt Ihre Prüfungen aus, bevor die Wiederherstellung als erfolgreich gilt.

SANDBOX

Eine Wegwerf-Kopie

Eine private Datenbank mit TTL, Zugangsdaten und einer schreibgeschützten Abfragekonsole. Sie räumt sich selbst auf.

--to sandbox --ttl 6h
NEW

Eine neue Datenbank

In einer Staging-Sandbox wiederhergestellt und geprüft, dann unter neuem Namen kopiert. Bestehende Objekte werden nie überschrieben.

--to new --database app_copy
IN PLACE

Wirklich zurückrollen

Erstellt zuerst ein Sicherheits-Backup und verlangt, dass Sie den Namen des Ziels eintippen. Erfordert die Rolle restorer-admin.

--to in-place --confirm app
DOWNLOAD

Eine Dump-Datei

Ein entschlüsselter, komprimierter logischer Dump hinter einem Link, der nach einer Stunde abläuft. Auditiert.

--to download
Fußabdruckklein und ruhig

So leicht, dass man es vergisst.

Keeper ist ein einziges Go-Binary. Controller und API planen und lesen nur; Daten bewegen sich in kurzlebigen Jobs, die nach getaner Arbeit enden. Zwischen den Backups bleibt nichts Schweres im Cluster.

54MBein statisches Binary: Controller, API und Konsole, Mover, Streamer, Restorer und CLI
18MBkomprimierter Download, keine Laufzeitumgebung, keine Sidecars
21MiBSpeicher des Controllers im Ruhezustand, während er einen Cluster voller Datenbanken überwacht
19MiBSpeicher von API und Konsole im Ruhezustand, Katalog im Speicher

Working Set laut Kubelet im k3d-Testcluster (12 Datenbanken) nach End-to-End- und Chaos-Suite; die CPU im Ruhezustand liegt bei wenigen Millicores. Jede Datenbank mit Point-in-Time-Wiederherstellung betreibt zusätzlich einen Streamer, etwa 70 MiB während des Streamens.

Schnell durch Konstruktion

Streaming-Pipelines ohne temporäre Dateien, parallele Multipart-Uploads, Multithread-zstd und ein Katalog im Speicher hinter einer Konsole, die in Millisekunden antwortet.

Zuverlässig durch Konstruktion

Crash-only: Jeder Pod kann jederzeit sterben. Der Zustand liegt in CRDs und S3, ein Backup existiert erst, wenn sein Manifest zuletzt geschrieben ist, und nichts wartet ewig.

Prüfenvor dem Zurückholen

Wissen, was sich zwischen zwei Versionen geändert hat.

Jedes Backup trägt ein Inventar seiner Tabellen, Zeilen und Größen. Jedes Änderungssegment trägt eine Zusammenfassung dessen, was es getan hat. So sehen Sie vor jeder Wiederherstellung, welche Version die verlorenen Zeilen noch hatte.

  • Diffs zwischen beliebigen zwei Backups. Schemaänderungen, Zeilenzahlen und Größe je Tabelle.
  • Änderungsübersicht je WAL- oder Binlog-Segment. Inserts, Updates, Deletes und DDL je Tabelle, damit ein TRUNCATE um 22:48 leicht zu finden ist.
  • Maskierte Vorschauen. Beispielzeilen mit maskierten Spalten Ihrer Wahl, lesbar mit einem Katalogschlüssel, der die Daten selbst nicht entschlüsseln kann.
Funktioneninklusive

Gebaut für die Nacht, in der etwas schiefgeht.

Änderungsstrom

Keepers eigener WAL-Empfänger auf einem Replikations-Slot für Postgres und mysqlbinlog für MySQL. Das Fenster reicht bis zur Gegenwart, auch bei einer ruhigen Datenbank.

Geprüft, nicht erhofft

Geplante Prüf-Wiederherstellungen führen Ihre SQL-Prüfungen auf einer echten Wiederherstellung aus und markieren das Backup als geprüft. Die Dauer wird als Metrik exportiert.

Verschlüsselt, bevor es geht

Jedes Objekt wird clientseitig mit age für Ihre Schlüssel verschlüsselt. Der Bucket sieht nie Klartext, und der Katalogschlüssel der Konsole kann keine Daten lesen.

Standardmäßig komprimiert

zstd mit der Stufe, die Sie je Richtlinie wählen, einmal in der Pipeline angewendet. Dump-Werkzeuge laufen unkomprimiert, und der Datenbankserver verbraucht dafür keine CPU.

Hängt nie

Keine Mounts, keine Block-Devices; Datenbanken nur über das Netzwerk. Jeder Strom hat einen Fortschritts-Watchdog, jedes Werkzeug läuft in seiner eigenen Prozessgruppe.

Crash-only

Beenden Sie jederzeit jeden Pod. Ein Backup existiert erst, wenn sein Manifest zuletzt geschrieben ist, und die Chaos-Suite beendet Keeper mitten im Backup, um das zu beweisen.

Schonend für die Produktion

Schreibgeschützte Benutzer mit minimalen Rechten. Slots je Host, Bandbreitenlimits und ein Last-Wächter, der ein Backup verschiebt, wenn der Server ausgelastet ist.

Konsole, CLI und API

Eine JSON-API, beschrieben mit OpenAPI, mit Rollen aus Cloudflare Access. Jeder Schreibzugriff und jede Abfrage wird auditiert.

GitOps-nativ

Stores, Richtlinien, Ziele und Wiederherstellungen sind CRDs. Aufbewahrungsstufen, Alerts und ein Grafana-Dashboard sind im Chart enthalten.

ArchitekturDatenpfad

Daten bewegen sich in Jobs, nie im Controller.

Der Controller plant nur. Mover und Streamer tragen die Bytes durch eine einzige Streaming-Pipeline direkt in Ihren Bucket, und der Restorer holt sie zurück.

Postgres · MySQL in Ihrem Cluster mover Job Vollsicherungen streamer WAL · binlog eine Streaming-Pipeline zstd → age → SHA-256 → 8 × multipart keine temporären Dateien, Gegendruck von S3 Ihr S3-Bucket manifest.json zuletzt *.zst.age restorer Job prüfen → entschlüsseln → einspielen → testen Sandbox · neue Datenbank · vor Ort · Download mit TTL, Abfragekonsole und Audit
Im Vergleichzu einem Cronjob

Mehr als ein nächtlicher Dump im Bucket.

Wenn Sie …Cron + pg_dump-SkriptKeeper
auf 09:41:27 zurück müssenDer Dump von gestern Nacht, bis zu 24 h verlorenJede Sekunde im Fenster
beweisen müssen, dass ein Backup funktioniertErfahren Sie es während des VorfallsGeplante Prüf-Wiederherstellungen mit Ihren Prüfungen
die Version mit den fehlenden Zeilen finden müssenMehrere zurückholen und nachsehenDiffs und Änderungsübersichten in der Konsole
ohne Risiko nachsehen wollenÜber ein geteiltes Staging zurückspielenEine private Sandbox mit TTL
den Bucket blind halten wollenServerseitige Verschlüsselung, falls eingerichtetClientseitige age-Verschlüsselung mit Ihren Schlüsseln
einen ausfallenden Knoten überstehen müssenEine halb geschriebene Datei, die vollständig aussiehtNichts zählt, bevor das Manifest zuletzt geschrieben ist
wissen wollen, dass es noch läuftStilleAlerts für überfällige Backups, gebrochene Ketten und Verzögerung
Installierenetwa zehn Minuten

Von null auf wieder­herstell­bar.

  1. Chart installieren

    CRDs, Controller, API und Konsole, RBAC, Alerts und das 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. Bucket und Schlüssel angeben

    Jeder S3-kompatible Speicher. Erzeugen Sie einen age-Schlüssel mit age-keygen und bewahren Sie eine Offline-Kopie auf.

    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…]   # nur der öffentliche Schlüssel; der private bleibt offline
  3. Ein Ziel neben der Datenbank deklarieren

    Legen Sie die schreibgeschützten Benutzer mit dem SQL aus docs/sql/ an und committen Sie das Ziel in 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             # nächtliche Vollsicherung, 7-Tage-Fenster
      credentials:
        secretRef: { name: keeper-backup-postgres }
        replicationSecretRef: { name: keeper-repl-postgres }
  4. Etwas zurückholen, mit Absicht

    Die erste Vollsicherung startet von selbst. Probieren Sie dann aus, was Sie hoffentlich nie brauchen.

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

Die vollständige Anleitung, jedes CRD-Feld und die REST-API stehen in der Dokumentation (auf Englisch).

Testen Sie Ihre Wiederherstellung, bevor Sie sie brauchen.