Add bnd section to Truss config - #2624
Conversation
|
|
There was a problem hiding this comment.
Pull request overview
Adds first-class volumes support to TrussConfig, including typed parsing/validation for BDN volume mounts and per-namespace access capabilities, and updates the generated JSON schema and tests accordingly.
Changes:
- Introduces
VolumeMount,Volumes, andVolumeAccessModemodels and wiresvolumesintoTrussConfig. - Extends
config.schema.jsonwith the newvolumesdefinitions and top-level property. - Adds YAML parsing + round-trip serialization tests and validation coverage for mounts/access.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| truss/base/truss_config.py | Adds volumes models, validation, and a new TrussConfig.volumes field. |
| truss/config.schema.json | Adds schema defs for volumes-related types and exposes volumes on the root schema. |
| truss/tests/test_config.py | Adds YAML parsing/round-trip and validation tests for the new volumes config. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| class VolumeAccessMode(str, enum.Enum): | ||
| """Permissions granted to a model for a BDN volume namespace.""" | ||
|
|
||
| PULL = "pull" |
There was a problem hiding this comment.
@stevvooe @kofmangregory there was a unmatched description about the access mode requirement [read, publish] vs [pull, push, tag, etc], i am staying consistent with the bdn scope here? I am also wondering do we have any plan to change the capbility, if yes, it might be easier to just accept arbitrary str instead of an enum?
| ) | ||
| access: dict[str, list[VolumeAccessMode]] = pydantic.Field( | ||
| default_factory=dict, | ||
| description="Namespace names mapped to BDN volume operation scopes.", |
There was a problem hiding this comment.
What is a namespace? I can't find this in any docs, API, etc but I may be missing it
There was a problem hiding this comment.
added description
| return str(mount_path) | ||
|
|
||
|
|
||
| class VolumeAccessMode(str, enum.Enum): |
There was a problem hiding this comment.
Can you describe these a bit better? I'm familiar w/ fs mount options, but not familiar with pull, push, tag, etc.
There was a problem hiding this comment.
I added more description about what are the namespaces, volume and tags in the comments. we currently don't have any public facing doc description yet. please help take a look and see if it make sense
76a77e0 to
0306876
Compare
| These are registry permissions, not filesystem mount options: they govern | ||
| what the deployment may ask the BDN volume service to do, and mirror the |
There was a problem hiding this comment.
they govern what the deployment may ask the BDN volume service to do
I am still not following exactly. How does the user's deployment ask the the BDN volume service to do things? Say I have a deployment, can you give be an example of how I can leverage "push" or "tag"? (pardon my ignorance)
There was a problem hiding this comment.
those are volume operations performed during the operation of a deployment, as far as i know, there are two ways that an volume operation can be performed:
- chowder agent, it lives on the deployment node, and knows the volume protocol and can talk to bdn sevrvice
- cannery cli if installed, can be used to talk to bdn service with valid token
cc @stevvooe @kofmangregory please correct me if I am wrong
There was a problem hiding this comment.
Hrmm, I may not understand in enough detail, but I would expect what you can/can't do to a volume is a product of restrictions of auth/client and not something about a model deployment. I assume whatever you can do to a volume in container you can do out of container right? So do we really need in container specific approach here?
There was a problem hiding this comment.
This allows the deployment itself to push/pull volumes at runtime. They can be hotloaded through a local pod API and mounted to the local filesystem or pushed from local data.
There was a problem hiding this comment.
I guess I don't understand exactly, why wouldn't they use the same tools in-container runtime as they might out of container? What does it look like to push a volume at runtime from my container? Not the Baseten CLI they may be familiar with? I can understand it may seem convenient to say "if it came from internal IP, apply different auth", but the concern is that they'd still have to go back to the CLI to do lots and lots of other stuff (e.g. list volumes maybe?), and the other concern is that our permission model for accessing this information should be consistent no matter caller location (especially as we add advanced auth things).
Having said that, technically no strong objection for a just-for-some-calls-and-just-for-in-container different auth approach than otherwise. It can save them from providing auth themselves (which they do have to do for other Baseten API usage from inside container) and maybe there are optimized network routes if a different tool is used.
| source: Annotated[str, pydantic.StringConstraints(min_length=1)] = pydantic.Field( | ||
| ..., | ||
| description="Volume to mount. Either a BDN reference (bdn://weights/llama-8b:prod) " | ||
| "or an external URI using hf://, s3://, gs://, azure://, r2://, cw://, or https://.", | ||
| ) | ||
| dest: Optional[str] = pydantic.Field( | ||
| default=None, | ||
| description="BDN volume the external source is ingested into, as " | ||
| "bdn://namespace/volume[:tag]. Required for external sources, and not " | ||
| "permitted when source is already a bdn:// reference.", | ||
| ) |
There was a problem hiding this comment.
It looks like this changed a bit since I last read. So does this concept of "external source" effectively amount to changing truss push to be server-side truss volume push + truss push? And we're sure we want to combine those concepts? What is the benefit to me as a user being forced to provide this destination if I just want my S3 bucket mounted? I may never use this destination or even care it is BDN backed correct?
Finally, if I did want to push an s3:// source to a bdn:// destination not-specific to this one model (so I could use it across models) could I do so leveraging whatever server-side mechanisms this is going to leverage? Or must I make a fake Truss model and push it to do this data transfer?
There was a problem hiding this comment.
sorry, that is out dated. there is a discussion going on to discuss how to expose the support of remote source to customer.
One approach is to introduce a truss volume command to also build a volume out of remote source first, and then use bdn volume in the config. which i think would provide the capability you mentioned that a user just want to push the remote source to a bdn volume and not associated with any model.
For now, i removed the capability, and will handle it later once we are aligned on the support
345fc85 to
27fda6d
Compare
| mounts: list[VolumeMount] = pydantic.Field( | ||
| default_factory=list, | ||
| description="Existing BDN volumes to mount when the model starts.", | ||
| ) | ||
| hotload: dict[str, list[HotloadAccessScope]] = pydantic.Field( | ||
| default_factory=dict, | ||
| description="BDN namespaces mapped to operations available through hot load.", | ||
| ) |
There was a problem hiding this comment.
Did something change where these are no longer under volumes? If this new "hotload" concept specific to volumes, would recommend both it and mounts is under a volumes section so as not to pretend "hotload" is something general (we do have a concept of "hot reload" on models).
There was a problem hiding this comment.
yes, we discussed this part yesterday, and decided to update access -> hotload to indicate clearly those are the namespaces and scopes that can be accessed for hotload. I think that is a new concept, in short refers operations performed by the deployment, we might have to work on the documentation. i also updated the description little bit, hope it is more clear
There was a problem hiding this comment.
That is more clear, thanks! It sounds like "hotload" is a volumes-specific concept not a general Baseten one (that can be confused with "hot reload"). I wonder if we can move mounts and hotload under a volumes area? This will also give you a place to add more fields as they come up as opposed to every new non-mount/hotload volume thing being top-level.
There was a problem hiding this comment.
| default_factory=lambda: Weights([]), | ||
| description="Configure Baseten Delivery Network (BDN) for model weight delivery with multi-tier caching.", | ||
| ) | ||
| mounts: list[VolumeMount] = pydantic.Field( |
There was a problem hiding this comment.
@stevvooe @kofmangregory , @cretz mentioned that we should bring back the top level volume section back, so that we can group all configuration related to bdn under the same section.
i recall we decided to remove the top level since mounts and hotload two different things. i think have a top-level section to group all configuration is a good practice, so that we can add any future related config under the same section, maybe instead of volume, we can use other top-level section name like bdn? want to bring it up here and see what is your opinion here?
There was a problem hiding this comment.
i like a top-level section to contain all volume-related config settings. we are not putting this in config.yaml though, right?
There was a problem hiding this comment.
This is config.yaml we're discussing (this model is the schema, eventually a JSON schema, doc'd at https://docs.baseten.co/reference/truss-configuration, generated in SDKs e.g. https://pkg.go.dev/github.com/basetenlabs/baseten-go@v0.2.0/client/modelconfig#ModelConfig, etc). We are encouraging all new features/products to have their own config sections to allow them to add fields in the future and have them be properly qualified/namespaced separate from the rest of the potentially-unrelated config.
6b1813d to
6ae63a1
Compare
Summary
bdn.mountsconfiguration section usingBDNVolumeMountbdn://schemeTesting
uv run pytest truss/tests/test_config.py -q(271 passed)uv run ruff check truss/base/truss_config.py truss/tests/test_config.pyuv run ruff format --check truss/base/truss_config.py truss/tests/test_config.pyuv run mypy truss/base/truss_config.py truss/tests/test_config.pyuv run bin/generate_truss_config_schema.py --check