Skip to content

Commit 0214794

Browse files
author
Roy Lin
committed
docs(box): refresh CRI conformance scoreboard (38 pass / 44 fail, v1.30.1)
Updates the stale 2.0.4 baseline (21 pass) to the current measured run: 38 Passed / 44 Failed / 15 Skipped. Documents what now passes (streaming, logs+reopen, most SecurityContext incl. force-RemoveContainer, /proc+/sys in the chroot, ReadonlyPaths) and groups the 44 failures by root cause: ~22 registry-egress + ~1 busybox-substitution artifacts (not defects), writable volume mounts (architectural), seccomp/sysctls/AppArmor (guest features), capabilities (murky/kernel). Adds a Stability section noting graceful-shutdown VM reaping and the SIGKILL-case TODO.
1 parent b8bb31e commit 0214794

1 file changed

Lines changed: 55 additions & 31 deletions

File tree

docs/cri-conformance.md

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,25 @@ This is the versioned `critest` scoreboard for `a3s-box-cri`. It records where
44
the CRI implementation stands against the upstream Kubernetes CRI conformance
55
suite so regressions are visible and progress is measurable.
66

7-
> **Prerequisite:** the CRI server must be reachable over its Unix socket. Until
8-
> the vendored `h2` UDS-authority patch (`third_party/h2`, see the workspace
9-
> `[patch.crates-io]`), `crictl`/`critest` could not connect at all — every RPC
10-
> failed at CRI-API validation with `PROTOCOL_ERROR`.
7+
> **Prerequisite:** the CRI server must be reachable over its Unix socket. This
8+
> required a vendored `h2` UDS-authority patch (`third_party/h2`, see the
9+
> workspace `[patch.crates-io]`); before it, `crictl`/`critest` could not connect
10+
> at all — every RPC failed CRI-API validation with `PROTOCOL_ERROR`.
1111
1212
## Latest run
1313

1414
| Field | Value |
1515
|-------|-------|
16-
| Date | 2026-05-31 |
16+
| Date | 2026-06-01 |
1717
| `critest` | v1.30.1 |
18-
| a3s-box | 2.0.4 |
18+
| a3s-box | 2.0.5 (+ unreleased CRI maturity work, heading to 2.0.6) |
1919
| Host | Linux KVM node (`/dev/kvm`), Ubuntu 24.04 |
20-
| Result | **21 Passed · 59 Failed · 17 Skipped** (ran 80 of 97 specs, ~16 min) |
20+
| Result | **38 Passed · 44 Failed · 15 Skipped** (ran 82 of 97 specs, ~17 min) |
21+
22+
This is up from the original **21 Passed / 59 Failed** baseline (2.0.4): streaming
23+
exec/attach, container logs + reopen, and most of the Linux SecurityContext now
24+
pass. Several remaining "failures" are **test-environment artifacts**, not runtime
25+
defects (see below).
2126

2227
How it was run:
2328

