Skip to content

Support splitting container rootfs and SNAPSHOT_FIDELITY_ROOTFS on gVisor - #2673

Merged
Dmitry Berkovich (dberkov) merged 2 commits into
agent-substrate:mainfrom
nybidari:gvisor-nightly-split-checkpoint
Oct 17, 2026
Merged

Dmitry Berkovich (dberkov) merged 2 commits into
agent-substrate:mainfrom
nybidari:gvisor-nightly-split-checkpoint

Conversation

@nybidari

@nybidari nybidari commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

gVisor ActorTemplates can now set snapshotConfig.preferredFidelity: SNAPSHOT_FIDELITY_ROOTFS.
Pause and Suspend keep each container's rootfs writes and the DurableDir volumes, without process memory. Resume cold-boots with them back in place.

ateworker-gvisor saves container rootfs overlays and DurableDir volumes as two filesystem checkpoint bundles, rootfs/ and fs/:

  • ROOTFS checkpoints write both bundles with runsc fscheckpoint.
  • MEMORY checkpoints split both bundles out of the process checkpoint, so the rootfs is stored apart from the other state.
  • Restore passes --fs-restore-image-path for each bundle the requested fidelity uses. VOLUMES uses only fs/.
  • CreateActorTemplate no longer limits ROOTFS to sandboxClass: microvm, and the ROOTFS e2e cases now also run on gVisor.
  • Removes outdated text that limited gVisor templates to one DurableDir.

Breaking change

  • The default gVisor SandboxConfig moves to a newer runsc (v4). As with any gVisor version change, existing MEMORY and golden snapshots may not resume at full fidelity. Re-create golden snapshots after upgrading.
  • ateworker-gvisor now needs a runsc that supports multiple filesystem checkpoint bundles. A SandboxConfig pinned to an older runsc fails MEMORY checkpoints of actors that have a DurableDir.
  • New gVisor snapshots contain rootfs/ files, which older atelet and object-store-plugin builds reject. Upgrade atelet and the plugin before, or together with, ateworker-gvisor. Don't roll atelet back once new snapshots exist.

Fixes #2435. Completes the gVisor phase of #2447.

  • Unit tests pass (ateworker-gvisor, internal/resources, ateapi apivalidation)
  • gVisor e2e passes with the final nightly
  • Documentation updated

@nybidari
nybidari force-pushed the gvisor-nightly-split-checkpoint branch 2 times, most recently from 100133a to cc9d314 Compare October 14, 2026 20:20
@nybidari
nybidari force-pushed the gvisor-nightly-split-checkpoint branch from cc9d314 to b520933 Compare October 14, 2026 20:48
# ateom-gvisor uses to save and restore durable-dir volumes.
- name: v3
# TODO: move both architectures to the first gs://gvisor nightly that
# includes google/gvisor@<commit> (multi-bundle filesystem checkpoint).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing commit

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with the 10/17 gVisor release and removed TODO

