Skip to content

k8s: ship sysbox-runc as a containerd drop-in for k3s / RKE2#152

Open
Till0196 wants to merge 2 commits into
nestybox:masterfrom
Till0196:feat/k8s-containerd-dropin
Open

k8s: ship sysbox-runc as a containerd drop-in for k3s / RKE2#152
Till0196 wants to merge 2 commits into
nestybox:masterfrom
Till0196:feat/k8s-containerd-dropin

Conversation

@Till0196
Copy link
Copy Markdown

@Till0196 Till0196 commented May 19, 2026

Summary

The Sysbox v0.7.0 deb already ships everything needed to run sysbox-runc pods with hostUsers: false on K8s + containerd v2 -- the maintainer confirmed as much in nestybox/sysbox-runc#109 ("Sysbox v0.7.0 supports K8s pods with user-namespaces"). Verified empirically: the v0.7.0 deb's sysbox-runc (commit a4dd414f) carries the features subcommand from sysbox-runc#106, which is what advertises userns support to containerd 2.x's runtime introspection (internal/cri/server/service.go::supportsCRIUserns).

On k3s / RKE2 the deploy script cannot actually land that binary stack though, because the dasel-based edit of /etc/containerd/config.toml is wiped on every agent restart (k3s and RKE2 regenerate the file from a template). This PR writes the sysbox-runc runtime block as a config-v3.toml.d drop-in instead -- the supported extension point on those distros.

Problem

sysbox-deploy-k8s fails on k3s / RKE2 with containerd v2 (sysbox#1000):

Detected containerd version 2.1.5-k3s1.
Adding Sysbox to containerd config ...
cp: cannot stat '/mnt/host/etc/containerd/config.toml': No such file or directory

Even when the file is created, k3s/RKE2 regenerate it on the next agent restart so any edits are dropped silently -- the user's runtime config disappears between reboots.

Fix

  • Detect k3s / RKE2 via systemd (k8s_dist_owning_containerd).
  • Write sysbox.toml to the distro's config-v3.toml.d directory: /var/lib/rancher/<dist>/agent/etc/containerd/config-v3.toml.d/sysbox.toml.
  • The drop-in body lives as a static TOML next to the other k8s/config/* artifacts. BinaryName is hard-coded to /usr/bin/sysbox-runc (the only path the installer ever writes for sysbox-CE on non-Flatcar nodes).
  • Vanilla containerd nodes keep the existing dasel-based edit path unchanged.

Why drop-in, not path redirect

Approach Pro Con
Redirect host_containerd_conf_file to /var/lib/rancher/<dist>/.../config.toml Smaller diff Wiped on every agent restart; works against k3s/RKE2's supported extension model
Drop-in into config-v3.toml.d (this PR) Survives regeneration; matches documented extension point Slightly more code (distro detection + restart-service dispatcher)

Note on SupportsUserns

This PR does not set SupportsUserns = true on the runtime entry. The key is not a field on containerd's Runtime config struct (internal/cri/config/config.go) and is silently discarded by the TOML decoder -- empirically verified on containerd 2.2.3-k3s1 (no behavioural difference with or without the line; net-ns ownership and OCI spec user.path are identical). The real userns gating mechanism is the <runtime> features subcommand result, which sysbox-runc already handles since nestybox/sysbox-runc#106 and which is present in the v0.7.0 deb.

Test plan

Verified on Flatcar 4593.2.1 + RKE2 v1.36.0+rke2r1 + containerd 2.2.3-k3s1 + Cilium CNI, with stock v0.7.0 deb binaries (no out-of-tree patches, extracted directly from the sysbox-deploy-k8s container image: sysbox-runc commit a4dd414f, sysbox-fs commit b70bd38b, sysbox-mgr commit aa8f237c):

Scenario Result
Install via daemonset on RKE2 Drop-in written at /var/lib/rancher/rke2/agent/etc/containerd/config-v3.toml.d/sysbox.toml; survives rke2-agent restart
Uninstall Drop-in removed cleanly
runtimeClassName: sysbox-runc + hostUsers: false (alpine sleep) Running. uid_map shows K8s-allocated level-1 range; sysfs/proc mounted; sysbox-fs FUSE serves /proc/sys; binfmt_misc visible
runtimeClassName: sysbox-runc + hostUsers: false + docker:dind Running. Inner dockerd starts, pulls alpine:3.19, inner container gets bridge IP, outbound to 1.1.1.1 succeeds

This matches the maintainer's claim in nestybox/sysbox-runc#109 that v0.7.0 supports hostUsers: false pods -- but only once the deploy script actually lands the runtime registration. This PR is what makes that happen on k3s / RKE2.

The vanilla containerd dasel path was not exercised in the manual test; please flag if additional verification is wanted.

Scope

Till0196 added 2 commits May 19, 2026 18:25
k3s and RKE2 with containerd 2.x regenerate /etc/containerd/config.toml
on every restart, so the existing dasel-based config.toml editing path
is wiped out on the next reboot. The supported extension point is the
config-v3 drop-in directory (config-v3.toml.d), which is read after
the generated base config and merged on top of it.

Detect k3s / RKE2 via systemd, resolve the per-distro drop-in dir
under /var/lib/rancher/<dist>/agent/etc/containerd/, and write a
minimal sysbox-runc runtime block as a standalone drop-in. The
drop-in body is shipped as a template (config/containerd-sysbox-
dropin.toml.tmpl) and rendered with a sed substitution at install
time so the TOML lives next to the other k8s config artifacts rather
than embedded in the deploy script. Vanilla containerd nodes keep
their existing config.toml-editing path.

unconfig_containerd_for_sysbox is updated to mirror the new path:
on k3s / RKE2 it simply removes the drop-in and restarts the wrapper
service.
The drop-in only ever substituted the sysbox-runc binary path. Carrying
it as a .tmpl with an @SYSBOX_RUNC_PATH@ placeholder is heavier than
needed: rename it to a plain .toml that is valid on its own and hard-code
BinaryName to /usr/bin/sysbox-runc (the only path the installer ever
writes on non-Flatcar nodes). Simplify write_containerd_sysbox_dropin()
to a straight cp. config_containerd_for_sysbox() still computes
sysbox_runc_path for the legacy dasel-based containerd.conf branch.
Copilot AI review requested due to automatic review settings May 19, 2026 09:35
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the Kubernetes deploy script to register sysbox-runc with containerd on k3s/RKE2 using the supported config-v3.toml.d drop-in mechanism (instead of editing a regenerated config.toml), so runtime registration persists across agent restarts.

Changes:

  • Detect k3s/RKE2 via systemd and write a containerd config-v3 drop-in at the Rancher-managed path.
  • Add a helper to restart the appropriate owning service (k3s/rke2 vs. vanilla containerd) after config changes.
  • Ship a static TOML artifact in the sysbox-ce image for the drop-in content.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
k8s/scripts/sysbox-deploy-k8s.sh Adds k3s/RKE2 detection, drop-in write/remove logic, and service restart dispatch.
k8s/Dockerfile.sysbox-ce Includes the new containerd drop-in artifact in the image.
k8s/config/containerd-sysbox-dropin.toml Defines the sysbox-runc runtime block for containerd config-v3 drop-in usage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +42 to +45
# Containerd drop-in used on k3s / RKE2. Ships with /usr/bin/sysbox-runc; on
# Flatcar do_distro_adjustments() rewrites this artifact to /opt/bin/sysbox-runc
# up-front, so the install path can copy it verbatim.
containerd_sysbox_dropin_src="${sysbox_artifacts}/config/containerd-sysbox-dropin.toml"
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.sysbox-runc]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.sysbox-runc.options]
BinaryName = "/usr/bin/sysbox-runc"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants