Skip to content

Repository files navigation

kube-db-backup

A Kubernetes-native operator that backs up databases running in your cluster to S3-compatible storage — and restores them on demand.

The operator is built around a pluggable engine model: it handles the generic backup lifecycle (scheduling, job orchestration, retries, state tracking), while small, swappable engine container images handle the database-specific mechanics (dumping and restoring one database type each).

Currently supported engines: PostgreSQL (pg_dump / pg_restore)

Adding a new database type (MongoDB, MySQL, Milvus, Weaviate, …) is designed to require only a new engine image and a registry entry — no changes to the CRDs or controllers.

How it works

  1. You create DatabaseInstance (how to connect), BackupConfig (where to store), and either a Backup (one-shot) or BackupSchedule (cron) resource.
  2. The operator validates the references, resolves the engine type via the Engine Registry, and creates a Kubernetes Job.
  3. The Job runs an engine container image with a standardized set of environment variables and mounted secrets.
  4. The engine connects to the database, dumps it, uploads the dump + manifest to S3, and writes a standardized JSON result to stdout.
  5. The operator reads the Job's result and exit code, then updates the Backup/Restore status — retrying with backoff on connectivity/storage failures.

Custom resources

CRD Purpose
DatabaseInstance Connection details for a database: engineType, host/port, database name, auth SecretRef, and an engine-specific engineConfig map.
BackupConfig S3 destination (endpoint, bucket, prefix, credentials via SecretRef), retention policy, and Job timeout.
Backup A one-shot backup request referencing a DatabaseInstance and BackupConfig.
BackupSchedule Cron-based generator of Backup objects (Kubernetes CronJobJob pattern, but for backups).
Restore Restores a backup (from a Backup object or a raw S3 path) into a target DatabaseInstance. Validates that source and target engine types match.

Credentials are never stored in CRD specs — database and S3 credentials are always referenced via Kubernetes Secrets.

Engine contract

The operator and engine images communicate through a fixed contract (defined in pkg/engine/contract.go):

  • Environment variablesOPERATION (backup/restore), DB_HOST, DB_PORT, DB_NAME, DB_USER, S3_ENDPOINT, S3_BUCKET, S3_PREFIX, BACKUP_ID, plus engine-specific ones like DUMP_FORMAT.
  • Secrets mounted as files/etc/db-secret/password, /etc/s3-secret/access-key, /etc/s3-secret/secret-key.
  • Exit codes0 success, 1 internal error, 2 auth failure, 3 connectivity failure (retried), 4 storage failure (retried).
  • Result JSON — wrapped in ___RESULT_START___ / ___RESULT_END___ markers on stdout, carrying status, timestamps, size, SHA-256 checksum, S3 object keys, and table count.

Retries: max 3 attempts with 30s / 2m / 5m backoff for connectivity and storage failures.

Backups are stored under a predictable S3 layout, with a self-describing manifest so backups remain discoverable and restorable even if the Backup CRD is deleted:

s3://{bucket}/{prefix}/backups/{engineType}/{databaseName}/{backupId}/
├── dump.{format}
└── backup-manifest.json

Getting started

Local development stack

docker-compose.yml spins up PostgreSQL 16 and MinIO (S3-compatible) with a pre-created db-backups bucket:

docker compose up -d

Build and test

make build     # build the operator binary
make test      # run Go tests
make docker-build   # build operator + pg-engine images

Deploy

Install via the Helm chart (charts/kube-db-backup/), which packages the CRDs, operator Deployment, RBAC, and sample application resources:

helm install kube-db-backup charts/kube-db-backup --create-namespace -n db-backup

Configure database connections, S3 credentials, schedules, and images in the chart's values.yaml (or the corresponding manifests under config/). The operator image is overridable via IMG, and the engine images via ENGINE_PG_IMG and ENGINE_MYSQL_IMG (or the PG_ENGINE_IMAGE / MYSQL_ENGINE_IMAGE environment variables on the operator Deployment).

Testing after install

The examples/ directory contains standalone manifests to test each CRD type without re-installing the chart:

# One-shot backups
kubectl apply -f examples/postgres-backup.yaml
kubectl apply -f examples/mysql-backup.yaml

# Scheduled backups
kubectl apply -f examples/postgres-schedule.yaml
kubectl apply -f examples/mysql-schedule.yaml

# Restore into the same instance
kubectl apply -f examples/postgres-restore.yaml
kubectl apply -f examples/mysql-restore.yaml

# Restore into a different target
kubectl apply -f examples/postgres-target.yaml
kubectl apply -f examples/postgres-restore-to-new-target.yaml

# Restore from a raw S3 path (no Backup CRD needed)
kubectl apply -f examples/postgres-restore-from-s3.yaml

Watch progress:

kubectl get backups,restores,backupschedules -n db-backup -w

Adding a new database engine

  1. Build a new engine image that implements the engine contract (see engines/postgres/ for a reference implementation).
  2. Add an entry to the Engine Registry in pkg/engine/registry.go.
  3. Done — no CRD or controller changes.

Project layout

api/v1alpha1/          # CRD Go types (DatabaseInstance, BackupConfig, Backup, BackupSchedule, Restore)
cmd/                   # operator entrypoint (controller-runtime manager)
internal/controller/   # Backup, BackupSchedule, and Restore reconcilers
pkg/engine/            # engine contract + engine registry
engines/postgres/      # the PostgreSQL engine image (backup.sh, restore.sh, entrypoint.sh)
config/                # raw Kubernetes manifests (CRDs, RBAC, manager, samples)
charts/kube-db-backup/ # Helm chart
docker-compose.yml     # local dev stack (Postgres + MinIO)

Documentation

  • ARCHITECTURE.md — component design and rationale
  • PLAN.md — roadmap and engine abstraction strategy
  • REBUILD.md — how to recreate the project from scratch

Roadmap

  • Phase 1 (current): PostgreSQL engine, all 5 CRDs, Job-based contract end-to-end.
  • Phase 2: BackupEngine CRD for runtime engine registration; PITR-capable Postgres engine.
  • Phase 3+: MongoDB, MySQL, then Milvus/Weaviate engines — validating that new databases require only a new image and a registry entry.

About

A Go based Kubernetes operator to backup and restore databases on Kubernetes & OpenShift clusters.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages