Skip to content

Repository files navigation

containerd-rs

conformance-sig-node conformance-sig-api-machinery conformance-sig-storage conformance-sig-apps conformance-sig-network conformance-sig-cli conformance-sig-scheduling conformance-sig-auth conformance-sig-instrumentation

A Rust reimplementation of containerd's kubelet-facing surface: a daemon that serves the Kubernetes CRI v1 API (RuntimeService + ImageService) over a Unix socket and runs containers via crun (a fast, runc-compatible OCI runtime). The goal (SC-001) is to be a drop-in replacement for containerd as the node container runtime and pass the Kubernetes Conformance suite.

Status: a single-node cluster brought up with kubeadm runs entirely on containerd-rs — control plane converges, the node reaches Ready, the system pods (etcd, apiserver, controller-manager, scheduler, kube-proxy, CoreDNS) run, and kubectl exec/attach/port-forward work over SPDY. A [Conformance] test passes end-to-end; the [Conformance] suite runs in CI, split into per-sig workflows (see below).

Architecture at a glance

containerd-rs uses a direct-crun model: the daemon shells out to crun and supervises the container process in-process (no TTRPC shim). The CRI plugin, content store, snapshotter, and image puller are all built in.

kubelet ──CRI v1 gRPC (unix socket)──▶ containerd-rs daemon
                                        │
   Exec/Attach/PortForward ── URL ─────▶ streaming server (SPDY/3.1 + WS)
                                        │
   images ──▶ content store (verify-on-commit) + overlayfs snapshots
   metadata ──▶ redb                    │
   pods ──▶ CNI (Flannel) / host-net    ▼
                                       crun  (one process per container)
Crate Responsibility
core-types Shared types: content digests, OCI descriptors, namespaces
content Content-addressable blob store (digest/size verified on commit, dedup)
metadata Persistent metadata store backed by redb
snapshots Overlayfs snapshotter: layer diff apply, OCI whiteouts, chainIDs
images Image pull pipeline (oci-client), registry auth, chainID identity, GC
runtime OCI bundle generation + crun supervision (run/exec/kill/stats)
sandbox Pod sandbox model: network namespace + CNI plugin chain
cri CRI v1 gRPC server + the exec/attach/port-forward streaming server
containerd-rs The daemon binary (config, store bring-up, serve, reconcile)

See docs/architecture.md for the request flow and design notes, and docs/configuration.md for the full config reference.

Build

make build          # debug build of the workspace
make release        # release build (produces target/release/containerd-rs)
make check          # fmt-check + clippy (-D warnings) + tests — the local gate

make check mirrors CI exactly; run it before pushing.

Run the daemon

sudo containerd-rs --config /etc/containerd-rs/config.toml

A minimal config (all fields have defaults — see the config reference):

root  = "/var/lib/containerd-rs"      # persistent store (content, snapshots, metadata)
state = "/run/containerd-rs"          # ephemeral state (crun root, OCI bundles)
cri_socket = "/run/containerd-rs.sock"
stream_server_address = "127.0.0.1:10010"

[cri]
sandbox_image = "registry.k8s.io/pause:3.10"
snapshotter   = "overlayfs"
cni_conf_dir  = "/etc/cni/net.d"
cni_bin_dir   = "/opt/cni/bin"

Point the kubelet at it with --container-runtime-endpoint=unix:///run/containerd-rs.sock.

Smoke-test with crictl:

crictl --runtime-endpoint unix:///run/containerd-rs.sock version
crictl --runtime-endpoint unix:///run/containerd-rs.sock images

Bring up a single-node cluster

ci/kubeadm-init.sh (via make cluster-up) stands up a kubeadm control plane on containerd-rs as the sole runtime. Requires root + crun, kubeadm/kubelet/ kubectl, crictl, and CNI plugins on the host.

make release
make cluster-up     # phase-by-phase kubeadm + manual kubelet; waits for Ready + 7/7 pods
make cluster-down   # kubeadm reset + stop kubelet/daemon

Conformance (SC-001)

The Kubernetes [Conformance] suite is the acceptance gate. It runs via hydrophone:

make conformance-smoke   # one Conformance test (fast pipeline check)
make conformance         # full [Conformance] suite -> conformance-results/

