-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Component dependencies not working #238
Comments
Retried this locally and can confirm that this is not working |
I believe this is because we do not check for component dependencies before precompiling. I'd be curious if packaging the app with docker instead of OCI makes it work since we do not precompile for Docker images. |
Hey all, i'm the author of spin's component dependencies feature and i've been looking into implementing support for the shim. The obvious place to hook in is at the point of precompiling. My initial thinking was that calling To compose, we would need to re-construct the
However, each wasm layer is not 1:1 with a component in the What this means is that for each wasm layer, which may relate to 1-or-more spin components, may yield one of 2 different precompiled wasms, and so we can't assume that I haven't dug into the upstream shim crate (where Please let me know if what i said isn't clear or if i'm misunderstanding the invariant! |
We could potentially change this. At one-point during the initial designs we didn't have this restraint. The tricky part is communicating back which components are tied to which layer, so we can look them up and send them along properly. I put some thoughts in containerd/runwasi#504 a while back |
As far as I know, the |
I was thinking about this a bit more. I have a few questions to help me understand the use case a bit more the Kubernetes env. (From a dev, perspective this is a really cool feature!)
|
Hey @jsturtevant, thanks for taking a look!
|
Capturing the outcome of discussions with @jsturtevant and @Mossaka late last week on a potential solution for support component dependencies. Effectively what needs to be done is to relax the assumption that the input layers to To do this, a rough proposal sketch subject-to-change (inspired by James' original proposal linked above) might look like this: struct ProcessedLayer {
layer: Vec<u8>, // Bytes of processed layer
mapping: IndexSet<usize>, // Indices in to original layers using to produced this new layer
}
enum Layer {
Original(digest), // Untouched
Processed(ProcessedLayer),
}
fn process_layers(&self, _layers: &[WasmLayer]) -> Result<Vec<Layer>> {
// do work
} On return, the shim would use the mappings of each processed layer to attach gc labels to the original layers used to construct it. For untouched layers, we could associate it via label to the original layer using the index as its done today. |
Something to consider: I wonder if the full generalized version of the layers is a directed acyclic graph (DAG). In this graph, we have nodes and edges where edges are pointers to the original nodes. In DAG, we could enable multiple processed layers referring to one original layer or one processed layer referring to multiple original layers. We can do a topological ordering of the DAG to traverse through the graph. struct LayerGraph {
layers: vec<Layer>, // ID to layer
dependencies: vec<BTreeSet<usize>>, // Adjacency list of edges
}
struct Layer {
data: Option<Vec<u8>>,
}
impl LayerGraph {
fn topological_order(&self) -> Result<Vec<usize>> {
...
}
} |
Great call out @Mossaka, I think you're right that the full generalized version of this is best represented as a DAG. |
I'm making good progress on evolving the As a strawman, perhaps the api here should evolve to return something like: struct ProcessedLayers {
// 1:1 mapping with original (None if original should be used)
rewritten: Vec<Option<Vec<u8>>>,
// Layers created during precompile/processing
created: Vec<NewLayer>,
}
struct NewLayer {
// Needed to communicate back to the shim for creating a new `oci::image::Descriptor`
media_type: String,
// Bytes of the layer
bytes: Vec<u8>,
// Indices of original layers used during processing
dependencies: BTreeSet<usize>,
} Currently in the shim when a layer is rewritten the descriptor from the original layer is used to construct a |
From a runwasi/containerd perspective, I don't think this should be an issue. In spin the "pre-compiled" bytes are written to the cached location using the original digest id so this might cause an issue. Maybe there is a way to track this on spin side? The layer original digest id is used here but the precompiled bytes are written: containerd-shim-spin/containerd-shim-spin/src/source.rs Lines 58 to 60 in 1a93553
Is the layer different from the original here? I.e. If you want a different layer returned instead of the original, could that be considered "New layer"? |
I think in cases such as wanting to rewrite the |
I think we cracked it, I will open WIP PRs in the coming days for 👀 before moving onto polish. |
Trying to run an application that uses component dependencies -- for example https://github.com/radu-matei/spin-deps-image-manipulation.
Locally everything runs properly. However, when I run the app using SpinKube, I get the following error:
The text was updated successfully, but these errors were encountered: