Skip to content

[feature request] Rename Dynamic Storage to On-Demand Mount #481

Description

@mowangdk

Summary

Rename all references to "Dynamic Storage" / "Dynamic Volumes Mount" to "On-Demand Mount" across CRD APIs,
environment variables, Go types, internal code, and documentation. The current "dynamic" naming conflicts with
Kubernetes' well-established concept of Dynamic Volume Provisioning
(where a StorageClass automatically provisions PVs), causing confusion for operators and contributors.

Motivation

The project's "dynamic storage" feature mounts pre-existing PersistentVolumes into running sandbox containers
at claim/clone time via CSI NodePublishVolume calls. This is fundamentally different from Kubernetes dynamic PVC
provisioning, which creates new PVs on demand via StorageClass provisioners. The naming overlap leads to:

  1. Operator confusion: Admins familiar with Kubernetes expect "dynamic" to mean StorageClass-driven provisioning.
  2. Onboarding friction: New contributors misunderstand the feature's scope.
  3. Documentation ambiguity: Explanations must repeatedly disclaim "not Kubernetes dynamic provisioning".

"On-Demand Mount" accurately describes the behavior: volumes are mounted on demand when a sandbox is claimed,
cloned, or resumed — not at pod creation time or via dynamic provisioning.

Goals

  • Rename all user-facing and internal identifiers from "dynamic" to "on-demand mount" terminology.
  • Maintain backward compatibility for the CRD API field (dynamicVolumesMount JSON tag) during a deprecation window.
  • Maintain backward compatibility for the environment variable (DYNAMIC_STORAGE_DRIVER_LIST) during a deprecation window.
  • Keep E2B extension metadata keys unchanged (they use csi prefix, not dynamic).

Non-Goals/Future Work

  • Changing the underlying CSI mount mechanism or architecture.
  • Renaming E2B API extension keys (e2b.kruise.io/csi-*) — these already use a neutral csi prefix.
  • Renaming the sandbox-runtime-storage CLI binary.

Proposal

Naming Convention

Layer Current Name New Name
CRD field (Go) DynamicVolumesMount OnDemandMounts
CRD field (JSON tag) dynamicVolumesMount onDemandMounts (new) + dynamicVolumesMount (deprecated alias)
Env var DYNAMIC_STORAGE_DRIVER_LIST ON_DEMAND_MOUNT_DRIVER_LIST
Go const ENV_DYNAMIC_STORAGE_DRIVER_LIST ENV_ON_DEMAND_MOUNT_DRIVER_LIST
Package path pkg/agent-runtime/storages/ No change (already neutral)
Go types StorageProvider, MountProvider No change (already neutral)
Config types CSIMountOptions, MountConfig No change (already neutral)
Internal comments "dynamic mount point", "dynamic CSI mounts" "on-demand mount point", "on-demand CSI mounts"

Changes by Layer

Layer 1: CRD API Type — api/v1alpha1/sandboxclaim_types.go:83-89

// Before
DynamicVolumesMount []CSIMountConfig `json:"dynamicVolumesMount" ...`

// After
OnDemandMounts []CSIMountConfig `json:"onDemandMounts" ...`

Backward compatibility: The old JSON tag dynamicVolumesMount must remain functional during the deprecation
window. Two approaches (choose one):

  • Option A — Dual-field with controller-level migration (Recommended): Add OnDemandMounts as the primary
    field. Keep DynamicVolumesMount as a deprecated field. The SandboxClaim controller normalizes the deprecated
    field into OnDemandMounts at the start of reconciliation and at the point where claim options are built.
    Note: There is no existing SandboxClaim mutating webhook (pkg/webhook/ only has webhooks for sandboxset,
    sandboxtemplate, sandboxupdateops, and pod), so controller-level migration avoids introducing new webhook
    infrastructure solely for a rename.

  • Option B — Custom JSON unmarshaling: Implement UnmarshalJSON on SandboxClaimSpec to accept both field
    names. Simpler but mixes serialization concerns into the API type.

Recommended: Option A.

// api/v1alpha1/sandboxclaim_types.go

