Repository navigation
feat(backups): declare consistency guarantees and covered volumes for backup and restore #720
Description
Expose a backup's actual consistency and volume coverage, and let administrators require the level needed for recovery. Today a requested quiesce can proceed as unsupported, while both backup strategies capture only the primary data PVC. A successful copy therefore does not establish a complete, application-consistent recovery point for every module.
This is an enhancement proposal based on static inspection of master 04e41075cafc4c1a99bcb3723b0a8745ee810957 and module commit 91b64cc1e40ab76eef6209ec25995fc5e70b2245. No restore failure or data loss was reproduced.
Trigger and impact
Back up a running game whose module has no complete quiesce sequence, or a server using extra PVCs or separate version/loader mod volumes. The agent reports unsupported quiesce; the operator records that outcome and proceeds with a raw copy. Restic mounts only the primary claim, and CSI snapshots that same claim.
For 7 Days to Die, the primary PVC contains the world saves, so its worlds are included. Its extra serverfiles PVC holds the installation and can contain configuration/mod files. Separate Minecraft loader/mod PVCs likewise fall outside the primary backup. Administrators need a durable manifest to distinguish a world-only recovery from a complete server recovery, including the files and module version they must reconstruct.
Pinned evidence
- The agent treats missing/incomplete sequences as unsupported.
- The operator proceeds after unsupported quiesce.
- Restic mounts only the primary claim; CSI snapshots the primary claim.
- Separate loader/mod PVCs remain independent.
- 7 Days to Die world and extra mounts; serverfiles contents.
Recommended implementation
Add a requested consistency policy, for example best-effort, application-consistent, or stopped. Preserve existing behavior through an explicit compatibility default, but record the achieved guarantee separately. Unsupported quiesce must produce a visible condition; strict requests should fail before copying or use an authorized graceful-stop workflow.
Persist a backup manifest containing GameServer UID, module/template digest, selected game version, volume identities, mount paths, inclusion/exclusion reasons, and achieved consistency. Pin that manifest at capture time rather than deriving it from the current template during restore.
Allow modules to classify extra/mod volumes as required, reconstructible, or excluded, with administrator overrides. Support multi-volume Restic capture and restoration using named roots. For CSI, require a supported coordinated snapshot mechanism or describe the per-volume limitation; do not imply atomicity from sequential independent snapshots. Validate the manifest before destructive restore, and surface missing required volumes before changing the target.
Acceptance criteria
- CI covers unsupported quiesce under each policy and distinguishes achieved consistency from copy success.
- Backup status and API/UI can report included/excluded volumes and recovery prerequisites.
- A primary-world plus required-extra-volume fixture restores both; a reconstructible install remains optional.
- Template/version changes after backup do not rewrite its manifest or silently redirect restore paths.
- Legacy backups retain an explicit legacy/unknown manifest state and a documented recovery path.
Preserve the quiesce cleanup and serialization work in #454 and #590. This proposal extends their contract without treating unsupported-quiesce behavior as a newly discovered regression.
Activity
ValgulNecron commentedon Oct 20, 2026
Thanks, the gap is real: when a module has no quiesce sequence the backup proceeds as a raw copy with only an annotation (
operator/internal/controller/backup_controller.go:391-415), and both Restic and CSI cover only the primary<server>-dataclaim (backup_controller.go:~980-1006,backup_volumesnapshot.go:49-64), so modules with extra volumes such as 7 Days to Die are not fully captured. Two small notes: the code already documents CSI snapshots as crash-consistent only, andBackup.spec.quiescealready exists as an opt-out (operator/api/v1alpha1/backup_types.go:76), so anything new needs to sit alongside it.Go ahead with a PR scoped to the first step:
template.yaml) that marks an extra volume as real data or as rebuildable (re-downloaded, safe to skip). Volumes without it show as "not covered" in the manifest, so no existing module breaks; modules can fill it in later in GameplanePanel/module.Please leave the
stoppedpolicy (stop, copy, restart) and multi-volume Restic copies for a follow-up issue, since stopping games is an availability change that needs its own design.Baylem commentedon Oct 25, 2026
The requested first step is implemented in #767: a Consistency condition reports the achieved result, and a capture-time manifest records included and uncovered claims, mount paths and identities. Optional storage.extra[].backupRole accepts data or rebuildable; omission remains valid and leaves the volume unclassified/not covered. Existing captures keep unknown historical coverage.
The existing quiesce opt-out remains. This PR does not stop a running game or copy multiple volumes. The deferred stop/copy/restart policy and multi-volume Restic recovery are now tracked in #801, so their availability and recovery design stays separate when #767 closes this first-step issue.