Skip to content

Commit

Permalink
containerdexecutor: add network namespace callback
Browse files Browse the repository at this point in the history
In order to support identity mapping and user namespaces, the Moby
project needs to defer the creation of a container's network namespace
to the runtime and hook into the container lifecycle to configure the
network namespace before the user binary is started. The standard way to
do so is by configuring a `createRuntime` OCI lifecycle hook, in which
the OCI runtime executes a specified process in the runtime environment
after the container has been created and before it is started. In the
case of Moby the network namespace needs to be configured from the
daemon process, which necessitates that the hook process communicate
with the daemon process. This is complicated and slow. All the hook
process does is inform the daemon of the container's PID and wait until
the daemon has finished applying the network namespace configuration.

There is an alternative to the `createRuntime` OCI hook which containerd
clients can take advantage of. The `container.NewTask` method is
directly analogous to the OCI create operation, and the `task.Start`
method is directly analogous to the OCI start operation. Any operations
performed between the `NewTask` and `Start` calls are therefore directly
analogous to `createRuntime` OCI hooks, without needing to execute any
external processes! Provide a mechanism for network.Namespace instances
to register a callback function which can be used to configure a
container's network namespace instead of, or in addition to,
`createRuntime` OCI hooks.

Signed-off-by: Cory Snider <csnider@mirantis.com>
  • Loading branch information
corhere committed Nov 2, 2022
1 parent 14fa4f2 commit bf1c3d1
Showing 1 changed file with 20 additions and 0 deletions.
20 changes: 20 additions & 0 deletions executor/containerdexecutor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ type containerdExecutor struct {
rootless bool
}

// NetworkNamespaceHooker provides an alternative to OCI hooks for applying
// network configuration to a container. If the network provider returns a
// [network.Namespace] which also implements this interface, the containerd
// executor will run the callback at the appropriate point in the container
// lifecycle.
type NetworkNamespaceHooker interface {
network.Namespace
// OnCreateRuntime is analogous to the createRuntime OCI hook. The
// function is called after the container is created, before the user
// process has been executed. The argument is the container PID in the
// runtime namespace.
OnCreateRuntime(pid uint32) error
}

// New creates a new executor backed by connection to containerd API
func New(client *containerd.Client, root, cgroup string, networkProviders map[pb.NetMode]network.Provider, dnsConfig *oci.DNSConfig, apparmorProfile string, selinux bool, traceSocket string, rootless bool) executor.Executor {
// clean up old hosts/resolv.conf file. ignore errors
Expand Down Expand Up @@ -210,6 +224,12 @@ func (w *containerdExecutor) Run(ctx context.Context, id string, root executor.M
}
}()

if nn, ok := namespace.(NetworkNamespaceHooker); ok {
if err := nn.OnCreateRuntime(task.Pid()); err != nil {
return err
}
}

trace.SpanFromContext(ctx).AddEvent("Container created")
err = w.runProcess(ctx, task, process.Resize, process.Signal, func() {
startedOnce.Do(func() {
Expand Down

0 comments on commit bf1c3d1

Please sign in to comment.