type SandboxClaimSpec struct {
    // ...

    // OnDemandMounts specifies volumes to be mounted into the sandbox on demand
    // at claim time via CSI NodePublishVolume.
    // +optional
    // +patchMergeKey=mountPath
    // +patchStrategy=merge
    // +listType=map
    // +listMapKey=mountPath
    OnDemandMounts []CSIMountConfig `json:"onDemandMounts,omitempty" patchMergeKey:"mountPath" patchStrategy:"merge"`

    // DynamicVolumesMount is deprecated. Use OnDemandMounts instead.
    // If both are set, OnDemandMounts takes precedence.
    // +optional
    // Deprecated: Use OnDemandMounts instead. Will be removed in v1beta1.
    DynamicVolumesMount []CSIMountConfig `json:"dynamicVolumesMount,omitempty" patchMergeKey:"mountPath" patchStrategy:"merge"`
}

Layer 2: Controller-Level Migration — pkg/controller/sandboxclaim/core/common_control.go

There is no existing SandboxClaim mutating webhook. Migration is handled in the controller at the point where
claim options are built (the buildClaimOptions function), which is the single code path that reads the mount
config from the SandboxClaim spec:

// Normalize deprecated field into the new field.
// This runs before any business logic reads the mount config.
mounts := claim.Spec.OnDemandMounts
if len(mounts) == 0 && len(claim.Spec.DynamicVolumesMount) > 0 {
    mounts = claim.Spec.DynamicVolumesMount
}
if len(mounts) > 0 {
    // ... existing CSI mount option generation using `mounts` ...
}

This approach avoids introducing new webhook infrastructure solely for a rename. The deprecated field
is not mutated on the API object — it is simply read as a fallback. Both fields coexist in the CRD
schema, and users can use either until Phase 3.

Layer 3: Environment Variable — pkg/agent-runtime/common/types.go:21

// Before
ENV_DYNAMIC_STORAGE_DRIVER_LIST = "DYNAMIC_STORAGE_DRIVER_LIST"

// After
ENV_ON_DEMAND_MOUNT_DRIVER_LIST = "ON_DEMAND_MOUNT_DRIVER_LIST"

// Deprecated: Use ENV_ON_DEMAND_MOUNT_DRIVER_LIST instead.
ENV_DYNAMIC_STORAGE_DRIVER_LIST = "DYNAMIC_STORAGE_DRIVER_LIST"

Layer 4: Config Init — pkg/agent-runtime/storages/config.go:33-41

Read both env vars with the new one taking precedence:

func init() {
    driverListStr := os.Getenv(common.ENV_ON_DEMAND_MOUNT_DRIVER_LIST)
    if driverListStr == "" {
        driverListStr = os.Getenv(common.ENV_DYNAMIC_STORAGE_DRIVER_LIST)
    }
    if driverListStr == "" {
        return
    }
    driverList := strings.Split(driverListStr, ",")
    for _, driverName := range driverList {
        if driverName == "" {
            continue
        }
        initializeProviderFuncs = append(initializeProviderFuncs,
            func(sp *StorageProvider) {
                sp.RegisterProvider(driverName, &MountProvider{})
            })
    }
}

Layer 5: Controller Consumers — Update Field References

All consumers that read claim.Spec.DynamicVolumesMount must switch to claim.Spec.OnDemandMounts:

File Line Change
pkg/controller/sandboxclaim/core/common_control.go 373-393 claim.Spec.DynamicVolumesMountclaim.Spec.OnDemandMounts

Layer 6: Internal Comments

Update comment text only (no functional change):

File Line Current New
pkg/utils/runtime/csi.go 36 "creates a dynamic mount point" "creates an on-demand mount point"
pkg/sandbox-manager/infra/sandboxcr/sandbox.go 430 "creates a dynamic mount point" "creates an on-demand mount point"
pkg/controller/sandbox/core/interface.go 78 "runtime and dynamic CSI mounts" "runtime and on-demand CSI mounts"

Layer 7: CRD Manifest Regeneration

After modifying api/v1alpha1/sandboxclaim_types.go, run:

make generate manifests

This regenerates:

  • api/v1alpha1/zz_generated.deepcopy.go — adds DeepCopyInto for the new field
  • config/crd/bases/agents.kruise.io_sandboxclaims.yaml — adds the new JSON schema field

