Skip to content

Commit ec0b722

Browse files
authored
Merge pull request containerd#3292 from crosbymichael/shim-cgroup
Add shim cgroup support for v2 runtimes
2 parents b7f093e + fe6a2b0 commit ec0b722

File tree

7 files changed

+102
-13
lines changed

7 files changed

+102
-13
lines changed

container_linux_test.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,6 @@ func TestShimInCgroup(t *testing.T) {
133133
t.Fatal(err)
134134
}
135135
defer client.Close()
136-
if CheckRuntime(client.runtime, "io.containerd.runc") {
137-
t.Skip()
138-
}
139-
140136
var (
141137
ctx, cancel = testContext()
142138
id = t.Name()
@@ -160,12 +156,7 @@ func TestShimInCgroup(t *testing.T) {
160156
}
161157
defer cg.Delete()
162158

163-
task, err := container.NewTask(ctx, empty(), func(_ context.Context, client *Client, r *TaskInfo) error {
164-
r.Options = &runctypes.CreateOptions{
165-
ShimCgroup: path,
166-
}
167-
return nil
168-
})
159+
task, err := container.NewTask(ctx, empty(), WithShimCgroup(path))
169160
if err != nil {
170161
t.Fatal(err)
171162
}

runtime/v2/binary.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
client "github.com/containerd/containerd/runtime/v2/shim"
3131
"github.com/containerd/containerd/runtime/v2/task"
3232
"github.com/containerd/ttrpc"
33+
"github.com/gogo/protobuf/types"
3334
"github.com/pkg/errors"
3435
"github.com/sirupsen/logrus"
3536
)
@@ -52,7 +53,7 @@ type binary struct {
5253
rtTasks *runtime.TaskList
5354
}
5455

