Skip to content

Commit 7976bfd

Browse files
committed
Containerd: use correct platform for building
Signed-off-by: James Sturtevant <jstur@microsoft.com>
1 parent 03a3214 commit 7976bfd

7 files changed

Lines changed: 75 additions & 29 deletions

File tree

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,11 @@ dist/img-oci.tar: target/wasm32-wasi/$(OPT_PROFILE)/img-oci.tar
188188
load: dist/img.tar
189189
sudo ctr -n $(CONTAINERD_NAMESPACE) image import --all-platforms $<
190190

191+
CTR_VERSION := $(shell sudo ctr version | sed -n -e '/Version/ {s/.*: *//p;q;}')
191192
load/oci: dist/img-oci.tar
192-
sudo ../containerd/bin/ctr -n $(CONTAINERD_NAMESPACE) image import --all-platforms $<
193+
@echo $(CTR_VERSION)\\nv1.7.7 | sort -crV || (echo "containerd version must be 1.7.7+ was $(CTR_VERSION)" && exit 1)
194+
@echo using containerd $(CTR_VERSION)
195+
sudo ctr -n $(CONTAINERD_NAMESPACE) image import --all-platforms $<
193196

194197
.PHONY:
195198
target/wasm32-wasi/$(OPT_PROFILE)/img-oci.tar: target/wasm32-wasi/$(OPT_PROFILE)/wasi-demo-app.wasm

crates/containerd-shim-wasm/src/container/context.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::path::{Path, PathBuf};
22

3+
use oci_spec::image::Platform;
34
use oci_spec::runtime::Spec;
45

56
use crate::sandbox::oci::WasmLayer;
@@ -24,6 +25,8 @@ pub trait RuntimeContext {
2425
fn wasi_entrypoint(&self) -> WasiEntrypoint;
2526

2627
fn wasm_layers(&self) -> &[WasmLayer];
28+
29+
fn platform(&self) -> &Platform;
2730
}
2831

2932
pub struct WasiEntrypoint {
@@ -34,6 +37,7 @@ pub struct WasiEntrypoint {
3437
pub(crate) struct WasiContext<'a> {
3538
pub spec: &'a Spec,
3639
pub wasm_layers: &'a [WasmLayer],
40+
pub platform: &'a Platform,
3741
}
3842

3943
impl RuntimeContext for WasiContext<'_> {
@@ -62,6 +66,10 @@ impl RuntimeContext for WasiContext<'_> {
6266
fn wasm_layers(&self) -> &[WasmLayer] {
6367
self.wasm_layers
6468
}
69+
70+
fn platform(&self) -> &Platform {
71+
self.platform
72+
}
6573
}
6674

