Skip to content

Commit 6123436

Browse files
committed
cgroup2: use shim V2
* Requires containerd binaries from containerd/containerd#3799 . Metrics are unimplemented yet. * Works with crun v0.10.4, but `--security-opt seccomp=unconfined` is needed unless using master version of libseccomp ( containers/crun#156, seccomp/libseccomp#177 ) * Doesn't work with master runc yet * Resource limitations are unimplemented Signed-off-by: Akihiro Suda <[email protected]>
1 parent e6f6c35 commit 6123436

10 files changed

Lines changed: 93 additions & 26 deletions

File tree

daemon/daemon.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
794794
PluginStore: pluginStore,
795795
startupDone: make(chan struct{}),
796796
}
797+
797798
// Ensure the daemon is properly shutdown if there is a failure during
798799
// initialization
799800
defer func() {
@@ -914,7 +915,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
914915
}
915916
}
916917

917-
return pluginexec.New(ctx, getPluginExecRoot(config.Root), pluginCli, config.ContainerdPluginNamespace, m)
918+
return pluginexec.New(ctx, getPluginExecRoot(config.Root), pluginCli, config.ContainerdPluginNamespace, m, d.useShimV2())
918919
}
919920

920921
// Plugin system initialization should happen before restore. Do not change order.
@@ -1063,7 +1064,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
10631064

10641065
go d.execCommandGC()
10651066

1066-
d.containerd, err = libcontainerd.NewClient(ctx, d.containerdCli, filepath.Join(config.ExecRoot, "containerd"), config.ContainerdNamespace, d)
1067+
d.containerd, err = libcontainerd.NewClient(ctx, d.containerdCli, filepath.Join(config.ExecRoot, "containerd"), config.ContainerdNamespace, d, d.useShimV2())
10671068
if err != nil {
10681069
return nil, err
10691070
}

daemon/daemon_unix.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,3 +1639,7 @@ func (daemon *Daemon) setupSeccompProfile() error {
16391639
}
16401640
return nil
16411641
}
1642+
1643+
func (daemon *Daemon) useShimV2() bool {
1644+
return cgroups.IsCgroup2UnifiedMode()
1645+
}

