cmd/containerd-shim-sandboxed-runc-v2: persist the runc options in the sandbox bundle

"shim start" writes the runc options of the runtime handler and the
runtime name into the sandbox bundle, the files runc.NewContainer writes
for a task bundle. The sandbox service reads them to run a process
through the same runc, root and cgroup driver as the containers of the
pod, and "shim delete" reads them to force-delete that runc container
once the shim is gone.

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
This commit is contained in:
Maksym Pavlenko committed 2026-11-04 19:04:42 -08:00
1 parent 16d7ff4f1a
commit e09b89ff81
1 file changed
+25 -5
@@ -41,6 +41,7 @@ import (
"github.com/opencontainers/runtime-spec/specs-go/features"
legacymanager "github.com/containerd/containerd/v2/cmd/containerd-shim-runc-v2/manager"
"github.com/containerd/containerd/v2/cmd/containerd-shim-runc-v2/runc"
"github.com/containerd/containerd/v2/cmd/containerd-shim-sandboxed-runc-v2/sandbox"
"github.com/containerd/containerd/v2/defaults"
"github.com/containerd/containerd/v2/pkg/namespaces"
@@ -163,6 +164,12 @@ func (m *manager) Start(ctx context.Context, opts *bootapi.BootstrapParams) (_ *
return nil, fmt.Errorf("%s requires cgroup v2 (the unified hierarchy) and this host runs cgroup v1: %w", sandbox.BinaryName, errdefs.ErrNotImplemented)
}
// The working directory is the sandbox bundle.
cwd, err := os.Getwd()
if err != nil {
return nil, err
}
var params bootapi.BootstrapResult
params.Version = 3
params.Protocol = "ttrpc"
@@ -238,6 +245,16 @@ func (m *manager) Start(ctx context.Context, opts *bootapi.BootstrapParams) (_ *
if found, err := opts.FindExtension(&runcOpts); err != nil {
return nil, fmt.Errorf("failed to fetch runc options: %w", err)
} else if found {
// The runc options are persisted in the bundle. The sandbox service
// reads them to run containerd-sandbox-init through the same runc,
// root and cgroup driver as the containers of the pod, and Stop
// reads them to delete that container once the shim is gone.
if err := runc.WriteOptions(cwd, &runcOpts); err != nil {
return nil, fmt.Errorf("failed to persist the runc options: %w", err)
}
if err := runc.WriteRuntime(cwd, runcOpts.GetBinaryName()); err != nil {
return nil, fmt.Errorf("failed to persist the runtime name: %w", err)
}
if shimCgroup := runcOpts.GetShimCgroup(); shimCgroup != "" {
cg, err := cgroupsv2.Load(shimCgroup)
if err != nil {
@@ -259,11 +276,14 @@ func (m *manager) Start(ctx context.Context, opts *bootapi.BootstrapParams) (_ *
// Stop is "shim delete". containerd runs it in a bundle once the shim that
// served the bundle is gone: in the sandbox bundle, and in the bundle of every
// container task that joined the shim. Nothing needs telling apart: the runc
// task cleanup of containerd-shim-runc-v2 (force-delete the runc container of
// that id, detach its rootfs) does nothing in the sandbox bundle, and the
// sandbox cleanup (detach every mount under the bundle, remove the pod files)
// does nothing in a task bundle, so both run every time.
// container task that joined the shim. Stop does not tell the two apart and
// runs both cleanups every time:
// - The runc task cleanup of containerd-shim-runc-v2 force-deletes the runc
// container of that id and detaches its rootfs. In the sandbox bundle of a
// shared-PID pod that deletes containerd-sandbox-init; in any other
// sandbox bundle it does nothing.
// - The sandbox cleanup detaches every mount under the bundle and removes
// the pod files. In a task bundle it does nothing.
func (m *manager) Stop(ctx context.Context, id string) (shim.StopStatus, error) {
status, err := m.legacy.Stop(ctx, id)
cwd, cwdErr := os.Getwd()