Skip to content

BackupSchedule CRD

The BackupSchedule Custom Resource Definition defines cron-based scheduled backups. Each run creates a Backup CR; retention is controlled by history limits.

Overview

  • API Group: retour.thebackup.company/v1
  • Kind: BackupSchedule
  • Scope: Namespaced
  • Cron format: Standard 5-field cron (minute, hour, day-of-month, month, day-of-week).

Spec

Required Fields

Field Type Description
schedule string Cron expression (5 fields). Example: 0 2 * * * (daily at 02:00).
storageBackend string Name of the StorageBackend for backups.

Optional Fields (with defaults)

Field Type Default Description
namespacedResources array [] Resources to backup (same as Backup).
clusterResources array [] Cluster-scoped resources.
excludePVs bool false Skip PV data.
resourceFilter object nil Include/exclude filters.
suspend bool false If true, pause subsequent runs.
successfulBackupsHistoryLimit int32 3 Number of successful backups to retain.
failedBackupsHistoryLimit int32 1 Number of failed backups to retain.
concurrencyPolicy string Allow How to handle overlapping runs.

ConcurrencyPolicy

Value Behavior
Allow Create new backup even if previous is still running.
Forbid Skip the run if a backup is already in progress.
Replace Cancel the running backup and start a new one.

Retention

successfulBackupsHistoryLimit keeps a flat count. retention replaces it with grandfather-father-son tiers, keeping the newest backup per period up to each count:

Field Type Description
retention.keepHourly int32 Newest backup of each hour to keep.
retention.keepDaily int32 Newest backup of each day.
retention.keepWeekly int32 Newest backup of each week.
retention.keepMonthly int32 Newest backup of each month.
retention.keepYearly int32 Newest backup of each year.
backupDeletionPolicy string Whether expiring a backup also purges its data from the backend. Object Lock retention still defers the purge.

Backups are not owned by their schedule, so deleting the schedule leaves its backups and their data in place.

Restore Drills

drill restores this schedule's newest successful backup into scratch retour-drill-* namespaces on its own cron, optionally runs a check pod against the result, and deletes the scratch namespaces afterwards.

Field Type Description
drill.schedule string Cron expression for drill runs. Independent of the backup cron.
drill.check.image string Image the check container runs.
drill.check.command []string Command whose non-zero exit fails the drill. Restored claims are mounted at /data/<claimName>.
drill.check.namespace string Original namespace whose scratch clone the check runs in. Defaults to the first restored namespace.
drill.check.timeoutSeconds int32 Bounds the check run. Default 300.

The outcome lands in status.lastDrill, a Kubernetes event, and the retour_restore_drill_* metrics. A drill with no volumes to restore is recorded as Skipped, not Failed.

Timing

Field Type Default Description
startingDeadlineSeconds int64 — How long after a missed fire time a run may still start, with CronJob semantics. Without it, a rollout or API blip that crosses the fire time drops the run. A skipped run is an event and a counter either way.
suspend bool false Pause subsequent runs.

Inherited by Every Backup

These are copied onto each Backup the schedule creates and behave exactly as they do on Backup: scope, excludedNamespaces, includedSystemNamespaces, includeWebhookConfigurations, resourceDiscovery, namespaceSelector, hooks, databases, secrets, volumeGroups, skipVerification and bandwidthLimit.

Status

Field Type Description
phase string Pending, Active, Suspended, or Failed.
lastScheduleTime string When the last backup was created.
lastBackupName string Name of the last Backup CR created.
lastBackupStatus string Status of the last backup.
nextScheduleTime string When the next backup will run.
activeBackups []string Names of backups currently running.
error string Error message if schedule failed.
lastDrill object Outcome of the last restore drill: phase, what was restored, and the check result.
lastDrillTime string When the last drill ran.
lastSelectedNamespaces []string Namespaces the last run matched, for schedules that select by label.
conditions array Standard Kubernetes conditions, including QuotaExceeded when a BackupQuota is holding this schedule back.

Examples

Daily Backup at 02:00

apiVersion: retour.thebackup.company/v1
kind: BackupSchedule
metadata:
  name: daily-backup
spec:
  schedule: "0 2 * * *"
  storageBackend: s3-production
  namespacedResources:
    - resourceType: Deployment
      namespace: production
      name: webapp
  successfulBackupsHistoryLimit: 7

Hourly with Forbid (No Overlap)

apiVersion: retour.thebackup.company/v1
kind: BackupSchedule
metadata:
  name: hourly-backup
spec:
  schedule: "0 * * * *"
  storageBackend: s3-production
  concurrencyPolicy: Forbid
  namespacedResources:
    - resourceType: StatefulSet
      namespace: production
      name: database
  successfulBackupsHistoryLimit: 24
  failedBackupsHistoryLimit: 3

Weekly Full Namespace Backup

apiVersion: retour.thebackup.company/v1
kind: BackupSchedule
metadata:
  name: weekly-namespace
spec:
  schedule: "0 3 * * 0"
  storageBackend: s3-production
  clusterResources:
    - resourceType: Namespace
      name: production
  successfulBackupsHistoryLimit: 4

Suspended Schedule

apiVersion: retour.thebackup.company/v1
kind: BackupSchedule
metadata:
  name: paused-schedule
spec:
  schedule: "0 2 * * *"
  storageBackend: s3-production
  suspend: true
  namespacedResources:
    - resourceType: Deployment
      namespace: production
      name: webapp

Manifests Only (No PV Data)

apiVersion: retour.thebackup.company/v1
kind: BackupSchedule
metadata:
  name: manifests-schedule
spec:
  schedule: "0 */6 * * *"
  storageBackend: s3-production
  excludePVs: true
  clusterResources:
    - resourceType: Namespace
      name: production
  successfulBackupsHistoryLimit: 28

GFS Retention with a Weekly Drill

apiVersion: retour.thebackup.company/v1
kind: BackupSchedule
metadata:
  name: nightly
spec:
  schedule: "0 3 * * *"
  storageBackend: s3-production
  startingDeadlineSeconds: 3600
  clusterResources:
    - resourceType: Namespace
      name: production
  retention:
    keepDaily: 7
    keepWeekly: 4
    keepMonthly: 12
  drill:
    schedule: "0 5 * * 0"
    check:
      image: postgres:17
      command: ["sh", "-c", "test -s /data/db-data/PG_VERSION"]