Skip to content

RepositoryReplication

A RepositoryReplication mirrors a repository's blobs to a second backend on a schedule, using kopia repository sync-to. It is the "2" in a 3-2-1 backup strategy.

For the short type-and-default table see the field reference. For task guidance see Replication.

A RepositoryReplication is namespaced. It lives beside its source repository, the same way Maintenance does, and references either a namespaced Repository or a cluster-scoped ClusterRepository. The controller schedules one mover Job per slot, using the same machinery as Maintenance: croner, deterministic jitter, single-flight, and a repository-ready gate.

spec

sourceRef

The Repository or ClusterRepository to mirror from. Credentials and connect details come from it.

destination

The backend to mirror to. It is exactly one backend, written as the same single-key Backend object the repository types use, for example destination: { s3: {…} }.

The destination must differ from the source's backend. The admission webhook rejects a same-backend mirror, because replicating a backend onto itself means nothing.

The destination's own access credentials come from its auth.secretRef, or auth.workloadIdentity, exactly like a source repository. sync-to is a blob-level copy, so the mirror always inherits the source repository's format and encryption password, and there is no separate destination password.

The destination credential Secret must live in the RepositoryReplication's own namespace, because the mover loads it with envFrom, which only reads the local namespace, and replication does not project credentials. Use the same key names a source Secret would use.

The source and destination may use different credentials. Kopiur delivers the destination Secret under a KOPIUR_DEST_ environment prefix, so the two sides' keys never collide. See Destination credentials.

schedule

Cron and deterministic jitter for the replication runs, using the same scheduling machinery as Maintenance.

mover

Overrides for the replication run's mover Job pod: resources, scheduling and security context. It inherits the source repository's moverDefaults underneath.

suspend

Pause this replication from the manifest, default false. A suspended RepositoryReplication is skipped by its own reconcile, so no sync runs, and the state shows up in a condition.

sync

Tuning for the underlying kopia repository sync-to call, from issue #216. Every field is optional. Leaving out the sync block, or a field inside it, reproduces kopia's own default for that flag. See Tuning the sync.

Field kopia flag Meaning
parallel --parallel Concurrent blob-copy workers (kopia default 1, sequential; the main knob for a slow initial seed).
deleteExtra --delete Prune destination-only blobs for a true mirror (kopia default false, additive sync). Deletes destination content; see the safety note in the guide.
mustExist --[no-]must-exist Fail instead of initializing the destination's repository-format blob (kopia default false).
times --[no-]times Synchronize blob modification times to the destination, when supported (kopia default true).
update --[no-]update Update blobs already present at the destination when the source copy is newer (kopia default true).
maxDownloadSpeedBytesPerSecond --max-download-speed Cap read throughput from the source, bytes/sec (kopia default: unlimited).
maxUploadSpeedBytesPerSecond --max-upload-speed Cap write throughput to the destination, bytes/sec (kopia default: unlimited).

parallel and the two speed caps must be 1 or greater when set, which the admission webhook enforces.

Out-of-band runs

To trigger a one-off mirror, annotate a RepositoryReplication with kopiur.home-operations.com/run-requested set to an RFC 3339 timestamp. There is no run-mode companion, because a replication has only one kind of run.

The timestamp identifies which request the status answers, so re-applying the same value does nothing and a new timestamp starts a new run.

The requested run goes through the same mover, the same gates and the same single-flight rule as a cron slot. Because it stamps status.lastReplicated on success, it also re-anchors the next scheduled slot. See Run it now. kubectl kopiur replication run stamps the annotation for you.

A malformed timestamp is refused at admission

The admission webhook rejects a run-requested value that is not RFC 3339, naming the bad value and the fix, so in practice a malformed annotation never reaches the controller.

An object annotated while the webhook was down degrades gracefully instead of stalling. The schedule keeps running, and the controller reports Ready=False with reason InvalidRunRequest on the next pass where no cron slot is due. A due slot's own report takes that one Ready write, so on a very frequent schedule the message appears once the replication next goes idle.

status

phase

The lifecycle phase: Pending (admitted, not yet run, which is the default), Replicating (a mover Job is in flight), Succeeded (the last run completed and it is idle until the next slot), Failed (the last run failed; see conditions), or Suspended (paused through spec.suspend).

manualRun

The state of the most recent annotation-requested run: the requestedAt value it answers, its phase, and the completedAt instant it reached a terminal one. It is absent until a run is requested.

phase Meaning
Pending Recorded but not started, either because the replication is suspended or because the request is waiting behind an in-flight run. It runs once you unsuspend, or once that run finishes.
Running The requested mover Job is in flight.
Succeeded The requested run completed.
Failed The requested run's Job failed; conditions carry the detail.

others

Field Meaning
observedGeneration The metadata.generation last reconciled, for staleness detection and kstatus.
destinationBackend The destination backend kind, mirroring the spec.destination discriminant, behind the DESTINATION print column.
lastReplicated RFC 3339 timestamp of the most recent successful replication run, behind the LAST print column.
nextScheduledAt RFC 3339 timestamp of the next scheduled run, with cron and jitter already applied.
lastReplicatedBytes Bytes replicated by the last successful run, read from kopia output where available.
lastReplicatedBlobs Blobs replicated by the last successful run, read from kopia output where available.
conditions Standard Kubernetes conditions: Ready, Reconciling, Stalled.