Expand description
Shared sub-objects reused across multiple CRDs.
Per ADR-0003 §2.2 (principle 10) and §4.11, every credential, policy, and
identity surface is modeled as a sub-object so future fields slot in without
API breakage. Leaf Kubernetes types (LabelSelector, ResourceRequirements,
PodSecurityContext) are reused from k8s-openapi rather than re-invented.
Structs§
- Cache
Defaults - kopia cache defaults inherited by every mover unless overridden per-recipe.
- Catalog
Bounds - Bounds on materialization of
origin: discoveredSnapshotCRs. - Catalog
Retain - Bounds on the number of discovered
SnapshotCRs kept materialized. - Config
MapKey Ref - Reference to a key within a
ConfigMap(e.g. a CA bundle). - Create
Behavior - Behavior when the repository does not yet exist.
- Credential
Projection - Opt-in projection of a repository’s credential
Secret(s) into each mover Job’s namespace. - Cron
Spec - A single cron entry with optional deterministic jitter.
- Deletion
Protection Spec - Mass-deletion circuit breaker for this repository’s Snapshots.
- Ecc
- Reed-Solomon error-correcting-code parity for a freshly-created repository.
- Encryption
- Repository encryption settings.
- Failure
Block - A structured terminal-failure block written by the mover to
status.failure. - Failure
Policy - Per-run failure controls passed through to the mover
Job. - Identity
- Identity overrides — what kopia records as
username@hostname:path. - Identity
Defaults - CEL expressions evaluated at admission to derive consumer identity when a
SnapshotPolicydoesn’t override. Shared byRepositoryandClusterRepository(M5 gave the namespaced kind the same surface the cluster-scoped kind has had since M1) — both mean the same thing: this repository’s backend is (or may be) shared, so its consumers need a hostname/username recipe beyond the bare per-namespace default. - Mover
Defaults - Repository-wide mover defaults inherited by every mover, overridable per-recipe via
mover. - Mover
Spec - Per-recipe mover overrides (resources, cache, security context).
- Object
Ref - Generic name/namespace reference to another namespaced object (e.g. a
SnapshotCR or PVC). - PodSelector
- Selects workload pods by label.
- Policy
Ref - Reference to a
SnapshotPolicyCR. - PvcConsumer
Inherit - Tuning for
InheritSecurityContextFrom::PvcConsumer. - Repository
Ref - Reference from a consumer CR to a
RepositoryorClusterRepository. - Resolved
Identity - Fully-resolved identity pinned into status; never re-rendered after admission.
- Resolved
Mover - The fully-resolved mover configuration for a single run, after the 3-layer
field-wise merge
hardened ⊂ repo.moverDefaults ⊂ recipe.mover(ADR-0004 §1/§2).security_contextis ALWAYS present (the hardened base guarantees it); the rest areSomeonly when some layer set them. The privileged-mover gate (§4.11/§G16) runs onsecurity_context/pod_security_contexthere — the merged result — not on the raw recipe, so an elevation introduced bymoverDefaultsis still gated. - Retention
- GFS retention policy — how many snapshots to keep per time bucket.
- Schedule
Defaults - Repo-level scheduling defaults, inherited at reconcile time by consumers that don’t set their own equivalent field (ADR §2.2 principle 10: sub-object, not a leaf field, so future defaults — e.g. jitter — slot in without API breakage).
- Scratch
Defaults - Defaults for the deep-verification scratch volume — the throwaway restore-test target.
- Secret
KeyRef - Reference to a key within a
Secret. - Secret
Ref - Reference to an entire
Secret(the operator reads well-known keys from it). - Snapshot
Inherit - Tuning for
InheritSecurityContextFrom::Snapshot. Empty today; a sub-object (likePopulatorTarget) so future knobs slot in without API breakage. - Source
Colocation - Controls mover/source-PVC node co-location (RWO Multi-Attach avoidance).
- Throttle
- Repository-wide throttling for a mover’s kopia connection; each
Noneleaves kopia’s current limit. - Timezone
Ambiguity - Matched
SnapshotScheduletarget policies disagreed on their repositories’scheduleDefaults.timezone, soeffective_timezonecould not pick one unambiguously and fell back to UTC. The controller surfaces this as a status condition recommending an explicitspec.schedule.timezone. - TlsConfig
- TLS settings for object-store backends.
Enums§
- Cache
Volume Mode - How a mover’s kopia cache volume is provisioned.
- Deletion
Policy - Lifecycle of the underlying kopia snapshot when its
SnapshotCR is deleted. Produced backups default toDelete; discovered snapshots are forced toRetain. - Foreign
Snapshots - How catalog discovery treats snapshots written by ANOTHER cluster.
status.catalog.foreignSnapshotCountcounts an identity hostname carrying a different.<cluster>suffix ALWAYS, under either value below, plus — underIgnoreonly — a bare hostname naming no allowed namespace here. UnderFallback, that same disallowed bare host is NOT counted foreign: it materializes intocatalog.fallbackNamespaceexactly like a disallowedOwnClusterhost would, so it is placed rather than dropped-and-counted (seeclassify_hostname/decide_cluster_placement). Meaningful only whenidentityDefaults.clusteris set: without a cluster identity there is no notion of “foreign” and the legacy hostname-names-a-namespace placement applies (validators enforce this). - Inherit
Security Context From - Where the mover copies its security context from instead of an explicit context.
- Namespace
Delete Policy - What happens to a repository’s snapshots when a consuming namespace is deleted; default
Orphan. - Policy
Delete Policy - What the deletion of a
SnapshotPolicydoes to theSnapshotCRs carrying its config label (the recipe’s produced/adopted rows — NOT its kopia snapshot history in the abstract, which is exactly whatRetainpreserves). DefaultRetain: the CRs are removed but every kopia snapshot survives (rediscoverable/adoptable by a futureSnapshotPolicy, including this one re-created).Deleteopts into the cascade: each CR’s owndeletionPolicyapplies, as EXTERNAL deletions subject to the per-repository mass-deletion breaker (deletionProtection.threshold). - PvcAccess
Mode - A PersistentVolumeClaim access mode as a closed set —
ReadWriteOnce,ReadOnlyMany,ReadWriteMany,ReadWriteOncePod— so a typo is rejected by the CRD schema itself instead of surfacing as a provisioner error at the first backup or restore run. - Repository
Kind - Which kind of repository a consumer CR references (
RepositoryorClusterRepository). - Repository
Mode - Repository access mode;
ReadOnlyserves restores only (no backups, no maintenance). - Schedule
Delete Policy - What the deletion of a
SnapshotScheduledoes to theSnapshotCRs it produced (which Kubernetes GC cascade-deletes via their ownerReference). DefaultRetain: the CRs are removed but their kopia snapshots survive and the catalog rediscovers them asorigin: discovered.Deleteopts into the cascade: each Snapshot’s owndeletionPolicyapplies. - Snapshot
Adoption - Whether a discovered snapshot whose resolved identity matches a live
SnapshotPolicyis automatically adopted — re-attached (stamped with that policy’s config label,status.originflipped toAdopted) so GFS retention governs it and eventually prunes it, instead of it sitting in the catalog forever as an immortaldiscoveredrow. - Source
Colocation Mode - How the mover co-locates with the node an RWO source/destination PVC is attached to.
Constants§
- DEFAULT_
JOB_ TTL_ SECONDS - Built-in default
Job.spec.ttlSecondsAfterFinished(1h) applied to a mover Job when neithermoverDefaults.ttlSecondsAfterFinishednor the recipe’smover.ttlSecondsAfterFinishedsets one, so finished backup/restore Jobs and their pods self-GC instead of lingering (ADR-0005 §12). - DEFAULT_
POD_ STARTUP_ DEADLINE_ SECONDS - Default grace before a non-starting (wedged) mover pod fails its run — 5 minutes.
Long enough to absorb a slow image pull or a brief
Unschedulablewhile an RWO volume detaches from another node, short enough that a genuinely-broken pod (e.g. an impossible securityContext, a missing image) surfaces asFailedfast instead of hanging for hours. - MAX_
LOG_ TAIL_ BYTES - Byte cap for
status.logTail(and the stderr tail insideFailureBlock): the mover truncates to the LASTMAX_LOG_TAIL_BYTESbytes before patching status, so a noisy kopia run can’t bloat etcd. Full logs live in the mover Job’s pod. ADR §3.4/§4.10. - MOVER_
NONROOT_ ID - The nonroot UID/GID baked into the mover image (
docker/Dockerfile.mover:USER 65532:65532, distrolessnonroot). The hardened pod context defaultsfsGroupto this so the kubelet group-owns every mounted volume to the gid the mover actually runs as — most importantly the operator-managed kopia cache, which is otherwise createdroot:rooton PVC-backed storage and unwritable by the unprivileged mover. Centralized here (the single source of the hardened defaults) so the value can never drift from the image.
Traits§
- Phase
Label - A lifecycle-phase enum that can be rendered as a metric label.
Functions§
- create_
enabled - Whether the operator should create the repository when it does not yet exist.
- effective_
adoption - The effective adoption policy for a
SnapshotPolicy: its ownspec.adoptionwins; else the target repository’scatalog.adoption; elseSnapshotAdoption::Adopt. Neither link is context-free (the repository link resolves per-repo, the policy link per-policy), so neither field carries a schema default — every read goes through this resolver. - effective_
run_ as_ group - The effective
runAsGroupfollowing kubelet precedence — the gid peer ofeffective_run_as_user: containersecurityContext.runAsGroupif set, else the pod one.Nonewhen neither pins a group (image-determined). - effective_
run_ as_ user - The effective
runAsUserfollowing kubelet precedence: the containersecurityContext.runAsUserif set, else the podsecurityContext.runAsUser.Nonewhen neither pins a UID — the UID is then image-determined (theUSERline) and unknowable from the spec. - effective_
timezone - Pure. Decide the effective timezone a
SnapshotSchedule’s cron is evaluated in, given the schedule’s ownspec.schedule.timezone(own) and thescheduleDefaults.timezoneof each matched target policy’s repository (policy_repo_defaults, one entry per matched policy;None= that repo sets no default). Mirrorsresolve_tzfallback semantics (an unparseable name degrades to UTC — the webhook rejects bad names up front). - hardened_
pod_ security_ context - The restricted-PSA-compatible hardened pod security context — the pod-level
peer of
hardened_security_context. DefaultsfsGrouptoMOVER_NONROOT_IDso every mover pod’s volumes (notably the cache) are writable by the unprivileged mover;fsGroupChangePolicy: OnRootMismatchskips the recursive chown when the volume root already matches, so it does not needlessly rewrite ownership on every run. - hardened_
security_ context - The restricted-PSA-compatible hardened container security context (§4.11/G16):
non-root, no privilege escalation, drop ALL caps, seccomp
RuntimeDefault. - merge_
capabilities - Deep-merge two [
Capabilities]: each ofadd/dropis taken fromoverwhen set, else frombase. So anoverthat sets onlyaddkeepsbase.drop— an add-only override never silently drops the hardeneddrop:[ALL](the bug ADR-0004 §2 cites). - merge_
context_ pair - THE layer merge: overlay one
(container, pod)security-context layer pair onto another. Every layer fold —resolve_mover’shardened ⊂ moverDefaults ⊂ recipeand the controller’sinherited ⊂ explicitpre-fold — MUST go through this function; a lone per-dimensionmerge_security_context/merge_pod_security_contextreintroduces cross-dimension identity shadowing. - merge_
pod_ security_ context - Field-wise overlay of pod [
PodSecurityContext]overontobase. Exhaustive literal for the same reason asmerge_security_context. - merge_
pod_ security_ context_ opt Option-awaremerge_pod_security_context.- merge_
resources - Field-wise overlay of [
ResourceRequirements]:limits/requestsmerge per-key (viamerge_quantity_map);claimsis taken fromoverwhen set, elsebase. - merge_
resources_ opt Option-awaremerge_resources.- merge_
security_ context - Field-wise overlay of container [
SecurityContext]overontobase: eachSomefield inoverwins, unset fields inheritbase;capabilitiesdeep-merge viamerge_capabilities(ADR-0004 §2). - merge_
security_ context_ opt Option-awaremerge_security_context(handles the fourNone/Somecases).- pod_
security_ context_ is_ elevated - Whether a pod
PodSecurityContextrequests root. Pod-level only carries a subset of the container knobs —runAsUser/runAsNonRootare the ones that can make the mover root (capabilities/privileged are container-only).fsGroupand friends are NOT elevation. Pure helper forrequires_privilege_resolved. - pod_
startup_ deadline_ seconds - The effective pod-startup deadline (seconds) for a mover Job: the recipe’s
failurePolicy.podStartupDeadlineSeconds, orDEFAULT_POD_STARTUP_DEADLINE_SECONDSwhen unset. Shared by every reconciler that fast-fails a wedged mover (Snapshot, Restore, Maintenance) so the same default is applied identically on all three. - requires_
privilege_ resolved - Whether a mover with the given effective container security context (the
explicit
securityContext, or the one resolved frominheritSecurityContextFrom), pod security context, andprivilegedModeis privileged. The controller resolves an inherited context to a concreteSecurityContextand gates on that — so an inherited root context is caught exactly like an explicit one — and inspects the pod-level context too so a pod-levelrunAsUser: 0can’t slip past. Pure + exhaustive: the single definition of “privileged” for both the spec-only ([MoverSpec::requires_privilege]) and the resolved paths. - resolve_
mover - Resolve the effective mover configuration via the layer merge
hardened ⊂ moverDefaults ⊂ recipe(ADR-0004 §1/§2). - resolve_
tz - Resolve an optional IANA timezone name to a concrete zone, defaulting to UTC.
An unparseable name falls back to UTC defensively — the admission webhook rejects
bad names up front via
validate::validate_timezone, so reconcile-time resolution should never see one. - resolve_
tz_ with_ default - Resolve a consuming cron’s own optional IANA timezone against a repository-level
default, falling back to UTC (mirrors
resolve_tz):ownwins when set, elserepo_default(typicallyRepository/ClusterRepositoryspec.scheduleDefaults.timezone), else UTC. An unparseable name at whichever level is selected falls back to UTC defensively, same asresolve_tz— the admission webhook rejects bad names up front for both levels viavalidate::validate_timezone, so reconcile-time resolution should never see one. - security_
context_ is_ elevated - Whether a container
SecurityContextrequests privileges beyond a normal unprivileged user (root UID,privileged, escalation, added capabilities, or an explicitrunAsNonRoot: false). Pure helper for [MoverSpec::requires_privilege].