Kubernetes Operator

Deploy and manage LOX backups in Kubernetes using Custom Resource Definitions (CRDs). GitOps-friendly, auto-scaling, and fully declarative.

v0.1.0-betaBetaUpdated 2026-01-01

Beta Feature

The Kubernetes Operator is currently in beta. APIs may change in future releases. Production use is supported but please report any issues.

Features

  • Custom Resource Definitions for declarative backup management
  • Automatic backup scheduling with CronJob-like syntax
  • PVC and database backup support
  • GitOps compatible (ArgoCD, Flux)
  • Helm chart for easy deployment
  • Prometheus metrics and alerts

Installation

Using Helm

# Add the LOX Helm repository
helm repo add lox https://charts.backlox.com
helm repo update

# Install the operator
helm install lox-operator lox/lox-operator \
  --namespace lox-system \
  --create-namespace \
  --set apiKey=${LOX_API_KEY}

Using kubectl

# Install CRDs
kubectl apply -f https://raw.githubusercontent.com/loxbackup/operator/main/config/crd/bases/backlox.com_backups.yaml
kubectl apply -f https://raw.githubusercontent.com/loxbackup/operator/main/config/crd/bases/backlox.com_backupschedules.yaml

# Create namespace and secret
kubectl create namespace lox-system
kubectl create secret generic lox-credentials \
  --namespace lox-system \
  --from-literal=api-key=${LOX_API_KEY}

# Deploy operator
kubectl apply -f https://raw.githubusercontent.com/loxbackup/operator/main/config/deploy/operator.yaml

Custom Resources

Backup

The Backup resource triggers a one-time backup.

apiVersion: backlox.com/v1alpha1
kind: Backup
metadata:
  name: my-app-backup
  namespace: default
spec:
  # Backup a PVC
  source:
    type: pvc
    pvcName: my-app-data
    # Optional: specific paths within the PVC
    paths:
      - /data
      - /config

  # Backup configuration
  retention:
    days: 30

  tags:
    - kubernetes
    - my-app
    - production

  # Optional: run pre/post backup hooks
  hooks:
    pre:
      - exec:
          container: my-app
          command: ["/bin/sh", "-c", "pg_dump > /backup/db.sql"]
    post:
      - exec:
          container: my-app
          command: ["/bin/sh", "-c", "rm /backup/db.sql"]

BackupSchedule

The BackupSchedule resource creates recurring backups.

apiVersion: backlox.com/v1alpha1
kind: BackupSchedule
metadata:
  name: nightly-backup
  namespace: default
spec:
  # Cron schedule (UTC)
  schedule: "0 2 * * *"

  # Backup template
  template:
    spec:
      source:
        type: pvc
        pvcName: my-app-data

      retention:
        days: 7
        keepLast: 5

      tags:
        - scheduled
        - nightly

  # Keep last N successful backups
  successfulBackupsHistoryLimit: 5
  failedBackupsHistoryLimit: 3

DatabaseBackup

The DatabaseBackup resource backs up databases running in Kubernetes.

apiVersion: backlox.com/v1alpha1
kind: DatabaseBackup
metadata:
  name: postgres-backup
  namespace: default
spec:
  # Database type
  type: postgresql

  # Connection details (from secret)
  connectionSecret:
    name: postgres-credentials
    keys:
      host: PGHOST
      port: PGPORT
      user: PGUSER
      password: PGPASSWORD
      database: PGDATABASE

  # Or reference a Kubernetes service
  service:
    name: postgres
    port: 5432

  # Backup options
  options:
    format: custom  # plain, custom, tar
    compress: 9

  retention:
    days: 30

  tags:
    - postgresql
    - production

Examples

WordPress with MySQL

---
apiVersion: backlox.com/v1alpha1
kind: BackupSchedule
metadata:
  name: wordpress-files
spec:
  schedule: "0 3 * * *"
  template:
    spec:
      source:
        type: pvc
        pvcName: wordpress-data
        paths:
          - /var/www/html/wp-content
      retention:
        days: 30
      tags: [wordpress, files]
---
apiVersion: backlox.com/v1alpha1
kind: DatabaseBackup
metadata:
  name: wordpress-db
spec:
  type: mysql
  schedule: "0 3 * * *"
  connectionSecret:
    name: wordpress-mysql
  retention:
    days: 30
  tags: [wordpress, mysql]

MongoDB Replica Set

apiVersion: backlox.com/v1alpha1
kind: DatabaseBackup
metadata:
  name: mongodb-backup
spec:
  type: mongodb
  schedule: "0 */6 * * *"  # Every 6 hours

  # Connection URI from secret
  connectionSecret:
    name: mongodb-credentials
    keys:
      uri: MONGODB_URI

  options:
    oplog: true  # For point-in-time recovery
    gzip: true
    parallelCollections: 4

  retention:
    days: 14
    keepLast: 10

  tags:
    - mongodb
    - replica-set

Monitoring

Prometheus Metrics

The operator exposes metrics on :8080/metrics:

# Backup metrics
lox_backup_total{status="success", namespace="default"}
lox_backup_total{status="failed", namespace="default"}
lox_backup_duration_seconds{namespace="default", name="my-backup"}
lox_backup_size_bytes{namespace="default", name="my-backup"}

# Schedule metrics
lox_schedule_last_backup_time{namespace="default", name="nightly"}
lox_schedule_next_backup_time{namespace="default", name="nightly"}

# Operator health
lox_operator_reconcile_total
lox_operator_reconcile_errors_total

Alerting Rules

groups:
  - name: lox-backup
    rules:
      - alert: BackupFailed
        expr: increase(lox_backup_total{status="failed"}[1h]) > 0
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "LOX backup failed"
          description: "Backup {{ $labels.name }} in {{ $labels.namespace }} failed"

      - alert: BackupMissing
        expr: time() - lox_schedule_last_backup_time > 86400 * 2
        for: 1h
        labels:
          severity: warning
        annotations:
          summary: "LOX backup schedule missed"
          description: "No backup for {{ $labels.name }} in last 48 hours"

Status

Backup Status

$ kubectl get backups

NAME            STATUS      SIZE       AGE
my-app-backup   Completed   1.2 GB     5m
db-backup       InProgress  -          1m
old-backup      Failed      -          1h

Describe Backup

$ kubectl describe backup my-app-backup

Name:         my-app-backup
Namespace:    default
Status:
  Phase:              Completed
  UUID:               abc123-def456-...
  Size:               1288490188
  Started At:         2025-12-25T03:00:00Z
  Completed At:       2025-12-25T03:05:32Z
  Checksum:           sha256:abc123...
Events:
  Type    Reason    Age   Message
  ----    ------    ----  -------
  Normal  Started   6m    Backup started
  Normal  Uploaded  3m    Backup uploaded to LOX
  Normal  Verified  1m    Backup verified and distributed

Troubleshooting

Backup stuck in InProgress

Check the operator logs: kubectl logs -n lox-system deploy/lox-operator. Common causes: PVC not accessible, insufficient permissions.

CRDs not found

Ensure CRDs are installed: kubectl get crd | grep backlox.com. Re-install with helm upgrade --install.

Debug mode

Enable debug logging: helm upgrade lox-operator lox/lox-operator --set logLevel=debug

RBAC Requirements

The operator requires the following permissions:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: lox-operator
rules:
  - apiGroups: ["backlox.com"]
    resources: ["backups", "backupschedules", "databasebackups"]
    verbs: ["*"]
  - apiGroups: [""]
    resources: ["pods", "persistentvolumeclaims", "secrets"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create"]
  - apiGroups: ["batch"]
    resources: ["jobs"]
    verbs: ["*"]