Cordium documentation · Latest

Volumes

A Volume is a persistent storage device that belongs to a Space and that can be mounted by the Workspaces of that Space at arbitrary paths. Unlike a Workspace's own storage, a Volume has a lifecycle of its own: it outlives the Workspaces that mount it, it can be mounted by ephemeral Workspaces, and it is shared among the Members of its Space. Volumes are typically used for:

  • Build and dependency caches shared by ephemeral CI and AI agent Workspaces (e.g. Go, npm, pip, Cargo and Bazel caches).

  • Datasets, model weights and fixtures that are too large to download on every run.

  • Handing off artifacts between Workspaces (e.g. a build Workspace that produces binaries consumed by test Workspaces).

  • Persisting the state of ephemeral Workspaces (e.g. an AI agent's memory or a long-running job's checkpoints).

Creating Volumes

Volumes are created by the admins of their Space:

# A 50 GB Volume in the payments Space cordium create volume datasets.payments.cordium --size 50000 # A Volume that can be mounted by several Workspaces at the same time cordium create volume go-cache.payments.cordium --size 20000 --shared # A Volume in a specific Region cordium create volume models.research.cordium --size 200000 --region eu-west

You can list and inspect the Volumes of a Space as follows:

cordium get volume --space payments.cordium cordium get volume datasets.payments.cordium -o yaml
FieldDescription
spec.size.megabytesThe requested capacity. It defaults to 10 GB, must be at least 1000 MB, and is capped by the ClusterConfig. It can be grown later, but never shrunk.
spec.accessModeACCESS_MODE_EXCLUSIVE (the default) or ACCESS_MODE_SHARED. It is immutable.
status.stateSTATE_PENDING, STATE_READY or STATE_FAILED.
status.regionRefThe Region that hosts the Volume's storage.
status.capacityThe actual capacity of the provisioned storage, which can be larger than requested.
note

Volumes can already be mounted while they are STATE_PENDING, since most storage backends only provision the storage once the first Workspace that uses it is scheduled.

Access Modes

ACCESS_MODE_EXCLUSIVE Volumes can only be mounted by one active Workspace at a time. Starting a second Workspace that mounts the same Volume fails until the first one stops. They are backed by single-writer storage, which is what block storage backends (e.g. Longhorn, EBS, Persistent Disk or local volumes) provide. Use them for state that belongs to one Workspace at a time.

ACCESS_MODE_SHARED Volumes can be mounted by any number of Workspaces concurrently, even across nodes. They require the Cluster to be configured with a multi-writer filesystem storage backend (e.g. NFS, CephFS, EFS or Filestore). Otherwise, their storage cannot be provisioned and the Workspaces that mount them cannot start (read more here). Use them for shared caches and datasets.

Mounting Volumes

Volumes are mounted via the spec.runtime.volumeMounts field of a Workspace or a Template, by their name. A Workspace can mount up to 16 Volumes:

spec: runtime: volumeMounts: - volumeRef: name: go-cache mountPath: /cache/go - volumeRef: name: datasets mountPath: /data readOnly: true

Or via the --volume flag of cordium run and cordium create workspace in the NAME:MOUNT_PATH[:ro] format:

cordium run --template api-dev.payments.cordium \ --volume go-cache:/cache/go \ --volume datasets:/data:ro

Keep the following in mind:

  • The Volume must belong to the same Space as the Workspace, and all the Volumes mounted by a Workspace must be hosted in the same Region. The Workspace is automatically scheduled in that Region.

  • The mount path must be an absolute path that does not overlap with another mount. It cannot be /workspace itself nor a system directory (e.g. /, /etc, /usr, /var, /tmp, /proc, /dev, /run, /sys or the container storage directories), but it can be a path under /workspace or under the home directory. If the path already exists inside the Workspace, it must be an empty directory.

  • readOnly is set per mount, which means that the same Volume can be mounted read-write by one Workspace and read-only by others.

  • A newly created Volume is owned by the Workspace user of the first Workspace that mounts it read-write.

  • Mounts are applied on every start, which means that you can add or remove the mounts of a persistent Workspace by updating its spec.

Using Volumes as Caches

A common pattern is to point the package managers and build tools of ephemeral Workspaces to a shared Volume, so that every run starts with a warm cache. Here is an example of a Template for ephemeral Go CI runs:

spec: image: registry: url: golang:1.26-bookworm runtime: volumeMounts: - volumeRef: name: go-cache mountPath: /cache envVars: - key: GOMODCACHE value: /cache/mod - key: GOCACHE value: /cache/build autoStop: true tasks: - name: test type: ON_CREATE workingDir: /workspace/repo run: go test ./... onFailure: ON_FAILURE_ABORT

You can read more examples of using Volumes between Workspaces here.

Resizing and Deleting Volumes

A Volume can be grown via the UpdateVolume API or the web portal, provided that the storage backend supports volume expansion. A Volume can be deleted as follows:

cordium delete volume datasets.payments.cordium

A Volume cannot be deleted while it is referenced by a Workspace or a Template of its Space. Remove the mounts first.

note

Volumes are never included in WorkspaceSnapshots or Template pre-builds. A Workspace restored from a snapshot mounts the current content of its Volumes like any other Workspace.