6775
#[cfg(test)]
@@ -86,6 +94,7 @@ mod tests {
8694
let ctx = WasiContext {
8795
spec: &spec,
8896
wasm_layers: &[],
97+
platform: &Platform::default(),
8998
};
9099

91100
let args = ctx.args();
@@ -105,6 +114,7 @@ mod tests {
105114
let ctx = WasiContext {
106115
spec: &spec,
107116
wasm_layers: &[],
117+
platform: &Platform::default(),
108118
};
109119

110120
let args = ctx.args();
@@ -132,6 +142,7 @@ mod tests {
132142
let ctx = WasiContext {
133143
spec: &spec,
134144
wasm_layers: &[],
145+
platform: &Platform::default(),
135146
};
136147

137148
let args = ctx.args();
@@ -153,6 +164,7 @@ mod tests {
153164
let ctx = WasiContext {
154165
spec: &spec,
155166
wasm_layers: &[],
167+
platform: &Platform::default(),
156168
};
157169

158170
let path = ctx.wasi_entrypoint().path;
@@ -180,6 +192,7 @@ mod tests {
180192
let ctx = WasiContext {
181193
spec: &spec,
182194
wasm_layers: &[],
195+
platform: &Platform::default(),
183196
};
184197

185198
let WasiEntrypoint { path, func } = ctx.wasi_entrypoint();
@@ -208,6 +221,7 @@ mod tests {
208221
let ctx = WasiContext {
209222
spec: &spec,
210223
wasm_layers: &[],
224+
platform: &Platform::default(),
211225
};
212226

213227
let WasiEntrypoint { path, func } = ctx.wasi_entrypoint();

crates/containerd-shim-wasm/src/sandbox/containerd.rs

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use containerd_client::services::v1::{GetContainerRequest, GetImageRequest, Read
1010
use containerd_client::tonic::transport::Channel;
1111
use containerd_client::{tonic, with_namespace};
1212
use futures::TryStreamExt;
13-
use oci_spec::image::{Arch, ImageManifest};
13+
use oci_spec::image::{Arch, ImageManifest, MediaType, Platform};
1414
use tokio::runtime::Runtime;
1515
use tonic::Request;
1616

@@ -116,39 +116,57 @@ impl Client {
116116
// load module will query the containerd store to find an image that has an OS of type 'wasm'
117117
// If found it continues to parse the manifest and return the layers that contains the WASM modules
118118
// and possibly other configuration layers.
119-
pub fn load_modules(&self, containerd_id: impl ToString) -> Result<Vec<oci::WasmLayer>> {
119+
pub fn load_modules(
120+
&self,
121+
containerd_id: impl ToString,
122+
) -> Result<(Vec<oci::WasmLayer>, Platform)> {
120123
let image_name = self.get_image(containerd_id.to_string())?;
121124
let digest = self.get_image_content_sha(image_name)?;
122125
let manifest = self.read_content(digest)?;
123126
let manifest = manifest.as_slice();
124127
let manifest = ImageManifest::from_reader(manifest)?;
125128

126-
let arch = manifest
127-
.config()
128-
.platform()
129-
.as_ref()
130-
.ok_or_else(|| ShimError::Containerd("failed to extract platform".to_string()))?
131-
.architecture();
129+
let image_config_descriptor = manifest.config();
130+
let image_config = self.read_content(image_config_descriptor.digest())?;
131+
let image_config = image_config.as_slice();
132132

133-
match arch {
134-
Arch::Wasm => {
135-
log::info!("found manifest with WASM OCI image format.");
136-
}
137-
_ => {
138-
log::info!("manifest is not in WASM OCI image format");
139-
return Ok([].to_vec());
140-
}
141-
}
133+
// the only part we care about here is the platform values
134+
let platform: Platform = serde_json::from_slice(image_config)?;
135+
let Arch::Wasm = platform.architecture() else {
136+
log::info!("manifest is not in WASM OCI image format");
137+
return Ok((vec![], platform));
138+
};
139+
log::info!("found manifest with WASM OCI image format.");
142140

143-
manifest
141+
let layers = manifest
144142
.layers()
145143
.iter()
144+
.filter(|x| !is_image_layer_type(x.media_type()))
146145
.map(|config| {
147146
self.read_content(config.digest()).map(|module| WasmLayer {
148147
config: config.clone(),
149148
layer: module,
150149
})
151150
})
152-
.collect::<Result<Vec<_>>>()
151+
.collect::<Result<Vec<_>>>()?;
152+
Ok((layers, platform))
153+
}
154+
}
155+
156+
fn is_image_layer_type(media_type: &MediaType) -> bool {
157+
match media_type {
158+
MediaType::ImageLayer
159+
| MediaType::ImageLayerGzip
160+
| MediaType::ImageLayerNonDistributable
161+
| MediaType::ImageLayerNonDistributableGzip
162+
| MediaType::ImageLayerNonDistributableZstd
163+
| MediaType::ImageLayerZstd => true,
164+
MediaType::Other(s)
165+
if s.as_str()
166+
.starts_with("application/vnd.docker.image.rootfs.") =>
167+
{
168+
true
169+
}
170+
_ => false,
153171
}
154172
}

crates/containerd-shim-wasm/src/sandbox/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub enum Error {
4747
#[error("{0}")]
4848
Libcontainer(#[from] libcontainer::error::LibcontainerError),
4949
#[error("{0}")]
50-
Containerd(String)
50+
Containerd(String),
5151
}
5252

5353
pub type Result<T> = ::std::result::Result<T, Error>;

crates/containerd-shim-wasm/src/sys/unix/container/executor.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use libcontainer::workload::{
1010
Executor as LibcontainerExecutor, ExecutorError as LibcontainerExecutorError,
1111
ExecutorValidationError,
1212
};
13+
use oci_spec::image::Platform;
1314
use oci_spec::runtime::Spec;
1415

1516
use crate::container::{Engine, PathResolve, RuntimeContext, Stdio, WasiContext};
@@ -28,6 +29,7 @@ pub(crate) struct Executor<E: Engine> {
2829
stdio: Stdio,
2930
inner: OnceCell<InnerExecutor>,
3031
wasm_layers: Vec<WasmLayer>,
32+
platform: Platform,
3133
}
3234

3335
impl<E: Engine> LibcontainerExecutor for Executor<E> {
@@ -64,18 +66,24 @@ impl<E: Engine> LibcontainerExecutor for Executor<E> {
6466
}
6567

6668
impl<E: Engine> Executor<E> {
67-
pub fn new(engine: E, stdio: Stdio, wasm_layers: Vec<WasmLayer>) -> Self {
69+
pub fn new(engine: E, stdio: Stdio, wasm_layers: Vec<WasmLayer>, platform: Platform) -> Self {
6870
Self {
6971
engine,
7072
stdio,
7173
inner: Default::default(),
7274
wasm_layers,
75+
platform,
7376
}
7477
}
7578

7679
fn ctx<'a>(&'a self, spec: &'a Spec) -> WasiContext<'a> {
7780
let wasm_layers = &self.wasm_layers;
78-
WasiContext { spec, wasm_layers }
81+
let platform = &self.platform;
82+
WasiContext {
83+
spec,
84+
wasm_layers,
85+
platform,
86+
}
7987
}
8088

8189
fn inner(&self, spec: &Spec) -> &InnerExecutor {

crates/containerd-shim-wasm/src/sys/unix/container/instance.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ use libcontainer::syscall::syscall::SyscallType;
1212
use nix::errno::Errno;
1313
use nix::sys::wait::{waitid, Id as WaitID, WaitPidFlag, WaitStatus};
1414
use nix::unistd::Pid;
15+
use oci_spec::image::Platform;
1516

1617
use crate::container::Engine;
1718
use crate::sandbox::instance_utils::{determine_rootdir, get_instance_root, instance_exists};
1819
use crate::sandbox::sync::WaitableCell;
19-
use crate::sandbox::{containerd, Error as SandboxError, Instance as SandboxInstance, InstanceConfig, Stdio};
20+
use crate::sandbox::{
21+
containerd, Error as SandboxError, Instance as SandboxInstance, InstanceConfig, Stdio,
22+
};
2023
use crate::sys::container::executor::Executor;
2124

2225
static DEFAULT_CONTAINER_ROOT_DIR: &str = "/run/containerd";
@@ -41,15 +44,15 @@ impl<E: Engine> SandboxInstance for Instance<E> {
4144
let stdio = Stdio::init_from_cfg(cfg)?;
4245

4346
// check if container is OCI image with wasm layers and attempt to read the module
44-
let modules = containerd::Client::connect(cfg.get_containerd_address(), &namespace)?
47+
let (modules, platform) = containerd::Client::connect(cfg.get_containerd_address(), &namespace)?
4548
.load_modules(&id)
4649
.unwrap_or_else(|e| {
4750
log::warn!("Error obtaining wasm layers for container {id}. Will attempt to use files inside container image. Error: {e}");
48-
vec![]
51+
(vec![], Platform::default())
4952
});
5053

5154
ContainerBuilder::new(id.clone(), SyscallType::Linux)
52-
.with_executor(Executor::new(engine, stdio, modules))
55+
.with_executor(Executor::new(engine, stdio, modules, platform))
5356
.with_root_path(rootdir.clone())?
5457
.as_init(&bundle)
5558
.with_systemd(false)

test/k8s/Dockerfile.oci

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
ARG KIND_NODE_VERSION=v1.27.3@sha256:3966ac761ae0136263ffdb6cfd4db23ef8a83cba8a463690e98317add2c9ba72
44
ARG RUNTIME=wasmtime
5-
ARG GO_VERSION="1.21.1"
5+
ARG GO_VERSION="1.21.3-bullseye"
66

77
# modified from https://github.com/kubernetes-sigs/kind/blob/main/images/base/Dockerfile
88
# stage for building containerd
99
FROM golang:${GO_VERSION} as build-containerd
10-
ARG CONTAINERD_VERSION="main"
10+
ARG CONTAINERD_VERSION="v1.7.7"
1111
ARG CONTAINERD_CLONE_URL="https://github.com/containerd/containerd"
1212
# we don't build with optional snapshotters, we never select any of these
1313
# they're not ideal inside kind anyhow, and we save some disk space

0 commit comments

Comments
 (0)