daemon/daemon_windows.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,3 +653,7 @@ func (daemon *Daemon) initRuntimes(_ map[string]types.Runtime) error {
653653

654654
func setupResolvConf(config *config.Config) {
655655
}
656+
657+
func (daemon *Daemon) useShimV2() bool {
658+
return true
659+
}

daemon/start_unix.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"path/filepath"
99

1010
"github.com/containerd/containerd/runtime/linux/runctypes"
11+
v2runcoptions "github.com/containerd/containerd/runtime/v2/runc/options"
1112
"github.com/docker/docker/container"
1213
"github.com/docker/docker/errdefs"
1314
"github.com/pkg/errors"
@@ -43,6 +44,20 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain
4344
if err != nil {
4445
return nil, err
4546
}
47+
if daemon.useShimV2() {
48+
opts := &v2runcoptions.Options{
49+
BinaryName: path,
50+
Root: filepath.Join(daemon.configStore.ExecRoot,
51+
fmt.Sprintf("runtime-%s", container.HostConfig.Runtime)),
52+
}
53+
54+
if UsingSystemd(daemon.configStore) {
55+
opts.SystemdCgroup = true
56+
}
57+
58+
return opts, nil
59+
60+
}
4661
opts := &runctypes.RuncOptions{
4762
Runtime: path,
4863
RuntimeRoot: filepath.Join(daemon.configStore.ExecRoot,

libcontainerd/libcontainerd_linux.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ import (
99
)
1010

1111
// NewClient creates a new libcontainerd client from a containerd client
12-
func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend) (libcontainerdtypes.Client, error) {
13-
return remote.NewClient(ctx, cli, stateDir, ns, b)
12+
func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend, useShimV2 bool) (libcontainerdtypes.Client, error) {
13+
return remote.NewClient(ctx, cli, stateDir, ns, b, useShimV2)
1414
}

libcontainerd/libcontainerd_windows.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import (
1111
)
1212

1313
// NewClient creates a new libcontainerd client from a containerd client
14-
func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend) (libcontainerdtypes.Client, error) {
14+
func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend, useShimV2 bool) (libcontainerdtypes.Client, error) {
1515
if !system.ContainerdRuntimeSupported() {
16+
// useShimV2 is ignored for windows
1617
return local.NewClient(ctx, cli, stateDir, ns, b)
1718
}
18-
return remote.NewClient(ctx, cli, stateDir, ns, b)
19+
return remote.NewClient(ctx, cli, stateDir, ns, b, useShimV2)
1920
}

libcontainerd/remote/client.go

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/containerd/containerd/events"
2424
"github.com/containerd/containerd/images"
2525
"github.com/containerd/containerd/runtime/linux/runctypes"
26+
v2runcoptions "github.com/containerd/containerd/runtime/v2/runc/options"
2627
"github.com/containerd/typeurl"
2728
"github.com/docker/docker/errdefs"
2829
"github.com/docker/docker/libcontainerd/queue"
@@ -45,21 +46,27 @@ type client struct {
4546
logger *logrus.Entry
4647
ns string
4748

48-
backend libcontainerdtypes.Backend
49-
eventQ queue.Queue
50-
oomMu sync.Mutex
51-
oom map[string]bool
49+
backend libcontainerdtypes.Backend
50+
eventQ queue.Queue
51+
oomMu sync.Mutex
52+
oom map[string]bool
53+
useShimV2 bool
54+
v2runcoptionsMu sync.Mutex
55+
// v2runcoptions is used for copying options specified on Create() to Start()
56+
v2runcoptions map[string]v2runcoptions.Options
5257
}
5358

5459
// NewClient creates a new libcontainerd client from a containerd client
55-
func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend) (libcontainerdtypes.Client, error) {
60+
func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend, useShimV2 bool) (libcontainerdtypes.Client, error) {
5661
c := &client{
57-
client: cli,
58-
stateDir: stateDir,
59-
logger: logrus.WithField("module", "libcontainerd").WithField("namespace", ns),
60-
ns: ns,
61-
backend: b,
62-
oom: make(map[string]bool),
62+
client: cli,
63+
stateDir: stateDir,
64+
logger: logrus.WithField("module", "libcontainerd").WithField("namespace", ns),
65+
ns: ns,
66+
backend: b,
67+
oom: make(map[string]bool),
68+
useShimV2: useShimV2,
69+
v2runcoptions: make(map[string]v2runcoptions.Options),
6370
}
6471

6572
go c.processEventStream(ctx, ns)
@@ -126,9 +133,13 @@ func (c *client) Create(ctx context.Context, id string, ociSpec *specs.Spec, run
126133
bdir := c.bundleDir(id)
127134
c.logger.WithField("bundle", bdir).WithField("root", ociSpec.Root.Path).Debug("bundle dir created")
128135

136+
rt := runtimeName
137+
if c.useShimV2 {
138+
rt = shimV2RuntimeName
139+
}
129140
newOpts := []containerd.NewContainerOpts{
130141
containerd.WithSpec(ociSpec),
131-
containerd.WithRuntime(runtimeName, runtimeOptions),
142+
containerd.WithRuntime(rt, runtimeOptions),
132143
WithBundle(bdir, ociSpec),
133144
}
134145
opts = append(opts, newOpts...)
@@ -140,6 +151,13 @@ func (c *client) Create(ctx context.Context, id string, ociSpec *specs.Spec, run
140151
}
141152
return wrapError(err)
142153
}
154+
if c.useShimV2 {
155+
if x, ok := runtimeOptions.(*v2runcoptions.Options); ok {
156+
c.v2runcoptionsMu.Lock()
157+
c.v2runcoptions[id] = *x
158+
c.v2runcoptionsMu.Unlock()
159+
}
160+
}
143161
return nil
144162
}
145163

