feat(kubernetes): support PVC subPath driver config#2034
Conversation
Signed-off-by: mjamiv <michael.commack@gmail.com>
|
Thanks for this — the caller-owned-PVC-by-
Happy to help validate — we're deploying this exact pattern and can share e2e findings. |
Signed-off-by: mjamiv <michael.commack@gmail.com>
|
Thanks for the test-scope review. I added positive I agree the missing-PVC and durability claims need cluster-level coverage: kubelet |
| WORKSPACE_VOLUME_NAME, | ||
| ]; | ||
|
|
||
| const KUBERNETES_DRIVER_PROTECTED_MOUNT_PATHS: &[&str] = &[ |
There was a problem hiding this comment.
Why are we redefining what should be shared across drivers (see driver_mounts::RESERVED_MOUNT_TARGETS)? Note that the openshell_core::driver_utils::SUPERVISOR_CONTAINER_* constants added to the list later would already be covered by /opt/openshell which is included in the shared list.
Review: PVC subPath driver configThanks for this — the direction is good and it correctly routes subpath/source/target validation through the shared Code reuse / overlap with other driversAll container drivers already converge on
Correctly kept driver-local (don't hoist): the reserved volume-name list (PVC names are K8s-only), the PVC config structs, and the SPIFFE runtime-conflict check.
Implementation issuesGate on these:
Design — worth discussing:
Minor:
Checked and not issues: the reserved volume-name list does currently cover all five managed volume names; protected-path coverage of managed mounts (TLS, sa-token, supervisor) is complete via the protected list + shared Net: approve the direction; I'd like 1–3 (and ideally reuse items 1–4) addressed before merge. |
elezar
left a comment
There was a problem hiding this comment.
Review: PVC subPath driver config
Thanks for this — the direction is good and it correctly routes subpath/source/target validation through the shared openshell_core::driver_mounts module. Two themes below: code reuse (so the K8s driver doesn't become a fourth divergent copy of mount logic) and implementation issues (a few I'd gate merge on).
Code reuse / overlap with other drivers
All container drivers already converge on openshell_core::driver_mounts (Docker lib.rs:1779-1909, Podman container.rs:546-688), so subpath rules, NUL/empty checks, .. rejection, and the /sandbox + reserved-target base list are already unified. This PR reuses most of that — good. Remaining duplication worth consolidating:
path_is_or_underis an exact copy of the private fn indriver_mounts.rs:99-104. Make the shared onepuband import it instead of re-declaring.default_true()is now defined a third time (already indocker/lib.rs:342andpodman/container.rs:136). Along with the#[serde(default = "default_true")] read_only: boolidiom, this belongs in the shared module.- Duplicate mount-target detection is identical in three places — Docker (
lib.rs:1857-1917), Podman (container.rs:625-681), and now here. A sharedvalidate_unique_mount_targets(&[...], driver_name)would collapse all three. - Protected-path list overlaps and risks drift.
KUBERNETES_DRIVER_PROTECTED_MOUNT_PATHSrepeats/etc/openshell,/etc/openshell-tls,/run/netns(already indriver_mounts::RESERVED_MOUNT_TARGETS) and redundantly listsSUPERVISOR_CONTAINER_DIR/SUPERVISOR_CONTAINER_BINARY, both already under/opt/openshellwhich the shared list covers. Sincevalidate_kubernetes_mount_pathcallsvalidate_container_mount_targetfirst, keep only the K8s-unique entries (/var/run/secrets/openshell,/spiffe-workload-api) locally and let the shared list cover the rest — otherwise the two lists will silently diverge. - Consider promoting the stricter path checks into the shared validator.
validate_kubernetes_mount_pathadds rejection of internal empty segments (/a//b),.segments, and surrounding whitespace — checksvalidate_container_mount_targetlacks today (Docker/Podman currently accept/a//b). If these are correctness improvements, hoist them so every driver benefits and the K8s wrapper shrinks to just the protected-list check.
Correctly kept driver-local (don't hoist): the reserved volume-name list (PVC names are K8s-only), the PVC config structs, and the SPIFFE runtime-conflict check.
Note for reviewers: subpath support is intentionally inconsistent across drivers — Docker supports it on volume mounts, Podman rejects it (
reject_subpath). This PR adding subpath for PVC mounts matches Docker; it's deliberate, not an oversight.
Implementation issues
Gate on these:
-
Validation is split across three sites with inconsistent handling of the same check.
validate_kubernetes_mount_pathis used invalidate()(returnsErr), inkubernetes_driver_volume_mount_to_k8s(.expect()— panics), and inhas_explicit_sandbox_data_mount(.ok()— silently ignores). In the normal flowcreate_sandboxvalidates before rendering, so the panic is currently unreachable — but this PR widens the panic surface, sincefrom_template()now fails on semantic checks (duplicate/reserved names, bad subpath, protected paths, read-only weakening), not just serde errors. Any future render path not preceded byvalidate_driver_config_for_sandboxwill panic the driver instead of returningInvalidArgument. Render functions should take an already-validated, normalized config rather than re-parsing and.expect()-ing. -
Re-validation at render exists only to recompute the normalized string.
kubernetes_driver_volume_mount_to_k8sre-runsvalidate_kubernetes_mount_path/validate_mount_subpathpurely to get the normalizedmountPath/subPath. Validate once, store the normalized values on the struct, render from those — removes the redundant work and the panic in (1). -
Reserved volume-name list duplicates pod-spec string literals.
KUBERNETES_DRIVER_RESERVED_VOLUME_NAMEShardcodes"openshell-client-tls"and"openshell-sa-token"; the pod spec hardcodes the same literals (driver.rs:1465,1478). They match today, but if either managed volume is renamed the guard silently stops matching and a user volume could collide. Extract both to named constants used in both places (the other three already use constants).
Design — worth discussing:
-
Any subpath mount under
/sandboxdisables all default workspace persistence.has_explicit_sandbox_data_mountflipsinject_workspaceoff for any mount at-or-under/sandbox, so the documented example (/sandbox/.openshell/workspace,/sandbox/.openshell/memory) makes/sandboxitself ephemeral image content while only the two leaf subpaths persist. Kubernetes supports nested volumeMounts, so disabling the whole workspace isn't strictly required — it's a coarse simplification that silently drops persistence for everything else under/sandbox. At minimum this needs a prominent warning in the docs/README; better, reconsider whether the default workspace should coexist with narrow user subpath mounts. -
Double read-only opt-in is easy to trip. Both the PVC volume and the mount default to
read_only: true, and the validator rejects a RW mount on a RO volume — so RW requiresread_only: falsein two places. Consider defaulting the mount'sread_onlyfrom the volume's value to halve the opt-in.
Minor:
validate_kubernetes_reference_nameand theclaim_namecheck don't enforce DNS-1123 label syntax, so invalid-but-printable names pass driver validation and fail later at the API server.validate_kubernetes_driver_runtime_mountsre-runsvalidate_kubernetes_mount_pathon every mount already validated byvalidate()(~3× per create) — folds away once (1)/(2) land.
Checked and not issues: the reserved volume-name list does currently cover all five managed volume names; protected-path coverage of managed mounts (TLS, sa-token, supervisor) is complete via the protected list + shared RESERVED_MOUNT_TARGETS; mount_path_conflicts_with_protected_path correctly also blocks mounting a parent of a reserved path.
Net: approve the direction; I'd like 1–3 (and ideally reuse items 1–4) addressed before merge.
Summary
Add Kubernetes driver-config support for mounting existing PVCs into the agent container with optional
sub_pathvalues. This gives deployments a narrow driver-owned storage topology for durable per-user PVC data without broad PodSpec overrides.Related Issue
Fixes #2033
Changes
driver_config.kubernetes.volumes[]for PVC-backed pod volumes.driver_config.kubernetes.containers.agent.volume_mounts[]for agent PVC mounts with optionalsub_path.read_only: falseis explicit.sub_pathvalues, and attempts to weaken read-only PVC volumes./sandboxworkspace PVC injection when an explicit Kubernetes driver-config mount targets a path below/sandbox/.Testing
mise run pre-commitpassesmise; after installing it,mise run pre-commitrefused to run until the repo config was trusted. I did not runmise trustbecause it persistently changes local trust settings.cargo fmt --all -- --checkcargo test -p openshell-driver-kubernetescargo clippy -p openshell-driver-kubernetes --all-targets -- -D warningsnpx --yes markdownlint-cli2@0.22.0 crates/openshell-driver-kubernetes/README.md docs/reference/sandbox-compute-drivers.mdxUV_CACHE_DIR=.cache/uv uv run python scripts/update_license_headers.py --checkChecklist