@@ -32,35 +37,54 @@ critest --runtime-endpoint unix:///tmp/a3s-box.sock \
3237
--ginkgo.skip="PortForward"
3338
```
3439

35-
> **Caveat:** all `critest` test images were mapped to a single cached
36-
> `alpine` image (`test-images.yaml`), because the node has no general registry
37-
> egress. Tests that require multiple distinct images or registry pulls
38-
> (~8 specs in `image.go`) therefore fail as **test-setup artifacts**, not real
39-
> runtime defects. They are excluded from the "real gaps" below.
40+
> **Caveat:** all `critest` test images were mapped to a single cached `alpine`
41+
> image (`test-images.yaml`), because the node has no general registry egress.
42+
> Specs that pull a distinct image (`registry.k8s.io/e2e-test-images/{nginx,
43+
> httpd,nonewprivs}`, `gcr.io/.../test-image-predefined-group`) therefore fail at
44+
> image pull as **test-setup artifacts**, not runtime defects. Only
45+
> `defaultTestContainerImage` + `webServerImage` are overridable via the images
46+
> file, so these pulls cannot be redirected to the mirror.
4047
41-
## What passes (21)
48+
## What passes (38)
4249

43-
The core pod + container lifecycle is conformant: `RunPodSandbox` (boots a
44-
microVM), `PodSandboxStatus`, `CreateContainer`, `StartContainer`,
45-
`ContainerStatus`, `ListContainers`/`ListPodSandbox`, `StopContainer`,
46-
`RemoveContainer`, `StopPodSandbox`, `RemovePodSandbox`, plus basic
47-
`RuntimeStatus`/`Version` and basic `ImageStatus`/`ListImages`.
50+
- **Pod + container lifecycle:** `RunPodSandbox` (boots a microVM),
51+
`PodSandboxStatus`, `CreateContainer`, `StartContainer`, `ContainerStatus`,
52+
`ListContainers`/`ListPodSandbox`, `StopContainer`, **`RemoveContainer`
53+
(incl. force-removing a running container)**, `StopPodSandbox`,
54+
`RemovePodSandbox`, plus `RuntimeStatus`/`Version`.
55+
- **Streaming:** `Exec`/`Attach` over SPDY/3.1 (tty on/off, stdin on/off),
56+
`ExecSync`.
57+
- **Container logs:** writing to `log_path` and `ReopenContainerLog` (rotation).
58+
- **Linux SecurityContext:** `RunAsUser`, `RunAsGroup`, `RunAsUserName`
59+
(passwd lookup), reject `RunAsGroup` without `RunAsUser`, `SupplementalGroups`,
60+
`ReadonlyPaths`, seccomp `unconfined`/nil. `/proc` + `/sys` are mounted inside
61+
the container chroot.
62+
- Basic `ImageStatus`/`ListImages`.
4863

4964
## Real gaps (failures grouped by cause)
5065

51-
| Category | Failing specs (examples) | Root cause | Roadmap |
52-
|----------|--------------------------|------------|---------|
53-
| **Linux SecurityContext** | RunAsUser/RunAsGroup/RunAsUserName, add/drop capabilities, Privileged, ReadonlyRootfs, ReadonlyPaths/MaskedPaths, SupplementalGroups | OCI `SecurityContext` is not applied to the in-VM process (`guest-init`) | new: security-context |
54-
| **seccomp / AppArmor / sysctls** | seccomp default/unconfined/localhost, AppArmor permissive/blocking, safe/unsafe sysctls | LSM + sysctl plumbing not implemented in the guest | new: lsm-sysctl |
55-
| **Streaming** | exec (tty on/off, stdin on/off), attach | exec/attach return an empty error; SPDY streaming demux not wired to the VM agent | #5 streaming |
56-
| **Container logs** | starting container with log, reopening container log | CRI log writer does not capture container stdout/stderr to `log_path` | #5 log-writer |
57-
| **Volumes / mounts** | starting with volume, volume host-path symlink, mount propagation (rshared/rslave/rprivate), non-recursive readonly mounts | OCI mount spec (volumes, propagation, ro) not fully honored | new: mounts |
58-
| **Namespaces** | HostNetwork true/false, HostPID, HostIPC, PodPID, ContainerPID | Pod/host namespace sharing modes not mapped into the microVM | new: namespaces |
59-
| **Networking** | DNS config, port mapping (host+container, container-only) | DNS config injection + CRI port mapping over TSI not wired | #5 networking |
66+
| Category | Failing specs (examples) | Root cause | Fixable here? |
67+
|----------|--------------------------|------------|---------------|
68+
| **Registry egress** (~22) | Multiple-Containers exec/log/network, image pull/list/status, DNS, port-mapping, port-forward, HostNetwork/PID/IPC, Privileged, ReadOnlyRootfs, NoNewPrivs, image-group SupplementalGroups | webserver/helper images on `registry.k8s.io`/`gcr.io` are unreachable and not overridable via the images file | ❌ environmental |
69+
| **Writable volume mounts** (~6) | starting container with volume (+ host-path symlink), mount propagation rshared/rslave/rprivate, non-recursive readonly mounts | only read-only mounts (materialized by copy) are supported; writable host-path volumes need a virtio-fs share into the VM, which libkrun configures at boot (containers are created post-boot) | ⚠️ architectural |
70+
| **seccomp filters** (~3) | seccomp `RuntimeDefault` (wants `Seccomp: 2`), localhost profile, SYS_ADMIN-block | no BPF seccomp filter is installed in the guest child | ✅ guest feature |
71+
| **sysctls** (~2) | safe/unsafe sysctls | pod sysctls not applied in the guest (`/proc/sys` writes) | ✅ guest feature |
72+
| **AppArmor** (~2) | unloaded profile, profile blocking writes | LSM not wired in the guest | ✅ guest feature |
73+
| **Capabilities** (~3) | add/drop capability, drop ALL | capabilities not managed per-container; `brctl` bridge test also needs a `CONFIG_BRIDGE` guest kernel | ⚠️ murky / possibly kernel-limited |
74+
| **MaskedPaths** (1) | mask `/bin/ls` | masking code is correct, but under the alpine/busybox substitution `/bin/ls` and `/bin/sh` are the same `busybox` binary, so masking `ls` breaks `sh`; the expected stderr needs `sh` to run | ❌ test-image artifact |
75+
76+
## Stability
77+
78+
- **Graceful shutdown:** on SIGTERM/SIGINT the CRI drains the gRPC server and
79+
reaps every sandbox VM (kills the shim, unmounts its overlay, removes the
80+
rootfs dir) — no more orphaned microVMs/overlays across restarts.
81+
- **TODO:** SIGKILL/crash-case startup reaping (reconcile already marks orphaned
82+
sandboxes NotReady, but does not yet reap the dead instance's leftover shim
83+
processes + overlay mounts).
6084

6185
## Methodology
6286

63-
The baseline is intentionally captured *before* fixing the gaps so each fix can
64-
be measured against it. Re-run after each CRI feature lands and update the
65-
"Latest run" table; the goal is to drive Failed → 0 (excluding documented
66-
test-setup artifacts) and graduate `a3s-box-cri` to a conformant CRI runtime.
87+
The baseline is captured so each fix is measurable. Re-run after each CRI feature
88+
lands and update the "Latest run" table; the goal is to drive Failed → 0
89+
(excluding documented environmental/test-image artifacts) and graduate
90+
`a3s-box-cri` to a conformant, mature CRI runtime.

0 commit comments

Comments
 (0)