Layer 8: No Change Required (Already Neutral)

These identifiers use neutral naming (CSI, Mount, Storage) and require no rename:

Identifier Location Reason
CSIMountConfig api/v1alpha1/mount_types.go:19 Describes the config struct, not the feature
CSIMountHandler pkg/utils/csiutils/storages_provider.go:38 Describes the handler, not the feature
CSIMountOptions / MountConfig pkg/sandbox-manager/config/infra.go:38 Internal transport types
StorageProvider / MountProvider pkg/agent-runtime/storages/ Registry/provider pattern, not feature name
VolumeMountProvider / VolumeMountProviderRegistry pkg/agent-runtime/storages/interface.go Interface names, neutral
ProcessCSIMounts / CSIMount pkg/utils/runtime/csi.go Execution functions, neutral
ExtensionKeyClaimWithCSIMount* pkg/servers/e2b/models/extensions.go:51-55 E2B metadata keys use csi prefix
sandbox-runtime-storage pkg/utils/runtime/csi.go:34 CLI binary name, separate concern
storageRegistry field Multiple controllers/servers Local field name, describes purpose

Complete File Change List

Must change (functional):

# File What Changes
1 api/v1alpha1/sandboxclaim_types.go Add OnDemandMounts field, deprecate DynamicVolumesMount
2 pkg/agent-runtime/common/types.go Add ENV_ON_DEMAND_MOUNT_DRIVER_LIST, keep old const
3 pkg/agent-runtime/storages/config.go Read new env var first, fall back to old
4 pkg/controller/sandboxclaim/core/common_control.go DynamicVolumesMountOnDemandMounts with deprecated-field fallback (4 refs)

Must regenerate (automated):

# File How
6 api/v1alpha1/zz_generated.deepcopy.go make generate
7 config/crd/bases/agents.kruise.io_sandboxclaims.yaml make manifests

Should update (comments only):

# File Line
8 pkg/utils/runtime/csi.go 36
9 pkg/sandbox-manager/infra/sandboxcr/sandbox.go 430
10 pkg/controller/sandbox/core/interface.go 78

Must update (tests):

# File What Changes
11 pkg/controller/sandboxclaim/core/common_control_test.go DynamicVolumesMountOnDemandMounts, add deprecated-field fallback tests (~20 refs)
12 pkg/agent-runtime/storages/config_test.go Test both env var names

Risks and Mitigations

Risk Impact Mitigation
Existing SandboxClaim YAMLs use dynamicVolumesMount Users' manifests break Controller reads old field as fallback; both JSON tags accepted in CRD schema
Existing deployments set DYNAMIC_STORAGE_DRIVER_LIST env var Sandboxes lose CSI mount support on upgrade Init code reads both env vars; old var continues working indefinitely
Client SDK / generated clientset references old field SDK callers break client/ is generated — regenerate after API change. Both fields present during deprecation
CRD upgrade path Old CRD schema rejects new field CRD manifests are regenerated; standard kubectl apply adds the new field

Deprecation Timeline

Phase When Actions
Phase 1: Introduce v0.X (current) Add new names alongside old. Webhook migrates. Both env vars work.
Phase 2: Warn v0.X+1 Log deprecation warnings when old field/env var is used. Update all docs.
Phase 3: Remove v1beta1 Remove DynamicVolumesMount field and DYNAMIC_STORAGE_DRIVER_LIST const.

Upgrade Strategy

For CRD API: The controller handles migration transparently. Existing SandboxClaim resources with
dynamicVolumesMount continue to work without user action. The controller reads from the new field first,
falling back to the deprecated field when the new field is empty. No webhook infrastructure is required.

For environment variable: Operators using DYNAMIC_STORAGE_DRIVER_LIST need no immediate action. The init
code checks ON_DEMAND_MOUNT_DRIVER_LIST first, then falls back to the old name. Operators should update their
deployment manifests at their convenience before Phase 3.

For Go imports: Internal consumers (sandboxclaim controller, e2b server) are updated in the same PR.
External consumers (if any) can read from either field until Phase 3.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions