Skip to content

feat(k8s): support configuring storageClassName for the default workspace PVC #2442

Description

@loveRhythm1990

Problem Statement

The Kubernetes compute driver creates a default /sandbox workspace PVC for every sandbox pod (default_workspace_volume_claim_templates() in crates/openshell-driver-kubernetes/src/driver.rs, ~line 2158). The generated PVC spec only sets accessModes and resources.requests.storage — it never sets storageClassName. KubernetesComputeConfig (crates/openshell-driver-kubernetes/src/config.rs, ~line 269) only exposes workspace_default_storage_size; there is no storage-class field anywhere in the config struct, main.rs, or the Helm chart.

In clusters that have multiple StorageClass objects and no cluster-wide default StorageClass (a supported, common configuration), the generated PVC has an empty storageClassName. Kubernetes cannot bind or dynamically provision such a PVC, so it stays Pending indefinitely and sandbox creation fails outright. This is not a hypothetical edge case — we run clusters with multiple StorageClasses and intentionally no default, so this is a functional blocker for us today, not a nice-to-have.

Proposed Design

Mirror the existing workspace_default_storage_size pattern end-to-end so behavior stays backward compatible for clusters that do have a working default StorageClass:

  • Add workspace_storage_class: String to KubernetesComputeConfig (config.rs). Default is an empty string, meaning "omit storageClassName" — identical to current behavior.
  • Thread the value through SandboxPodParams in driver.rs and into default_workspace_volume_claim_templates(), setting storageClassName in the generated PVC spec only when the value is non-empty.
  • Add an environment variable (e.g. OPENSHELL_K8S_WORKSPACE_STORAGE_CLASS) read in main.rs, analogous to the existing OPENSHELL_K8S_WORKSPACE_DEFAULT_STORAGE_SIZE.
  • Wire the new setting through the Helm chart (deploy/helm/openshell/templates/gateway-config.yaml and values.yaml) as server.workspaceStorageClass, following the same pattern as server.workspaceDefaultStorageSize.
  • Update docs/reference/gateway-config.mdx and docs/reference/sandbox-compute-drivers.mdx to document the new field.

This keeps the setting at the same granularity as workspace_default_storage_size — a driver-level default applied to every sandbox's workspace PVC, not a per-sandbox override.

Alternatives Considered

  • Reference a pre-created PVC via driver_config.kubernetes volumes (the mechanism added in feat(kubernetes): support PVC subPath mounts via driver_config #2033): this lets an operator point a sandbox at an existing PVC with persistent_volume_claim.claim_name. It works for a single shared/static PVC but does not support per-sandbox, dynamically-provisioned PVCs on a specific StorageClass, so it isn't equivalent to configuring the default workspace PVC's storage class.
  • Rely on a cluster-level default StorageClass: this is the current implicit behavior, but it doesn't work for clusters that intentionally have no default StorageClass, which is our actual environment.

Agent Investigation

Investigated via direct code reading (not the create-spike skill): crates/openshell-driver-kubernetes/src/driver.rs (default_workspace_volume_claim_templates, SandboxPodParams), crates/openshell-driver-kubernetes/src/config.rs (KubernetesComputeConfig), crates/openshell-driver-kubernetes/src/main.rs (env var wiring), and deploy/helm/openshell/templates/gateway-config.yaml. Confirmed no storageClassName / storage-class configuration exists anywhere in this path today.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions