Title: feat: allow opt-in async NFS mount options for volume mounts
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 1.6k
- Forks
- 438
- PR merge metrics
- No merged PRs in 30d
Description
上面## Summary
Currently, NFS volume mounts inside sandboxes always use sync,noac,lookupcache=none mount options. This is necessary for pause/resume correctness but imposes a significant performance penalty for users who do not use pause/resume (e.g., self-hosted deployments, short-lived sandboxes).
This issue proposes adding an opt-in asyncNFS option to volume mount configuration, allowing users to choose high-throughput async NFS mounts when pause/resume safety is not required.
Problem
The current NFS mount options are:
sync,rsize=1048576,wsize=1048576,mountproto=tcp,mountport=2049,proto=tcp,port=2049,nfsvers=3,noacl,noac,lookupcache=none
These options exist for good reasons in the pause/resume path:
sync: Everywrite()blocks until data reaches the NFS proxy server. Without this, async writeback pages in the kernel's NFS client cache would be lost when a sandbox is paused (Firecracker snapshot) or killed, sinceFIFREEZEonly flushes the local rootfs, not NFS client caches.noac: Disables attribute caching. After pause/resume, the NFS proxy connection is re-established with a new lifecycle ID. Stale cached attributes (file size, mtime) from before the pause would cause incorrect behavior.lookupcache=none: Disables directory entry caching, ensuring that after resume, the client does not serve stale directory lookups.
However, for workloads that never use pause/resume, these options cause unnecessary overhead:
Operationsync+noac``async+actimeo=3600Improvementwrite() latencyBlocks until server ACK (network RTT per write)Returns immediately, kernel batches writes10-100x50-200xstat() / lsGETATTR RPC every callCached for up to 1 hourgit clone (large repo)Bottlenecked by per-file sync writesBulk async writesSignificantly fasternpm install / pip installMany small file writes, each syncBatched async writesSignificantly fasterreaddir + stat stormEvery lookup hits serverCached locallyNear-instant
Proposed Solution
Add an optional asyncNFS boolean field to the VolumeMount schema:
envd.yaml - VolumeMount schema
VolumeMount:
properties:
nfs_target:
type: string
path:
type: string
async_nfs:
type: boolean
description: >
Use async NFS mount options for higher throughput.
Only safe when pause/resume is not used.
Defaults to false (sync mount for pause/resume safety).
When async_nfs: false (default) — current behavior, safe for pause/resume:
sync,noac,lookupcache=none,rsize=1048576,wsize=1048576,...
When async_nfs: true — optimized for throughput, no pause/resume:
rw,async,noatime,nodiratime,actimeo=3600,rsize=1048576,wsize=1048576,...
Implementation scope
The change is minimal and fully backward-compatible:
- envd/spec/envd.yaml — Add
async_nfsboolean toVolumeMountschema - envd/internal/api/init.go — Two sets of NFS options,
mountNFS()selects based on the flag orchestrator/pkg/sandbox/sandbox.go— AddAsyncNFStoVolumeMountConfigorchestrator/pkg/sandbox/envd.go— Pass the flag through inconvertMounts()- Regenerate api.gen.go / envd.gen.go
Safety
- Default is
sync— no behavior change for existing users - Opt-in only — users must explicitly set
async_nfs: true - The orchestrator could also automatically set this based on whether the sandbox template supports pause/resume, providing a zero-config optimization for non-pausable sandboxes
Use Cases
- Self-hosted deployments that don't use pause/resume and want maximum NFS throughput
- Build/CI sandboxes that are short-lived and never paused
- Data-intensive workloads (ML training data, large file processing) where sync write overhead is the bottleneck
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with envd/internal/api/init.go and inspect mountNFS(), then trace VolumeMount through envd/spec/envd.yaml, orchestrator/pkg/sandbox/sandbox.go, and orchestrator/pkg/sandbox/envd.go. Add the opt-in async_nfs path while preserving synchronous defaults, pass AsyncNFS through the conversion, and regenerate api.gen.go and envd.gen.go.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- infrastructure
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100