Comment thread cmd/ateom-gvisor/fscheckpoint.go Outdated
if !errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf("while checking filesystem checkpoint manifest %q: %w", manifestPath, err)
}
if sub == resources.RootfsCheckpointSubdir && fidelity == ateompb.SnapshotFidelity_SNAPSHOT_FIDELITY_ROOTFS {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc comment says MEMORY treats rootfs/ as optional so snapshots taken before the split still restore. We don't keep old snapshot formats working pre-1.0, so let's drop that and require rootfs/ for MEMORY too. A new MEMORY snapshot that is missing it should fail here with a clear error.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the changes.

phaseTeardown = "teardown"
phaseCheckpoint = "checkpoint"
phaseDurableDir = "durable_dir"
phaseFSCheckpoint = "fs_checkpoint"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 nit 🟢 – VOLUMES and ROOTFS both run a single runsc fscheckpoint, but record it under durable_dir and fs_checkpoint respectively. One phase name would keep the same operation in one column; ate.snapshot.fidelity already tells the two apart.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread cmd/ateom-gvisor/fscheckpoint.go Outdated
// inside checkpoint.img.
// - Every fidelity uses `<checkpointDir>/fs` when
// `<checkpointDir>/fs/fscheckpoint.pb` exists.
func fsRestoreArgs(checkpointDir string, fidelity ateompb.SnapshotFidelity) ([]string, error) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 should-fix 🟡 – On rebase this collides with a change on main: after restore, dropActorCheckpointCacheAsync now runs runsc wait -fsrestore for fsRestoreContainers(containers), which lists only durable-dir owners, before it drops the page cache and removes the restore dir. With rootfs/ restored, every container has an entry in runsc's wait map, so that list under-waits for ROOTFS and MEMORY. Under VOLUMES, waiting on a container with no durable dir fails with no filesystems restored for container. The wait list has to follow the bundles this function selects.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebased and fixed.

// reference volumes the template declares, and a ROOTFS preferred fidelity
// needs a sandbox class that can capture rootfs changes without memory, which
// today is the micro-VM class alone.
// reference volumes the template declares.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 nit 🟢 – This hunk is already on main. The change that removed SandboxConfig from ActorTemplate dropped the ROOTFS-needs-microvm rule and its test with it, so this and the rootfs fidelity on microvm accepted case go away on rebase.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread demos/counter/README.md Outdated
snapshot of the volumes and each container's rootfs writes without guest
memory; this template keeps `MEMORY` because the in-RAM counter is the point of
the demo.
The micro-VM class also serves `SNAPSHOT_FIDELITY_ROOTFS`, a snapshot of the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could you please move this statement to general session, since this is available now for everyone.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread internal/proto/ateompb/ateom.proto Outdated
// The structure of the checkpoint should generally be treated as opaque. For
// gVisor, the checkpoint consists of a checkpoint.img file that contains the
// memory, sentry state, and filesystem deltas.
// gVisor, a MEMORY checkpoint is checkpoint.img and its page files (memory

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Do we actually need mention the gVisor in the API explicitly?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need, updated.

…isor

Split container rootfs overlays into the rootfs/ filesystem checkpoint
bundle alongside the fs/ durable-dir bundle, and enable
SNAPSHOT_FIDELITY_ROOTFS for gVisor ActorTemplates.

Move the default gVisor SandboxConfig to the 2026-10-17 nightly, the
first to include gVisor commit b79256080dec, which saves and restores
multiple filesystem checkpoint bundles.
…ed bundle

- MEMORY restores now require rootfs/, like ROOTFS. Snapshots from before
  the split are not kept restorable before 1.0, so a missing bundle fails
  with a clear error.
- runsc wait -fsrestore follows the bundles the restore selects: every
  container for ROOTFS and MEMORY, durable-dir mount owners for VOLUMES.
- VOLUMES and ROOTFS both record their runsc fscheckpoint as fs_checkpoint;
  ate.snapshot.fidelity tells them apart.
- The counter demo README describes ROOTFS in its intro, since it is no
  longer specific to one sandbox class.
@dberkov
Dmitry Berkovich (dberkov) added this pull request to the merge queue Oct 17, 2026
Merged via the queue into agent-substrate:main with commit b1e9ad1 Oct 17, 2026
15 checks passed
Dmitry Berkovich (dberkov) pushed a commit to dberkov/substrate that referenced this pull request Oct 19, 2026
…nt-substrate#2880)

Now that gVisor supports `SNAPSHOT_FIDELITY_ROOTFS` alongside micro-VM
(agent-substrate#2673), a snapshot's rootfs upper layer depends only on the container
image (`ActorTemplate`) and not on the worker's sandbox runtime version
or host CPU features.
- **`requiredSnapshotRuntime`**: Only impose a `RequiredRuntime`
placement constraint when restoring `SNAPSHOT_FIDELITY_MEMORY`
snapshots; `SNAPSHOT_FIDELITY_ROOTFS` and `SNAPSHOT_FIDELITY_VOLUMES`
snapshots can schedule onto any eligible worker of the same sandbox
class without runtime matching.
- **`ensureAteletRestored`**: When a durable `MEMORY` snapshot falls
back onto a runtime-incompatible worker, downgrade the restore fidelity
to `SNAPSHOT_FIDELITY_ROOTFS` (preserving both rootfs writes and durable
volumes) instead of `SNAPSHOT_FIDELITY_VOLUMES`. Snapshots whose
`ActorTemplate` was replaced continue to downgrade to
`SNAPSHOT_FIDELITY_VOLUMES`.
- **Tests & Docs**: Update `workflow_resume_test.go`,
`functionaltest/actor_test.go`, and `docs/api-guide.md` to reflect
`ROOTFS` fallback semantics.
Follow-up to agent-substrate#2673 and agent-substrate#2660.
<img width="1364" height="1688" alt="image"
src="https://github.com/user-attachments/assets/7a105b64-2c30-440f-8679-5afbeb591f7d"
/>



- [ ] Tests pass
- [ ] Appropriate changes to documentation are included in the PR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add gVisor support to separate rootfs snapshot from other durable directories.

4 participants