Shared volumes
OGO-managed sandboxes normally get one auto-provisioned PVC for the
/sandbox workspace directory (see Sandbox). This
guide covers mounting an additional, pre-existing PVC (or ConfigMap or
Secret) into a sandbox pod — for sharing a workspace across pipeline steps,
serving a read-only dataset to multiple sandboxes, or injecting
configuration that shouldn't live in the sandbox image.
Is this a CRD feature or a passthrough?
OGO's operator never mediates individual sandbox creation requests — it
only provisions the <gateway>-sandbox ServiceAccount, RBAC, and namespace
scaffolding that CI callers and the CLI use to talk to the gateway
directly. OGO's own code contains no Go types or proto definitions for the
agents.x-k8s.io Sandbox CRD's spec; a sandbox is created and owned
entirely by the OpenShell gateway binary in response to a CreateSandbox
call, independent of OGO's reconcile loop. So the existing-PVC-mount
capability upstream added (NVIDIA/OpenShell#2034)
is available to any OGO-managed gateway today, with no OGO CRD or
controller changes required — it's a matter of passing the right
request, not configuring the operator.
Confirm the mechanism yourself:
openshell sandbox create --help
Look for --driver-config-json, documented as an "Experimental
driver-keyed JSON object for driver-specific sandbox settings" whose
"[v]alidation behavior is not yet finalized." For the Kubernetes driver,
this accepts kubernetes.volumes (standard pod
Volume
entries) and kubernetes.containers.agent.volume_mounts (standard
VolumeMount
entries), per the upstream issue. Since the flag is marked experimental,
verify the exact JSON shape against your installed OpenShell CLI's own
--help output before relying on it in a pipeline — this guide documents
the field paths and OGO-specific deployment constraints, not a stable
upstream schema OGO controls.
Requires the gateway's OpenShell version to be >= v0.0.82 (the version
driver_config.kubernetes.volumes/volume_mounts first shipped in).
Check your gateway's pinned version:
oc get openshellgateway -o jsonpath='{.items[0].spec.imageTag}'
Usage
openshell sandbox create \
--driver-config-json '{
"kubernetes": {
"volumes": [
{"name": "shared", "persistent_volume_claim": {"claim_name": "my-existing-pvc"}}
],
"containers": {
"agent": {
"volume_mounts": [
{"name": "shared", "mount_path": "/data"}
]
}
}
}
}' \
-- ls /data
This is additive: the sandbox's own auto-provisioned workspace PVC still
gets mounted at /sandbox as usual. /data in this example is a second,
independent mount pointing at a PVC that already exists before the sandbox
was created.
Deployment constraints
Namespace alignment
The sandbox pod and the PVC must be in the same namespace — a Sandbox
spec references a PVC by name only, with no cross-namespace mount
mechanism. OGO's spec.sandbox.namespace (default: the gateway's own
namespace) controls where sandbox pods are created. If your workload that
needs to share a PVC with sandboxes runs in a different namespace than
spec.sandbox.namespace, either:
- Move the workload into the sandbox namespace, or
- Point
spec.sandbox.namespaceat the workload's namespace.
Cross-namespace PVC access isn't supported by the underlying mechanism, so there's no OGO-side workaround for this — the recommended approach is one gateway per team, with the sandbox namespace matching the team's workload namespace, rather than trying to share PVCs across namespace boundaries.
Authentication for non-interactive callers
A CI pipeline step or controller creating sandboxes non-interactively needs
a supported auth path — see
CI/CD Pipeline Access for the full setup (ServiceAccount +
OpenShellWorkspaceMember, or mTLS as a simpler alternative).
RWO scheduling
This is the constraint most likely to bite a shared-workspace CI/CD pattern, and it's a Kubernetes volume-binding property, not something OGO or OpenShell control:
- A
ReadWriteOnce(RWO) PVC can be mounted by multiple pods concurrently only if those pods land on the same node. AReadWriteOnceclaim restricts attachment to one node at a time — not one pod — but Kubernetes doesn't guarantee co-location unless you tell it to. - The common failure mode: a CI system (e.g. Tekton) holds a workspace PVC
mounted in its own pod for the full duration of a multi-step Task, and a
sandbox pod created mid-task also needs that PVC. If the scheduler places
the sandbox pod on a different node, it gets stuck
Pendingwith aFailedAttachVolume/multi-attach error — nothing about the sandbox itself is broken, the volume just can't attach to two nodes simultaneously. - Prefer a
ReadWriteMany(RWX) storage class for any PVC that will be concurrently mounted by a CI pod and a sandbox pod, if your cluster's storage provider offers one (e.g. NFS-backed, CephFS, or a cloud provider's RWX-capable class). - If only RWO storage is available, either avoid true concurrency (don't
create the sandbox until the CI pod has released the mount, and vice
versa — awkward with Tekton's per-Task pod-lifetime volume mounting), or
pin both the CI pod and the sandbox pod to the same node with matching
nodeSelector/affinity rules. Neither is as simple as just switching to RWX if you have the option.