In CI the suite is split into manual (workflow_dispatch) per-sig workflows, each building the daemon, installing the Kubernetes toolchain, bringing up the cluster on a real runner, and running its slice via hydrophone (they share conformance-reusable.yml). The split covers 441 of the [Conformance] specs across nine SIGs (registry.k8s.io/conformance:v1.35.6):

Workflow Focus Specs Asserts
conformance-sig-node.yml [sig-node] 105 runtime/CRI on the node: lifecycle, exec/attach, probes, security context, env, sysctls, ephemeral containers
conformance-sig-api-machinery.yml [sig-api-machinery] 95 apiserver contract: CRDs, admission webhooks, watch, namespaces, garbage collection, resource quota, server-side apply
conformance-sig-storage.yml [sig-storage] 91 volume/mount path: emptyDir, configMap/secret/projected/downwardAPI volumes, subpaths
conformance-sig-apps.yml [sig-apps] 60 workload controllers: Deployment, ReplicaSet, StatefulSet, DaemonSet, Job, CronJob (rolling updates, scale, ordered bring-up)
conformance-sig-network.yml [sig-network] 47 pod networking, Services/ClusterIP, DNS, hostPort
conformance-sig-cli.yml [sig-cli] 17 kubectl behaviours: create/apply/run/expose/patch/label
conformance-sig-scheduling.yml [sig-scheduling] 11 predicates and basic scheduling: node selectors, taints/tolerations, resource fit
conformance-sig-auth.yml [sig-auth] 10 ServiceAccount tokens, projected SA volumes, related authn/authz
conformance-sig-instrumentation.yml [sig-instrumentation] 4 Events API lifecycle: create/patch/delete/list

A few [Conformance] specs structurally require a multi-node cluster (they fail with "needs a cluster with at least 2 nodes") and so cannot pass on this single-node setup — [sig-architecture] … should have at least two untainted nodes (no workflow) and [sig-apps] Daemon set [Serial] should rollback without unnecessary restarts. ci/run-conformance.sh skips these by default (SKIP regex, overridable); they are environmental, not runtime, limitations.

They run only on demand (conformance is expensive; CI minutes are limited), and each can be validated locally first with the docker harness, e.g. make conformance-docker FOCUS='\[sig-apps\].*\[Conformance\]'. The status badges at the top of this README reflect each workflow's latest run.

CRI conformance (critest)

Alongside the Kubernetes suite, containerd-rs is gated on critest — the CRI-conformance suite that upstream containerd and CRI-O themselves gate on. It exercises the CRI contract directly (no kubelet), so it catches runtime-surface regressions the end-to-end suite would only find indirectly.

Equivalence with containerd is defined as: critest green minus a ratified, documented skip list. The current local result is 85 Passed / 0 Failed / 28 Skipped — every runnable spec passes. The skips are by-design or environmental, not runtime gaps (containerd maintains its own skips likewise):

Skipped spec Why
AppArmor (profile tests) Environmental: the profile can't be loaded on the harness (in-container → apparmor_parser//sys/kernel/security/apparmor unavailable, matching containerd's HostSupports() guard). RuntimeDefault AppArmor is a no-op where AppArmor is unsupported.
should output OOMKilled reason By-design: crun run deletes the container cgroup on exit, so the post-mortem OOM flag isn't readable.
should support RunAsUserName Windows-style username; N/A on Linux.

Run it locally with no CI minutes / host sudo (self-contained privileged container — installs critest, brings up the daemon, runs the suite):

make critest-docker                              # full suite (green-minus-skips)
make critest-docker FOCUS='seccomp default'      # one focused spec

The critest.yml workflow runs the same gate in CI (workflow_dispatch).

Testing

  • Unit + contract + integration tests: make test (or cargo test --workspace).
  • Tests that need crun/network are #[ignore]d; run them with cargo test -p <crate> -- --ignored.
  • CRI contract tests: crates/cri/tests/contract_*.rs.
  • End-to-end pod lifecycle + image management: crates/cri/tests/integration_*.rs.

License

MIT — see LICENSE.

About

Containerd reimplemented in Rust

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages