Capability reference
The tutorials cover a first backup and a first restore. This page lists what
Retour grew after that: what each capability does, the field that turns it on,
and nothing you have to read twice. docs/PRODUCT.md in the repository carries
the full reference for every one of them.
Proving backups restore
BackupSchedule.spec.drill restores the schedule's newest successful backup
into scratch retour-drill-* namespaces on its own cron. A check pod can run
against the result, with every restored claim mounted at /data/<claimName>;
the scratch namespaces are then deleted. The outcome lands in
status.lastDrill, a Kubernetes event, and the retour_restore_drill_*
metrics.
spec:
drill:
schedule: "0 5 * * 0"
check:
image: postgres:17
command: ["sh", "-c", "test -s /data/db-data/PG_VERSION"]
Verification is separate and runs by default at both ends. After upload the
carrier compares the destination against the still-mounted source and decodes
the stored metadata document. After a restore, the restored volume is checked
back against the backup it came from, using the same filters the restore copied
with, so a truncated download is not reported as a successful recovery. A
failure fails the operation; on the backup side success lands as a Verified
condition. Turn either off with spec.skipVerification on the Backup or the
Restore. Kopia-written operations verify themselves: a content-addressed
repository cannot hand back a corrupt file without failing.
Retention, immutability, and cost
BackupSchedule.spec.retention keeps the newest backup per hour, day, week,
month, and year up to each keep* count, instead of the flat
successfulBackupsHistoryLimit. A standalone backup can carry spec.ttl,
which expires it through the same deletion path.
StorageBackend.spec.s3.immutability (mode: GOVERNANCE|COMPLIANCE,
retainDays) stamps S3 Object Lock retention on every uploaded object.
Deletion waits for the lock to expire, and a lock that cannot be applied fails
the backup.
StorageBackend.spec.engine: kopia stores deduplicated, compressed snapshots
in a repository instead of copying files path-addressed, so a run uploads only
what changed. It works on s3, azureblob, and gcs.
spec.transfer governs the pipe itself: bandwidthLimit (rclone timetable
syntax, which gives you backup windows for free), transfers, and checkers,
set per backend and overridable per backup or schedule.
What gets captured
Backup.spec.scope: Cluster sweeps every namespace and the cluster-scoped
resources. System namespaces are excluded by default, and both
excludedNamespaces and the retour.io/exclude-from-backup annotation are
honored.
resourceDiscovery: Dynamic enumerates every namespaced resource the API
server actually serves, so operator CRs are captured rather than missed by a
fixed registry. The sensitive-resource deny-list still filters first.
Backup.spec.secrets.mode: EncryptedOptIn adds the Secrets stream. It needs
three things: an operator-level admin switch, a crypt backend, and a
passphrase of its own that differs from the main one.
Raw volumeMode: Block claims are streamed as one image, with a SHA-256
recorded at backup and enforced at restore. VirtualMachine and DataVolume
are in the resource registry for KubeVirt; pair them with hooks for
guest-filesystem consistency.
Hooks hold one exec session across the snapshot window, with profiles shipped
for PostgreSQL, MySQL, MongoDB, Redis, and qemu-guest freeze. For
CloudNativePG, spec.databases.cnpg.mode: Delegate hands protection to the
database operator and records the backup id and LSNs in the metadata.
spec.volumeGroups cuts label-grouped CSI VolumeGroupSnapshots so several
volumes are captured at one instant. Where the cluster has no
VolumeGroupSnapshot API, the fallback is recorded rather than assumed.
Restoring with control
namespaceMapping,storageClassMapping, andimageRewritesretarget a restore at a different namespace, storage class, or registry.resourceModifiersapplies selector-scoped RFC 6902 JSON patches or RFC 7386 merge patches to manifests before they are created.existingResourcePolicy: Keep|Update|Replacedecides what happens to objects that already exist. PVCs are exempt;spec.targetPVCis how data is restored into an existing claim.dryRun: truerenders the plan, patches and collisions included, without applying anything.pathFiltersrestores selected files instead of whole volumes. The UI browses the catalog and builds the CR for you.scaleWorkloadsToZerolands workloads stopped, so nothing races the data.
Continuity and migration
Nothing in the stored format is tied to a vendor: the data goes through rclone
or kopia and the manifests are plain YAML, so a backup taken in one data center
restores in another. On-premise Ceph to a cloud provider, one region to the
next, or between two providers that share nothing but the network.
namespaceMapping and storageClassMapping handle the differences, so the
target cluster does not have to look like the source, and
Disaster Recovery covers restoring with no Backup CR present.
A RestoreSync on a standby cluster polls the shared storage backend, works
out what the primary wrote from the metadata documents alone, and creates
Restores from a template. mode: Latest replays the newest qualifying backup;
Continuous replays every new one, oldest first. The standby never connects to
the primary.
apiVersion: retour.thebackup.company/v1
kind: RestoreSync
metadata:
name: shop-dr
spec:
storageBackendRef: shared-dr-bucket
pollInterval: 15m
selector:
scheduleName: nightly
restoreTemplate:
namespaceMapping:
shop: shop
scaleWorkloadsToZero: true
Restore.spec.veleroImport reads an existing Velero backup out of object
storage: manifests always, and volume data for the backups kopia wrote
(volumeData.enabled: true, plus the source cluster's repository password as a
Secret). The Velero repository is connected read-only, and imported content
passes the same deny-list, mappings, modifiers, and dry run as a native
restore.
Governance
The cluster-scoped BackupQuota CR caps active backups, backups per day,
schedules, schedule frequency, and total size per namespace. A backup over
quota is held in Pending rather than failed, and proceeds once the pressure
clears. Full field reference:
BackupQuota.
A schedule that stops firing is exported rather than left to be noticed:
last-success, next-run, missed-runs and suspended gauges per schedule, with
shipped alerts on all of them. startingDeadlineSeconds lets a run that missed
its window by a rollout or an API blip still start, with CronJob semantics, and
a genuinely skipped run is an event and a counter. Deleting a schedule leaves
its backups and their data alone, and retention will not purge a backup while a
restore is reading it.
Every mutating request through the UI server is recorded append-only with the
actor taken from the verified identity. Admins can query and export it, and the
CRs the server creates are stamped with retour.io/requested-by.
The operator writes a periodic protection report (backups and restores by phase, schedules out of SLA, unprotected namespaces, drill outcomes) as ConfigMaps, and uploads it to a storage backend when one is configured.
spec.encryption.keySource (aws-kms or vault-transit) wraps the encryption
material so only ciphertext is stored. Each job unwraps it just in time into a
short-lived secret, and rotation is a rewrap.