Skip to content

Commit 1dfd3f0

Browse files
committed
kata-deploy: keep the default snapshotter in the erofs unpack config
d607cce ("EROFS verity: declare the block size, pin the differ, fail closed (RM-47/48/50)") writes an unpack_config listing only the erofs snapshotter. That key replaces containerd's built-in default rather than extending it, and getSupportedPlatform() in core/transfer/local/pull.go only accepts an entry whose snapshotter equals the one the pull asked for. So every pull that does not ask for erofs matches nothing, the unpacker is built with an empty platform list, and the pull fails with unable to initialize unpacker: no unpack platforms defined Since we also set use_local_image_pull = false, every CRI pull goes through the transfer service, so this takes down image pulls node-wide - the erofs k8s jobs fail it on each test. Restate containerd's default entry next to the erofs binding. An erofs pull still goes through the erofs differ, which is all RM-50 asked for, and everything else pulls the way it did before kata-deploy touched the config. Ordering is safe: a match requires the snapshotter to be equal, and a pull that omits it explicitly prefers the default snapshotter entry. Assisted-by: GitHub Copilot (Claude) Signed-off-by: Saul Paredes <saulparedes@microsoft.com>
1 parent 6004be4 commit 1dfd3f0

1 file changed

Lines changed: 50 additions & 5 deletions

File tree

tools/packaging/kata-deploy/binary/src/artifacts/snapshotters.rs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,29 @@ fn erofs_mkfs_options() -> String {
3131
"[\"-T0\",\"--mkfs-time\",\"--sort=none\"]".to_string()
3232
}
3333

34+
/// containerd's own default unpack snapshotter, restated because `unpack_config`
35+
/// replaces the built-in default wholesale rather than extending it.
36+
const DEFAULT_UNPACK_SNAPSHOTTER: &str = "overlayfs";
37+
3438
/// Bind the transfer service's unpacker for the `erofs` snapshotter to the `erofs`
3539
/// differ, so layer construction cannot silently fall back to a path that produces
3640
/// no dm-verity metadata. See RM-50 and the call site for why this matters.
41+
///
42+
/// The default-snapshotter entries are not optional padding. Setting this key
43+
/// discards containerd's built-in default, and the transfer service only unpacks a
44+
/// pull whose requested snapshotter equals one of the entries here
45+
/// (`getSupportedPlatform` in core/transfer/local/pull.go). With erofs-only
46+
/// entries, every pull that does not ask for erofs -- i.e. every non-kata pod on
47+
/// the node -- matches nothing and fails the whole pull with "unable to initialize
48+
/// unpacker: no unpack platforms defined".
3749
fn erofs_unpack_config() -> String {
38-
"[{platform = \"linux/amd64\", snapshotter = \"erofs\", differ = \"erofs\"}, \
39-
{platform = \"linux/arm64\", snapshotter = \"erofs\", differ = \"erofs\"}]"
40-
.to_string()
50+
format!(
51+
"[{{platform = \"linux/amd64\", snapshotter = \"{d}\"}}, \
52+
{{platform = \"linux/arm64\", snapshotter = \"{d}\"}}, \
53+
{{platform = \"linux/amd64\", snapshotter = \"erofs\", differ = \"erofs\"}}, \
54+
{{platform = \"linux/arm64\", snapshotter = \"erofs\", differ = \"erofs\"}}]",
55+
d = DEFAULT_UNPACK_SNAPSHOTTER
56+
)
4157
}
4258
use std::path::Path;
4359

@@ -603,11 +619,12 @@ mod tests {
603619
let entries = doc["unpack_config"]
604620
.as_array()
605621
.expect("array of inline tables");
606-
assert_eq!(entries.len(), 2, "one entry per supported platform");
607622
let mut platforms = Vec::new();
608623
for entry in entries.iter() {
609624
let table = entry.as_inline_table().expect("inline table");
610-
assert_eq!(table["snapshotter"].as_str(), Some("erofs"));
625+
if table["snapshotter"].as_str() != Some("erofs") {
626+
continue;
627+
}
611628
assert_eq!(
612629
table["differ"].as_str(),
613630
Some("erofs"),
@@ -619,6 +636,34 @@ mod tests {
619636
assert!(platforms.contains(&"linux/arm64".to_string()));
620637
}
621638

639+
/// Writing this key replaces containerd's built-in default, so dropping the
640+
/// default-snapshotter entries leaves every non-erofs pull on the node with no
641+
/// matching unpack platform, failing with "no unpack platforms defined".
642+
#[test]
643+
fn erofs_unpack_config_keeps_the_default_snapshotter() {
644+
let doc: toml_edit::DocumentMut = format!("unpack_config = {}", erofs_unpack_config())
645+
.parse()
646+
.expect("unpack_config must be TOML");
647+
let platforms: Vec<String> = doc["unpack_config"]
648+
.as_array()
649+
.expect("array of inline tables")
650+
.iter()
651+
.filter_map(|entry| {
652+
let table = entry.as_inline_table()?;
653+
(table["snapshotter"].as_str() == Some(DEFAULT_UNPACK_SNAPSHOTTER))
654+
.then(|| table["platform"].as_str().unwrap().to_string())
655+
})
656+
.collect();
657+
assert!(
658+
platforms.contains(&"linux/amd64".to_string()),
659+
"{platforms:?}"
660+
);
661+
assert!(
662+
platforms.contains(&"linux/arm64".to_string()),
663+
"{platforms:?}"
664+
);
665+
}
666+
622667
/// containerd's differ appends its own `-U <uuid-of-layer-digest>` after these
623668
/// options, and mkfs.erofs honours the last one, so passing our own would be
624669
/// dead configuration that misleads a reader into thinking reproducibility

0 commit comments

Comments
 (0)