55-
func (b *binary) Start(ctx context.Context, onClose func()) (_ *shim, err error) {
56+
func (b *binary) Start(ctx context.Context, opts *types.Any, onClose func()) (_ *shim, err error) {
5657
args := []string{"-id", b.bundle.ID}
5758
if logrus.GetLevel() == logrus.DebugLevel {
5859
args = append(args, "-debug")
@@ -64,6 +65,7 @@ func (b *binary) Start(ctx context.Context, onClose func()) (_ *shim, err error)
6465
b.runtime,
6566
b.containerdAddress,
6667
b.bundle.Path,
68+
opts,
6769
args...,
6870
)
6971
if err != nil {
@@ -126,6 +128,7 @@ func (b *binary) Delete(ctx context.Context) (*runtime.Exit, error) {
126128
b.runtime,
127129
b.containerdAddress,
128130
bundlePath,
131+
nil,
129132
"-id", b.bundle.ID,
130133
"-bundle", b.bundle.Path,
131134
"delete")

runtime/v2/manager.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,13 @@ func (m *TaskManager) Create(ctx context.Context, id string, opts runtime.Create
126126
bundle.Delete()
127127
}
128128
}()
129+
topts := opts.TaskOptions
130+
if topts == nil {
131+
topts = opts.RuntimeOptions
132+
}
133+
129134
b := shimBinary(ctx, bundle, opts.Runtime, m.containerdAddress, m.events, m.tasks)
130-
shim, err := b.Start(ctx, func() {
135+
shim, err := b.Start(ctx, topts, func() {
131136
log.G(ctx).WithField("id", id).Info("shim disconnected")
132137
_, err := m.tasks.Get(ctx, id)
133138
if err != nil {

runtime/v2/runc/v1/service.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ import (
4444
taskAPI "github.com/containerd/containerd/runtime/v2/task"
4545
runcC "github.com/containerd/go-runc"
4646
"github.com/containerd/typeurl"
47+
"github.com/gogo/protobuf/proto"
48+
"github.com/gogo/protobuf/types"
4749
ptypes "github.com/gogo/protobuf/types"
4850
specs "github.com/opencontainers/runtime-spec/specs-go"
4951
"github.com/pkg/errors"
@@ -163,6 +165,31 @@ func (s *service) StartShim(ctx context.Context, id, containerdBinary, container
163165
if err := shim.WriteAddress("address", address); err != nil {
164166
return "", err
165167
}
168+
if data, err := ioutil.ReadAll(os.Stdin); err == nil {
169+
if len(data) > 0 {
170+
var any types.Any
171+
if err := proto.Unmarshal(data, &any); err != nil {
172+
return "", err
173+
}
174+
v, err := typeurl.UnmarshalAny(&any)
175+
if err != nil {
176+
return "", err
177+
}
178+
if opts, ok := v.(*options.Options); ok {
179+
if opts.ShimCgroup != "" {
180+
cg, err := cgroups.Load(cgroups.V1, cgroups.StaticPath(opts.ShimCgroup))
181+
if err != nil {
182+
return "", errors.Wrapf(err, "failed to load cgroup %s", opts.ShimCgroup)
183+
}
184+
if err := cg.Add(cgroups.Process{
185+
Pid: cmd.Process.Pid,
186+
}); err != nil {
187+
return "", errors.Wrapf(err, "failed to join cgroup %s", opts.ShimCgroup)
188+
}
189+
}
190+
}
191+
}
192+
}
166193
if err := shim.SetScore(cmd.Process.Pid); err != nil {
167194
return "", errors.Wrap(err, "failed to set OOM Score on shim")
168195
}

runtime/v2/runc/v2/service.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ import (
4545
taskAPI "github.com/containerd/containerd/runtime/v2/task"
4646
runcC "github.com/containerd/go-runc"
4747
"github.com/containerd/typeurl"
48+
"github.com/gogo/protobuf/proto"
49+
"github.com/gogo/protobuf/types"
4850
ptypes "github.com/gogo/protobuf/types"
4951
specs "github.com/opencontainers/runtime-spec/specs-go"
5052
"github.com/pkg/errors"
@@ -206,6 +208,31 @@ func (s *service) StartShim(ctx context.Context, id, containerdBinary, container
206208
if err := shim.WriteAddress("address", address); err != nil {
207209
return "", err
208210
}
211+
if data, err := ioutil.ReadAll(os.Stdin); err == nil {
212+
if len(data) > 0 {
213+
var any types.Any
214+
if err := proto.Unmarshal(data, &any); err != nil {
215+
return "", err
216+
}
217+
v, err := typeurl.UnmarshalAny(&any)
218+
if err != nil {
219+
return "", err
220+
}
221+
if opts, ok := v.(*options.Options); ok {
222+
if opts.ShimCgroup != "" {
223+
cg, err := cgroups.Load(cgroups.V1, cgroups.StaticPath(opts.ShimCgroup))
224+
if err != nil {
225+
return "", errors.Wrapf(err, "failed to load cgroup %s", opts.ShimCgroup)
226+
}
227+
if err := cg.Add(cgroups.Process{
228+
Pid: cmd.Process.Pid,
229+
}); err != nil {
230+
return "", errors.Wrapf(err, "failed to join cgroup %s", opts.ShimCgroup)
231+
}
232+
}
233+
}
234+
}
235+
}
209236
if err := shim.SetScore(cmd.Process.Pid); err != nil {
210237
return "", errors.Wrap(err, "failed to set OOM Score on shim")
211238
}

runtime/v2/shim/util.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package shim
1818

1919
import (
20+
"bytes"
2021
"context"
2122
"fmt"
2223
"io/ioutil"
@@ -29,13 +30,15 @@ import (
2930
"time"
3031

3132
"github.com/containerd/containerd/namespaces"
33+
"github.com/gogo/protobuf/proto"
34+
"github.com/gogo/protobuf/types"
3235
"github.com/pkg/errors"
3336
)
3437

3538
var runtimePaths sync.Map
3639

3740
// Command returns the shim command with the provided args and configuration
38-
func Command(ctx context.Context, runtime, containerdAddress, path string, cmdArgs ...string) (*exec.Cmd, error) {
41+
func Command(ctx context.Context, runtime, containerdAddress, path string, opts *types.Any, cmdArgs ...string) (*exec.Cmd, error) {
3942
ns, err := namespaces.NamespaceRequired(ctx)
4043
if err != nil {
4144
return nil, err
@@ -94,6 +97,13 @@ func Command(ctx context.Context, runtime, containerdAddress, path string, cmdAr
9497
cmd.Dir = path
9598
cmd.Env = append(os.Environ(), "GOMAXPROCS=2")
9699
cmd.SysProcAttr = getSysProcAttr()
100+
if opts != nil {
101+
d, err := proto.Marshal(opts)
102+
if err != nil {
103+
return nil, err
104+
}
105+
cmd.Stdin = bytes.NewReader(d)
106+
}
97107
return cmd, nil
98108
}
99109

task_opts_unix.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,29 @@ func WithNoPivotRoot(_ context.Context, _ *Client, ti *TaskInfo) error {
7777
}
7878
return nil
7979
}
80+
81+
// WithShimCgroup sets the existing cgroup for the shim
82+
func WithShimCgroup(path string) NewTaskOpts {
83+
return func(ctx context.Context, c *Client, ti *TaskInfo) error {
84+
if CheckRuntime(ti.Runtime(), "io.containerd.runc") {
85+
if ti.Options == nil {
86+
ti.Options = &options.Options{}
87+
}
88+
opts, ok := ti.Options.(*options.Options)
89+
if !ok {
90+
return errors.New("invalid v2 shim create options format")
91+
}
92+
opts.ShimCgroup = path
93+
} else {
94+
if ti.Options == nil {
95+
ti.Options = &runctypes.CreateOptions{}
96+
}
97+
opts, ok := ti.Options.(*runctypes.CreateOptions)
98+
if !ok {
99+
return errors.New("could not cast TaskInfo Options to CreateOptions")
100+
}
101+
opts.ShimCgroup = path
102+
}
103+
return nil
104+
}
105+
}

0 commit comments

Comments
 (0)