@@ -200,11 +218,26 @@ func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin
200218

201219
if runtime.GOOS != "windows" {
202220
taskOpts = append(taskOpts, func(_ context.Context, _ *containerd.Client, info *containerd.TaskInfo) error {
203-
info.Options = &runctypes.CreateOptions{
204-
IoUid: uint32(uid),
205-
IoGid: uint32(gid),
206-
NoPivotRoot: os.Getenv("DOCKER_RAMDISK") != "",
221+
if c.useShimV2 {
222+
// For v2, we need to inherit options specified on Create
223+
c.v2runcoptionsMu.Lock()
224+
opts, ok := c.v2runcoptions[id]
225+
c.v2runcoptionsMu.Unlock()
226+
if !ok {
227+
opts = v2runcoptions.Options{}
228+
}
229+
opts.IoUid = uint32(uid)
230+
opts.IoGid = uint32(gid)
231+
opts.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
232+
info.Options = &opts
233+
} else {
234+
info.Options = &runctypes.CreateOptions{
235+
IoUid: uint32(uid),
236+
IoGid: uint32(gid),
237+
NoPivotRoot: os.Getenv("DOCKER_RAMDISK") != "",
238+
}
207239
}
240+
208241
return nil
209242
})
210243
} else {
@@ -466,6 +499,9 @@ func (c *client) Delete(ctx context.Context, containerID string) error {
466499
c.oomMu.Lock()
467500
delete(c.oom, containerID)
468501
c.oomMu.Unlock()
502+
c.v2runcoptionsMu.Lock()
503+
delete(c.v2runcoptions, containerID)
504+
c.v2runcoptionsMu.Unlock()
469505
if os.Getenv("LIBCONTAINERD_NOCLEAN") != "1" {
470506
if err := os.RemoveAll(bundle); err != nil {
471507
c.logger.WithError(err).WithFields(logrus.Fields{

libcontainerd/remote/client_linux.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ import (
1616
"github.com/sirupsen/logrus"
1717
)
1818

19-
const runtimeName = "io.containerd.runtime.v1.linux"
19+
const (
20+
runtimeName = "io.containerd.runtime.v1.linux"
21+
shimV2RuntimeName = "io.containerd.runc.v2"
22+
)
2023

2124
func summaryFromInterface(i interface{}) (*libcontainerdtypes.Summary, error) {
2225
return &libcontainerdtypes.Summary{}, nil

libcontainerd/remote/client_windows.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ import (
1616
"github.com/sirupsen/logrus"
1717
)
1818

19-
const runtimeName = "io.containerd.runhcs.v1"
19+
const (
20+
runtimeName = "io.containerd.runhcs.v1"
21+
shimV2RuntimeName = runtimeName
22+
)
2023

2124
func summaryFromInterface(i interface{}) (*libcontainerdtypes.Summary, error) {
2225
switch pd := i.(type) {

plugin/executor/containerd/containerd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ type ExitHandler interface {
2626
}
2727

2828
// New creates a new containerd plugin executor
29-
func New(ctx context.Context, rootDir string, cli *containerd.Client, ns string, exitHandler ExitHandler) (*Executor, error) {
29+
func New(ctx context.Context, rootDir string, cli *containerd.Client, ns string, exitHandler ExitHandler, useShimV2 bool) (*Executor, error) {
3030
e := &Executor{
3131
rootDir: rootDir,
3232
exitHandler: exitHandler,
3333
}
3434

35-
client, err := libcontainerd.NewClient(ctx, cli, rootDir, ns, e)
35+
client, err := libcontainerd.NewClient(ctx, cli, rootDir, ns, e, useShimV2)
3636
if err != nil {
3737
return nil, errors.Wrap(err, "error creating containerd exec client")
3838
}

0 commit comments

Comments
 (0)