Late Capture of Hook-Created Resources
Late capture lets a resource-bound backupPrehook action declare a resource
it creates or updates. Kasten then captures that resource into the restore
point in its post-hook state.
Discovery runs before backupPrehook and never runs again during the
backup. Without a late-capture declaration, a resource the hook creates
never reaches the restore point. Additionally, an updated resource reaches
the restore point in its pre-hook state. See
Per-Resource Backup Processing.
This page describes the declaration contract. For a complete database dump and replay pattern, see the staging PVC how-to.
Declaration Artifacts
A backupPrehook output artifact declares a resource when its name
starts with lateCapture. Kasten reads this artifact after
backupPrehook completes and treats it as a declaration, not as plain
metadata. The prefix is case-sensitive. An artifact named LateCapture or
latecapture is plain metadata, and Kasten does not capture the resource it
describes.
actions:
backupPrehook:
kind: StatefulSet
outputArtifacts:
lateCapture:
keyValue:
apiVersion: "{{ .Phases.createStagingPVC.Output.apiVersion }}"
group: "{{ .Phases.createStagingPVC.Output.group }}"
resource: "{{ .Phases.createStagingPVC.Output.resource }}"
name: "{{ .Phases.createStagingPVC.Output.name }}"
namespace: "{{ .Phases.createStagingPVC.Output.namespace }}"
KubeOps returns these 5 fields as phase
outputs automatically. A KubeTask or KubeExec phase can produce the same
fields with kando output. A declaration can also set the values
directly, without a phase output. See
Output Artifacts.
Each artifact declares one resource. A blueprint can declare several
resources with one lateCapture-prefixed artifact for each, such as
lateCapturePVC1, lateCapturePVC2 and lateCaptureCR.
The following artifact declares a Percona Server for MongoDB backup. It sets
group and gives apiVersion as the version only.
outputArtifacts:
lateCaptureCR:
keyValue:
apiVersion: v1
group: psmdb.percona.com
resource: perconaservermongodbbackups
name: "{{ .Phases.createBackup.Output.name }}"
namespace: "{{ .Phases.createBackup.Output.namespace }}"
Declaration Fields
Every keyValue entry carries the following fields.
| Field | Required | Description |
|---|---|---|
apiVersion |
Yes | API version only, such as v1. Must not include the group. |
group |
Conditional | API group of the declared resource. Omit or leave empty for core resources such as PersistentVolumeClaims and ConfigMaps. Required for custom resources. |
resource |
Yes | Plural, lowercase resource name, such as persistentvolumeclaims |
name |
Yes | Name of the declared resource |
namespace |
Yes | Namespace of the declared resource. Must match the bound workload's namespace. |
A declaration missing apiVersion, resource, name or namespace fails
the backup before Kasten captures anything.
Supported Resource Types
Late capture supports 3 resource types: PersistentVolumeClaims, ConfigMaps and custom resources.
Kasten rejects a declaration of any other type, including Secrets.
Kasten also rejects certain custom resources it already restores through dedicated handling. Examples include KubeVirt VirtualMachines, CDI DataVolumes and resources Kasten must create before workloads, such as NetworkAttachmentDefinitions.
Common Requirements
Every declaration must meet the following conditions.
- The backup is a namespace-scoped application backup. A VM-scoped backup rejects every declaration.
- The declared resource is in the bound workload's namespace.
- The declared resource exists when
backupPrehookfinishes. - The policy's resource filters do not exclude the declared resource.
Staging PVC Requirements
A declared PersistentVolumeClaim must meet these conditions as well.
- The blueprint is bound to a workload. Kasten treats any resource that owns pods as a workload, including an operator custom resource.
- The blueprint does not define a
backupaction. -
The PersistentVolumeClaim is Bound when
backupPrehookfinishes. A hook phase that mounts the volume binds it. -
The PersistentVolumeClaim uses the
Filesystemvolume mode. Kasten rejects theBlockvolume mode. - The PersistentVolumeClaim uses CSI-provisioned storage.
-
The
backupPosthookdeletes the PersistentVolumeClaim. See Capture Behavior.
A blueprint bound to a resource that owns no pods has no volume snapshot step. Kasten fails such a declaration rather than restore an empty volume. ConfigMap and custom resource declarations carry no such restriction.
Capture Behavior
Kasten adds a late-captured PersistentVolumeClaim to the volume snapshot
set and snapshots it after backupPrehook completes. The restore point
then contains the data the hook wrote.
Kasten captures a declared ConfigMap or custom resource as a resource spec. Only PersistentVolumeClaims join the volume snapshot set.
Reuse across backups follows different rules for each resource type:
- ConfigMaps and custom resources. If discovery already captured the resource earlier in the same backup, late capture replaces that copy. Leaving the resource on the cluster between backups is safe.
-
PersistentVolumeClaims. The declared volume must not exist before
backupPrehookcreates it. Kasten fails the whole backup when it already exists.
A crashed or cancelled backup can leave a staging PersistentVolumeClaim
behind, because backupPosthook never ran. That volume still holds the
dump from the previous run, so a snapshot of it could contain stale data.
Kasten fails the next backup that declares the same volume. Delete the
leftover PersistentVolumeClaim before you run the next backup.
Restore Behavior
A restore point stores the lateCapture output artifact and the captured
spec for every declared resource. A declared PersistentVolumeClaim also
carries a volume snapshot.
Kasten restores a late-captured resource like any other captured resource, with no extra configuration.
A restored staging PersistentVolumeClaim remains in the namespace until the restore hook deletes it. If the volume still exists when the next backup runs, Kasten fails that backup. See Capture Behavior.
A restore action reads the declaration when it lists the artifact name in
inputArtifactNames. The action then references the fields through
.ArtifactsIn.<artifactName>.KeyValue.<field>. A restorePosthook uses
this to find the resource name, even when backupPrehook generated that
name. See Input Artifact Names.
actions:
restorePosthook:
kind: StatefulSet
inputArtifactNames:
- lateCapture
phases:
- func: PrepareData
name: replayDump
args:
namespace: "{{ .StatefulSet.Namespace }}"
image: postgres:16
volumes:
"{{ .ArtifactsIn.lateCapture.KeyValue.name }}": /restore
command: ["bash", "-c", "psql -U postgres -f /restore/full.sql"]
failOnError: true
Failure Behavior
A declaration that Kasten cannot honor fails the whole backup. Kasten does not publish a restore point that omits a declared resource.