Skip to content

feat(backups): declare consistency guarantees and covered volumes for backup and restore #720

Open

Description

@Baylem

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

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

  1. ValgulNecron commented on Oct 20, 2026

    @ValgulNecron
    Collaborator

    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>-data claim (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, and Backup.spec.quiesce already 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:

    • A status condition on each Backup stating the consistency actually achieved (quiesced, unsupported/raw copy, crash-consistent snapshot), so an unsupported quiesce is visible instead of hidden in an annotation.
    • A covered-volume manifest recorded at capture time, listing which volumes were included and which were not.
    • An optional per-volume field in the module contract (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 stopped policy (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.

  2. Baylem commented on Oct 25, 2026

    @Baylem
    MemberAuthor

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions