Skip to content

Commit

Permalink
Refactor and add documentation
Browse files Browse the repository at this point in the history
Signed-off-by: James Sturtevant <[email protected]>
  • Loading branch information
jsturtevant committed Jan 19, 2024
1 parent fb387ca commit f58fe43
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 54 deletions.
99 changes: 45 additions & 54 deletions crates/containerd-shim-wasm/src/sandbox/containerd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,76 +454,67 @@ impl Client {
};

log::info!("found manifest with WASM OCI image format.");
// This label is unique across runtimes and versions
// This label is unique across runtimes and version of the shim running
// a precompiled component/module will not work across different runtimes or versions
let label = precompile_label(T::info());
match image.labels.get(&label) {
Some(precompile_digest) if T::can_precompile() => {
log::info!("found precompiled image");
log::info!("found precompiled module in cache");
let precompiled = self.read_content(precompile_digest)?;
Ok((
return Ok((
vec![WasmLayer {
config: image_config_descriptor.clone(),
layer: precompiled,

Check warning on line 467 in crates/containerd-shim-wasm/src/sandbox/containerd.rs

View workflow job for this annotation

GitHub Actions / common / lint on ubuntu-latest

Diff in /home/runner/work/runwasi/runwasi/crates/containerd-shim-wasm/src/sandbox/containerd.rs
}],
platform,
))
}
None if T::can_precompile() => {
log::info!("precompiling module");
let layers = manifest
.layers()
.iter()
.filter(|x| is_wasm_layer(x.media_type(), T::supported_layers_types()))
.map(|config| self.read_content(config.digest()))
.collect::<Result<Vec<_>>>()?;

log::debug!("precompile complete and saving content");
let precompiled = engine.precompile(layers.as_slice())?;
let precompiled_content =
self.save_content(precompiled.clone(), image_digest.clone(), T::info())?;

log::debug!("updating image with compiled content digest");
image
.labels
.insert(label, precompiled_content.digest.clone());
self.update_image(image)?;

// The original image is considered a root object, by adding a ref to the new compiled content
// We tell to containerd to not garbage collect the new content until this image is removed from the system
// this ensures that we keep the content around after the lease is dropped
log::debug!("updating content with precompile digest to avoid garbage collection");
let mut image_content = self.get_info(image_digest.clone())?;
image_content.labels.insert(
"containerd.io/gc.ref.content.precompile".to_string(),
precompiled_content.digest.clone(),
);
self.update_info(image_content)?;

Ok((
vec![WasmLayer {
config: image_config_descriptor.clone(),
layer: precompiled,
}],
platform,
))
}
_ => {
log::info!("using module from OCI layers");
let layers = manifest
_ => {}
}

Check warning on line 474 in crates/containerd-shim-wasm/src/sandbox/containerd.rs

View workflow job for this annotation

GitHub Actions / common / lint on ubuntu-latest

Diff in /home/runner/work/runwasi/runwasi/crates/containerd-shim-wasm/src/sandbox/containerd.rs
let layers = manifest
.layers()
.iter()
.filter(|x| is_wasm_layer(x.media_type(), T::supported_layers_types()))
.map(|config| {
self.read_content(config.digest()).map(|module| WasmLayer {
config: config.clone(),
layer: module,
})
})
.collect::<Result<Vec<_>>>()?;
Ok((layers, platform))
}
.map(|config| self.read_content(config.digest())).collect::<Result<Vec<_>>>()?;

if T::can_precompile() {
log::info!("precompiling module");
let precompiled = engine.precompile(layers.as_slice())?;
let precompiled_content =
self.save_content(precompiled.clone(), image_digest.clone(), T::info())?;

Check warning on line 485 in crates/containerd-shim-wasm/src/sandbox/containerd.rs

View workflow job for this annotation

GitHub Actions / common / lint on ubuntu-latest

Diff in /home/runner/work/runwasi/runwasi/crates/containerd-shim-wasm/src/sandbox/containerd.rs

log::debug!("updating image with compiled content digest");
image.labels.insert(label, precompiled_content.digest.clone());
self.update_image(image)?;

// The original image is considered a root object, by adding a ref to the new compiled content
// We tell to containerd to not garbage collect the new content until this image is removed from the system
// this ensures that we keep the content around after the lease is dropped
log::debug!("updating content with precompile digest to avoid garbage collection");
let mut image_content = self.get_info(image_digest.clone())?;
image_content.labels.insert(
"containerd.io/gc.ref.content.precompile".to_string(),
precompiled_content.digest.clone(),
);
self.update_info(image_content)?;

return Ok((
vec![WasmLayer {
config: image_config_descriptor.clone(),
layer: precompiled,

Check warning on line 505 in crates/containerd-shim-wasm/src/sandbox/containerd.rs

View workflow job for this annotation

GitHub Actions / common / lint on ubuntu-latest

Diff in /home/runner/work/runwasi/runwasi/crates/containerd-shim-wasm/src/sandbox/containerd.rs
}],
platform,
))
}

log::info!("using module from OCI layers");
let layers = layers.into_iter().map(|module| WasmLayer {

Check warning on line 512 in crates/containerd-shim-wasm/src/sandbox/containerd.rs

View workflow job for this annotation

GitHub Actions / common / lint on ubuntu-latest

Diff in /home/runner/work/runwasi/runwasi/crates/containerd-shim-wasm/src/sandbox/containerd.rs
config: image_config_descriptor.clone(),
layer: module,
}).collect::<Vec<_>>();
Ok((layers, platform))

}
}

Expand Down
48 changes: 48 additions & 0 deletions docs/oci-descision-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# OCI pre-compilation

The OCI images layers are loaded from containerd. If the runtime supports pre-compilation the images will be precompiled and cached using the containerd content store.

```mermaid
graph TD
start[Task new]
imgconfig[Load image config from containerd]
iswasm{Arch==wasm?}
alreadycompiled{Does image label for shim runtime version exist? runwasi.io/precompiled/runtime/version
}
startcontainer[Create Container]
precompiledenabled{Is precompiling enabled in shim?}
precompiledenabled2{Is precompiling enabled in shim?}
fetchcache[Fetch cached precompiled layer from containerd content store]
precompile[Precompile using wasm runtime]
loadoci[Load OCI layers from containerd]
storecache[Store precompiled layer in containerd content store]
start --> imgconfig --> iswasm
iswasm -- yes --> precompiledenabled
iswasm -- no wasm will be loaded from file inside image --> startcontainer
precompiledenabled -- yes --> alreadycompiled
precompiledenabled -- no --> loadoci --> precompiledenabled2
alreadycompiled -- yes --> fetchcache --> startcontainer
alreadycompiled -- no --> loadoci
precompiledenabled2 -- yes --> precompile --> storecache --> startcontainer
precompiledenabled2 -- no --> startcontainer
```

Once a wasm module or component is pre-compiled it will remain in the containerd content store until the original image is removed from containerd. There is a small disk overhead associated with this but it reduces the complexity of managing stored versions during upgrades.

To view the images in containerd that have associated pre-compilations:

```bash
sudo ctr i ls | grep "runwasi.io"
ghcr.io/containerd/runwasi/wasi-demo-oci:latest application/vnd.oci.image.manifest.v1+json
sha256:60fccd77070dfeb682a1ebc742e9d677fc452b30a6b99188b081c968992394ce 2.4 MiB wasi/wasm
runwasi.io/precompiled/wasmtime/0.3.1=sha256:b36753ab5a46f26f6bedb81b8a7b489cede8fc7386f1398706782e225fd0a98e

# query for the sha in the label
sudo ctr content ls | grep "b36753ab5a46f26f6bedb81b8a7b489cede8fc7386f139870"
sha256:60fccd77070dfeb682a1ebc742e9d677fc452b30a6b99188b081c968992394ce 561B 2 months containerd.io/gc.ref.content.0=sha256:a3c18cd551d54d3cfbf67acc9e8f7ef5761e76827fe7c1ae163fca0193be88b3,containerd.io/gc.ref.content.config=sha256:85b7f2b562fe8665ec9d9e6d47ab0b24e2315627f5f558d298475c4038d71e8b,containerd.io/gc.ref.content.precompile=sha256:b36753ab5a46f26f6bedb81b8a7b489cede8fc7386f1398706782e225fd0a98e
sha256:b36753ab5a46f26f6bedb81b8a7b489cede8fc7386f1398706782e225fd0a98e 626.4kB 3 days runwasi.io/precompiled=sha256:60fccd77070dfeb682a1ebc742e9d677fc452b30a6b99188b081c968992394ce
```

0 comments on commit f58fe43

Please sign in to comment.