feat(dataset-mount): drive dataset mounts from the platform#6867
Conversation
Perform the FUSE mount for dataset repositories outside the (unprivileged) computing-unit pod. A per-node privileged `texera-mounter` DaemonSet runs GeeseFS on the pod's behalf and the read-only mount is exposed back into the pod via mount propagation, scoped to that computing unit. A JWT-authenticated S3 proxy in file-service fronts the LakeFS S3 gateway: it verifies the pod's JWT, checks the user's read access, and re-signs to LakeFS with credentials held only server-side, so no global credential ever enters the pod. - `texera-mounter` DaemonSet: mounter.py (+ tests), dockerfile, helm daemonset/rbac/values. - Unprivileged CU pod + mount-propagation wiring (KubernetesClient) and mounter config/env. - File-service JWT S3 proxy (S3ProxyServlet). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H27sHgS29u2JcLYPPR6Hdx
Build on the mount infrastructure to let the platform and users mount datasets and use them in Python UDFs. - Engine mount client: DatasetMountManager asks the node mounter to mount a dataset for the computing unit; the locator flows through PhysicalOp and WorkerConfig, and the resolved local path is handed to the Python worker. - Per-computing-unit mount API: mount / list / unmount datasets on a CU (ComputingUnitManagingResource + MounterClient), FileResolver resolving dataset paths both ways. - "Mount datasets into computing unit" UI. - Python UDF dataset-variable bindings: bind each mounted dataset to a variable holding its local path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H27sHgS29u2JcLYPPR6Hdx
Automated Reviewer SuggestionsBased on the
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #6867 +/- ##
============================================
- Coverage 77.30% 76.92% -0.39%
+ Complexity 3524 3522 -2
============================================
Files 1161 1165 +4
Lines 45922 46219 +297
Branches 5101 5137 +36
============================================
+ Hits 35501 35552 +51
- Misses 8840 9077 +237
- Partials 1581 1590 +9
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| 🔴 | bs=10 sw=10 sl=64 | 387 | 0.236 | 25,748/29,557/29,557 us | 🟢 -29.7% / 🔴 +100.9% |
| 🔴 | bs=100 sw=10 sl=64 | 789 | 0.482 | 126,942/147,000/147,000 us | 🟢 -11.0% / 🔴 +34.7% |
| ⚪ | bs=1000 sw=10 sl=64 | 911 | 0.556 | 1,099,075/1,138,991/1,138,991 us | ⚪ within ±5% / 🔴 +9.6% |
Baseline details
Latest main f02dd2f from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 387 tuples/sec | 371 tuples/sec | 754.55 tuples/sec | +4.3% | -48.7% |
| bs=10 sw=10 sl=64 | MB/s | 0.236 MB/s | 0.226 MB/s | 0.461 MB/s | +4.4% | -48.8% |
| bs=10 sw=10 sl=64 | p50 | 25,748 us | 23,025 us | 12,816 us | +11.8% | +100.9% |
| bs=10 sw=10 sl=64 | p95 | 29,557 us | 42,018 us | 16,594 us | -29.7% | +78.1% |
| bs=10 sw=10 sl=64 | p99 | 29,557 us | 42,018 us | 19,806 us | -29.7% | +49.2% |
| bs=100 sw=10 sl=64 | throughput | 789 tuples/sec | 806 tuples/sec | 969.38 tuples/sec | -2.1% | -18.6% |
| bs=100 sw=10 sl=64 | MB/s | 0.482 MB/s | 0.492 MB/s | 0.592 MB/s | -2.0% | -18.5% |
| bs=100 sw=10 sl=64 | p50 | 126,942 us | 117,384 us | 103,584 us | +8.1% | +22.5% |
| bs=100 sw=10 sl=64 | p95 | 147,000 us | 165,173 us | 109,097 us | -11.0% | +34.7% |
| bs=100 sw=10 sl=64 | p99 | 147,000 us | 165,173 us | 117,304 us | -11.0% | +25.3% |
| bs=1000 sw=10 sl=64 | throughput | 911 tuples/sec | 909 tuples/sec | 1,004 tuples/sec | +0.2% | -9.2% |
| bs=1000 sw=10 sl=64 | MB/s | 0.556 MB/s | 0.555 MB/s | 0.613 MB/s | +0.2% | -9.2% |
| bs=1000 sw=10 sl=64 | p50 | 1,099,075 us | 1,099,493 us | 1,002,357 us | -0.0% | +9.6% |
| bs=1000 sw=10 sl=64 | p95 | 1,138,991 us | 1,159,845 us | 1,046,463 us | -1.8% | +8.8% |
| bs=1000 sw=10 sl=64 | p99 | 1,138,991 us | 1,159,845 us | 1,073,661 us | -1.8% | +6.1% |
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,517.27,200,128000,387,0.236,25747.79,29556.60,29556.60
1,100,10,64,20,2535.16,2000,1280000,789,0.482,126941.56,146999.69,146999.69
2,1000,10,64,20,21953.36,20000,12800000,911,0.556,1099074.85,1138990.92,1138990.92Add coverage for the pure-logic paths of the platform integration: MounterClient (against a stub mounter HTTP server), DatasetMountManager locator/identity validation, the Python UDF datasetVariables validation, DatasetVariableMapping, and the executor-manager MOUNTED_DATASETS variable injection. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H27sHgS29u2JcLYPPR6Hdx
What changes were proposed in this PR?
Build on the mount infrastructure (#6862) to let the platform and users mount datasets and use them in Python UDFs.
DatasetMountManagerasks the node mounter to mount a dataset for the computing unit; the locator flows throughPhysicalOp/WorkerConfigto the Python worker, which exposes the resolved local path.GET/POST/DELETE /computing-unit/{cuid}/mounts(ComputingUnitManagingResource+MounterClient), a stateless proxy to that CU's node mounter;FileResolverresolves dataset paths both ways.open(f"{A}/file.csv").Any related issues, documentation, discussions?
Closes #6863 · part of #6606. Stacks on #6862 (mount infrastructure); this PR's diff becomes clean once #6862 merges.
How was this PR tested?
sbt WorkflowOperator/WorkflowExecutionService/ComputingUnitManagingService/FileService compile+ production frontend build green.MounterClientSpec(mount / list / unmount + error handling against a stub mounter HTTP server),DatasetMountManagerSpec(locator + identity validation),PythonUDFOpDescV2Spec(dataset-variable validation),DatasetVariableMappingSpec,PythonWorkflowWorkerStartupConfigSpec,test_run_python_worker.py, andtest_executor_manager.py(theMOUNTED_DATASETSvariable injection).torch.loadwith bit-exact output (model_output_sum == expected_sum); the mount API's mount → list → unmount cycle was exercised directly.Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Opus 4.8