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:
- Operator confusion: Admins familiar with Kubernetes expect "dynamic" to mean StorageClass-driven provisioning.
- Onboarding friction: New contributors misunderstand the feature's scope.
- 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.DynamicVolumesMount → claim.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:
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 |
DynamicVolumesMount → OnDemandMounts 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 |
DynamicVolumesMount → OnDemandMounts, 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.
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
NodePublishVolumecalls. This is fundamentally different from Kubernetes dynamic PVCprovisioning, which creates new PVs on demand via StorageClass provisioners. The naming overlap leads to:
"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
dynamicVolumesMountJSON tag) during a deprecation window.DYNAMIC_STORAGE_DRIVER_LIST) during a deprecation window.csiprefix, notdynamic).Non-Goals/Future Work
e2b.kruise.io/csi-*) — these already use a neutralcsiprefix.sandbox-runtime-storageCLI binary.Proposal
Naming Convention
DynamicVolumesMountOnDemandMountsdynamicVolumesMountonDemandMounts(new) +dynamicVolumesMount(deprecated alias)DYNAMIC_STORAGE_DRIVER_LISTON_DEMAND_MOUNT_DRIVER_LISTENV_DYNAMIC_STORAGE_DRIVER_LISTENV_ON_DEMAND_MOUNT_DRIVER_LISTpkg/agent-runtime/storages/StorageProvider,MountProviderCSIMountOptions,MountConfigChanges by Layer
Layer 1: CRD API Type —
api/v1alpha1/sandboxclaim_types.go:83-89Backward compatibility: The old JSON tag
dynamicVolumesMountmust remain functional during the deprecationwindow. Two approaches (choose one):
Option A — Dual-field with controller-level migration (Recommended): Add
OnDemandMountsas the primaryfield. Keep
DynamicVolumesMountas a deprecated field. The SandboxClaim controller normalizes the deprecatedfield into
OnDemandMountsat 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 forsandboxset,sandboxtemplate,sandboxupdateops, andpod), so controller-level migration avoids introducing new webhookinfrastructure solely for a rename.
Option B — Custom JSON unmarshaling: Implement
UnmarshalJSONonSandboxClaimSpecto accept both fieldnames. Simpler but mixes serialization concerns into the API type.
Recommended: Option A.
Layer 2: Controller-Level Migration —
pkg/controller/sandboxclaim/core/common_control.goThere is no existing SandboxClaim mutating webhook. Migration is handled in the controller at the point where
claim options are built (the
buildClaimOptionsfunction), which is the single code path that reads the mountconfig from the SandboxClaim spec:
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:21Layer 4: Config Init —
pkg/agent-runtime/storages/config.go:33-41Read both env vars with the new one taking precedence:
Layer 5: Controller Consumers — Update Field References
All consumers that read
claim.Spec.DynamicVolumesMountmust switch toclaim.Spec.OnDemandMounts:pkg/controller/sandboxclaim/core/common_control.goclaim.Spec.DynamicVolumesMount→claim.Spec.OnDemandMountsLayer 6: Internal Comments
Update comment text only (no functional change):
pkg/utils/runtime/csi.gopkg/sandbox-manager/infra/sandboxcr/sandbox.gopkg/controller/sandbox/core/interface.goLayer 7: CRD Manifest Regeneration
After modifying
api/v1alpha1/sandboxclaim_types.go, run:This regenerates:
api/v1alpha1/zz_generated.deepcopy.go— addsDeepCopyIntofor the new fieldconfig/crd/bases/agents.kruise.io_sandboxclaims.yaml— adds the new JSON schema fieldLayer 8: No Change Required (Already Neutral)
These identifiers use neutral naming (
CSI,Mount,Storage) and require no rename:CSIMountConfigapi/v1alpha1/mount_types.go:19CSIMountHandlerpkg/utils/csiutils/storages_provider.go:38CSIMountOptions/MountConfigpkg/sandbox-manager/config/infra.go:38StorageProvider/MountProviderpkg/agent-runtime/storages/VolumeMountProvider/VolumeMountProviderRegistrypkg/agent-runtime/storages/interface.goProcessCSIMounts/CSIMountpkg/utils/runtime/csi.goExtensionKeyClaimWithCSIMount*pkg/servers/e2b/models/extensions.go:51-55csiprefixsandbox-runtime-storagepkg/utils/runtime/csi.go:34storageRegistryfieldComplete File Change List
Must change (functional):
api/v1alpha1/sandboxclaim_types.goOnDemandMountsfield, deprecateDynamicVolumesMountpkg/agent-runtime/common/types.goENV_ON_DEMAND_MOUNT_DRIVER_LIST, keep old constpkg/agent-runtime/storages/config.gopkg/controller/sandboxclaim/core/common_control.goDynamicVolumesMount→OnDemandMountswith deprecated-field fallback (4 refs)Must regenerate (automated):
api/v1alpha1/zz_generated.deepcopy.gomake generateconfig/crd/bases/agents.kruise.io_sandboxclaims.yamlmake manifestsShould update (comments only):
pkg/utils/runtime/csi.gopkg/sandbox-manager/infra/sandboxcr/sandbox.gopkg/controller/sandbox/core/interface.goMust update (tests):
pkg/controller/sandboxclaim/core/common_control_test.goDynamicVolumesMount→OnDemandMounts, add deprecated-field fallback tests (~20 refs)pkg/agent-runtime/storages/config_test.goRisks and Mitigations
dynamicVolumesMountDYNAMIC_STORAGE_DRIVER_LISTenv varclient/is generated — regenerate after API change. Both fields present during deprecationkubectl applyadds the new fieldDeprecation Timeline
DynamicVolumesMountfield andDYNAMIC_STORAGE_DRIVER_LISTconst.Upgrade Strategy
For CRD API: The controller handles migration transparently. Existing SandboxClaim resources with
dynamicVolumesMountcontinue 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_LISTneed no immediate action. The initcode checks
ON_DEMAND_MOUNT_DRIVER_LISTfirst, then falls back to the old name. Operators should update theirdeployment 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.