Skip to content

[Feature] External volume mounts #232

Description

@msau42

Continuing the discussion in #119 (comment) and #220, let's start discussing the use cases and requirements for external volume mounts.

Use Cases

One use case I see discussed in the above issues is the need for each actor to have their own workspace to store data. Rootfs or working dir is insufficient because:

  • At larger capacities, there is a performance penalty of checkpointing local directories every time an actor is paused/suspended
  • Actor requires higher persistence guarantees with every IO rather than at the pause/suspend timeframe.

Open questions

  • Do volumes need to be sharable across multiple actors? If so, as read-only or writeable?

Proposal

Here's my initial thoughts on external volume semantics we can add to substrate.

Lifecycle

External volumes are an independent filesystem mount that follows the Actor lifecycle. A unique volume will be created per actor. Once a volume is created, it is persisted across the lifecycle of the actor. It is deleted when the actor is deleted.

If we support actor updates in the future, the volume will persist across updates. A volume can be added/removed across updates, but an existing volume cannot be mutated (for now). When a volume is deleted from the template, the underlying volume is also deleted after the rollout has completed.

Data Persistence Semantics

External volume mounts are expected to provide filesystem consistency semantics. Writes are persisted when flushed to the backing store. This is different than rootfs semantics where data is only guaranteed to be persisted when the actor is paused/suspended.

When an actor is paused/suspended, we do not take a snapshot of the volume mount (at least in the initial phase). We just unmount the volume and remount it when the actor is resumed. This implies that on resumption, the actor will get the latest volume state, regardless of if the actor gracefully completed its previous task or it crashed prematurely. The actor has to be able to handle the potential difference between its memory state and filesystem state.

In a future milestone, we can explore adding external volume snapshot support on actor suspension, and the ability to create actor volumes from a given volume snapshot.

Storage Backends

The storage backend has to support the following functionality at the required performance / scale:

  • Create/delete volumes
  • Attach/detach volumes to nodes
  • Mount/unmount volumes to nodes
  • Security/isolation of volume mounts
  • (Future) snapshot of volumes and clone from snapshot

NFS appears to be a commonly requested storage integration for this use case, however, while the file protocol is standard, the control plane APIs are typically vendor-specific. Rather than add a hard-dependency on NFS in substrate, I propose that we focus on supporting Container Storage Interface (CSI), which is well-defined and supported in the Kubernetes ecosystem.

API

kind: ActorTemplate
metadata:
  name: my-agent-template
spec: 
  ...
  containers:
  - image: my-agent-image:v1.2.3
    volumeMounts:
    - name: vol1
      mountPath: /my-data
  volumes:
  - name: vol1
    externalVolumeTemplate:
      capacity: 5Gi
      storageClassName: storage-pool1

Activity

  1. msau42 commented on Jun 12, 2026

    @msau42
    CollaboratorAuthor

    chenggui53 (@chenggui53) would love to hear more about your use case and if this proposal could address it.

  2. chenggui53 commented on Jun 15, 2026

    @chenggui53

    chenggui53 (@chenggui53) would love to hear more about your use case and if this proposal could address it.

    Michelle Au (@msau42) Thanks for your support on this problem.

    In our primary scenario, we need to maintain many agent instances (e.g., OpenClaw/Hermes) within a substrate actor. Each agent instance must persist its own data when the instance is paused, or when its node crashes – basically any fault that could cause in-memory data loss.

    Therefore, I think a persistent volume with the same lifecycle as the actor could solve part of our problem.

    As an open question: sometimes we also need a volume that can be shared among actors within a certain scope (e.g., a namespace). Such a shared volume could hold read‑only data maintained by an admin.

    So I’d like to ask: is it possible to provide both actor‑lifecycle volumes and shared volume mounts for actors?

  3. EItanya commented on Jun 15, 2026

    @EItanya
    Collaborator

    So I’d like to ask: is it possible to provide both actor‑lifecycle volumes and shared volume mounts for actors?

    I definitely think we need both of these.

    Do volumes need to be sharable across multiple actors? If so, as read-only or writeable?

    Shareable, definitely. Writable gets potentially difficult 😆. I think it could offer some powerful sharing potential, but would need to be used with caution.

  4. chenggui53 commented on Jun 16, 2026

    @chenggui53

    Shareable, definitely. Writable gets potentially difficult 😆. I think it could offer some powerful sharing potential, but would need to be used with caution.

    Maybe use it just like pvc for a pod.

  5. MushuEE commented on Jul 8, 2026

    @MushuEE
    Collaborator

    Do volumes need to be sharable across multiple actors?

    +1 to shared. CUJ: I am running GasTown with multiple "Pole Cats" all operating on the same shared context they write and share scripts, findings, etc to a mounted volume. Managing an independent volume lifecycle will get complex I imagine and if Actors are scheduled in a way that lands them into the same node as other Actors, cross-region etc. I am unsure if they will be able to share volumes across networks.

  6. msau42 commented on Jul 24, 2026

    @msau42
    CollaboratorAuthor

    Initial PR to add per-actor volume API and lifecycle hooks is here: #405.

    It's only useable in a test/dev purpose right now, we're actively working on adding CSI support in parallel.

    Here are the followup items from the initial PR reviews for tracking:

    Handled by #527:

    Handled by #678

    Discussing as part of #643:

    Open items:

  7. mowangdk commented on Aug 18, 2026

    @mowangdk
    Contributor

    Hey team — I'm the maintainer of Alibaba Cloud's CSI driver. I have few concern that ties this whole approach together, and I'd love to hear how you're thinking about it.

    1. Performance points away from virtio-fs
      Routing every CSI volume through guest → virtio-fs → vhost-user → virtiofsd → host bind-mount → backend adds a FUSE/vhost-user hop plus cache-revalidation on each IO — versus just handing the guest a block device.
    1. Reusing the plugin + virtio-fs at the node level exposes every mount on the node
      Running a single instance of the CSI plugin/virtiofsd per node exposes all tenant mounts in a shared tree under one worker identity.
      Since all volumes share the same host FS namespace, isolation relies solely on directory paths and file permissions. A compromised worker or an actor with elevated privileges could traverse the tree to access other tenants' volumes, violating multi-tenant isolation guarantees.

    Questions

    1. Deliberate or interim? Is virtio-fs a deliberate choice to keep mounts centralized/manageable at the cost of IO — or a "move fast, revisit later" step? If the latter, is virtio-blk / block passthrough still on the roadmap?
    2. Node-level isolation? Once all mountpoints live on the node behind a single shared plugin/virtio-fs, what keeps one tenant's volume from being reachable by another?
  8. added a commit that references this issue on Aug 19, 2026
    9c62dd9
  9. BenTheElder commented on Aug 20, 2026

    @BenTheElder
    Collaborator

    Deliberate or interim? Is virtio-fs a deliberate choice to keep mounts centralized/manageable at the cost of IO — or a "move fast, revisit later" step? If the latter, is virtio-blk / block passthrough still on the roadmap?

    Move fast. Also, FWIW virtio-blk passthrough seemed to have serious issues in developer environments (limactl / mac / kind), which is a key concern for us, but not more important than performance.

    already recommended virtio-blk for uVM writable storage for exactly these reasons (handling unlinked files smoothly; caches being in-memory).
    So the perf-optimal direction seems to point away from virtio-fs.

    That comment is stale, it didn't work well for that purpose, provisioning the block devices is slow and it wasn't really any more reliable. Worth revisiting.

    Node-level isolation? Once all mountpoints live on the node behind a single shared plugin/virtio-fs, what keeps one tenant's volume from being reachable by another?

    There's a virtiofs per actor, not per node.

    Since all volumes share the same host FS namespace, isolation relies solely on directory paths and file permissions. A compromised worker or an actor with elevated privileges could traverse the tree to access other tenants' volumes, violating multi-tenant isolation guarantees.

    We are only running hardened sandboxes like gVisor and uVM, an escape of those is pretty bad for multiple reasons currently, I don't think this is top of the list.

  10. BenTheElder commented on Aug 20, 2026

    @BenTheElder
    Collaborator

    In general I would describe the uVM implementation as "proof of concept". We started with gVisor, it's a lot more mature at the moment.

  11. mowangdk commented on Aug 21, 2026

    @mowangdk
    Contributor

    Deliberate or interim? Is virtio-fs a deliberate choice to keep mounts centralized/manageable at the cost of IO — or a "move fast, revisit later" step? If the latter, is virtio-blk / block passthrough still on the roadmap?

    Move fast. Also, FWIW virtio-blk passthrough seemed to have serious issues in developer environments (limactl / mac / kind), which is a key concern for us, but not more important than performance.

    already recommended virtio-blk for uVM writable storage for exactly these reasons (handling unlinked files smoothly; caches being in-memory).
    So the perf-optimal direction seems to point away from virtio-fs.

    That comment is stale, it didn't work well for that purpose, provisioning the block devices is slow and it wasn't really any more reliable. Worth revisiting.

    Node-level isolation? Once all mountpoints live on the node behind a single shared plugin/virtio-fs, what keeps one tenant's volume from being reachable by another?

    There's a virtiofs per actor, not per node.

    Since all volumes share the same host FS namespace, isolation relies solely on directory paths and file permissions. A compromised worker or an actor with elevated privileges could traverse the tree to access other tenants' volumes, violating multi-tenant isolation guarantees.

    We are only running hardened sandboxes like gVisor and uVM, an escape of those is pretty bad for multiple reasons currently, I don't think this is top of the list.

    Gotcha, Thanks for following up~

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

Metadata

Metadata

Labels

area/storagekind/featureAn enhancement / feature request or implementationprio/P1Important but not critical

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions