Volumes
View MarkdownA Volume is named storage that outlives the work that uses it. Every change is saved as a numbered revision, so you can see what changed, mount an earlier revision read-only, and never lose files to a stopped machine. You pay for the bytes stored, after your org’s included 10 GB.
Create a Volume and upload files
Section titled “Create a Volume and upload files”apiVersion: nodus.dev/v1kind: Volumemetadata: name: ex-volumes-put-getspec: accessMode: ReadWriteOnce size: 1Gi source: {upload: {}}nodus apply -f volume.yaml # or: nodus create volume data --size 100Ginodus volume put ex-volumes-put-get ./data /data # uploads ./data and prints the new revisionnodus volume ls ex-volumes-put-get /datanodus volume get ex-volumes-put-get /data/hello.txt ./out/nodus volume put data ./archive.tar.gz /raw --extractnodus volume rm data /raw/old.csvnodus volume clear data # an empty revision; the Volume and its history stayUploads only send what changed: a second put of the same files moves almost nothing. An upload that started
from an older revision than the latest is refused with 409 Conflict, so two people uploading at once never
overwrite each other silently; run it again on top of the new revision.
put adds to what is there: a directory’s contents merge into the remote path, and a file lands at the remote
path, or inside it when the remote path is a directory or ends in /. rm and clear also commit new
revisions, so earlier revisions keep the removed files. get and ls read the latest revision, or the one
--revision <n> names; get … - prints a file to standard output, and existing local files are kept unless
--force. --extract expands a .zip, .tar, .tar.gz, .tgz or .tar.zst archive. It refuses an archive
whose paths or links lead outside the remote path, or that has more than 10,000 members.
Mount it in a Job
Section titled “Mount it in a Job”apiVersion: nodus.dev/v1kind: Jobmetadata: name: ex-volumes-put-getspec: image: nodus/python:3.12 volumes: - {volume: ex-volumes-put-get, mountPath: /mnt/vol, readOnly: true} command: [cat, /mnt/vol/data/hello.txt]accessMode |
Who can write | How changes are saved |
|---|---|---|
ReadWriteOnce (default) |
One attempt at a time | On exit and every commitInterval (default 5 minutes) |
ReadOnlyMany (default for imports) |
Nobody; any number of readers | Revisions come from imports and uploads |
ReadWriteMany |
Every worker | Each worker’s changes are published when it commits or exits; the last writer of a path wins |
A ReadWriteOnce Volume is held by one attempt at a time. Starting a second writer, or deleting the Volume while
it is held, fails with 409 VolumeBusy, which names the holder; mount it with readOnly: true to read alongside.
Functions and Agents with more than one worker need ReadOnlyMany or ReadWriteMany.
Mount an earlier revision with revision: <n> and readOnly: true. nodus get volume data shows the latest
REVISION, USED and the current HOLDER; GET …/volumes/{name}/revisions lists the kept revisions
(revisionHistoryLimit, default 10).
Import from elsewhere
Section titled “Import from elsewhere”Set exactly one source; the import runs once on Nodus, billed as CPU time, and produces revision 1:
spec: accessMode: ReadOnlyMany size: 200Gi maxCostUSD: "2.00" source: {huggingface: {repo: meta-llama/Llama-3.1-8B, revision: 0e9e39f249a16976918f6564b8830bc894c89659, secret: hf-token}}| Source | Fields |
|---|---|
huggingface |
repo, revision (a commit or tag), files globs, secret holding HF_TOKEN |
git |
repo, ref, lfs |
url |
an https:// url, sha256, extract: Auto unpacks .zip, .tar, .tar.gz, .tgz and .tar.zst |
s3 |
uri and an S3 Connection |
The Volume is Pending while it imports and Ready after. A failed import shows Failed with reason
ImportFailed and a message; fix the source or add credits, then run nodus request reimport volume/<name>.
In Python
Section titled “In Python”vol = nodus.Volume.from_name("data", create_if_missing=True)vol.put_file("./local.csv", "/train/local.csv")print(vol.listdir("/train"))