Use namespace in default cgroup path

By default, the generated spec will place containers in cgroups by their
ids, we need to use the namespace as the cgroup root to avoid
containers with the same name being placed in the same cgroup.

```
11:perf_event:/to/redis
10:freezer:/to/redis
9:memory:/to/redis
8:devices:/to/redis
7:net_cls,net_prio:/to/redis
6:pids:/to/redis
5:hugetlb:/to/redis
4:cpuset:/to/redis
3:blkio:/to/redis
2:cpu,cpuacct:/to/redis
1:name=systemd:/to/redis

11:perf_event:/te/redis
10:freezer:/te/redis
9:memory:/te/redis
8:devices:/te/redis
7:net_cls,net_prio:/te/redis
6:pids:/te/redis
5:hugetlb:/te/redis
4:cpuset:/te/redis
3:blkio:/te/redis
2:cpu,cpuacct:/te/redis
1:name=systemd:/te/redis
```

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2017-10-09 15:37:19 -04:00
parent 72bb45ac46
commit d7864eb77b
8 changed files with 37 additions and 23 deletions

View File

@ -3,6 +3,8 @@ package containerd
import (
"fmt"
"testing"
"github.com/containerd/containerd/containers"
)
func BenchmarkContainerCreate(b *testing.B) {
@ -20,7 +22,7 @@ func BenchmarkContainerCreate(b *testing.B) {
b.Error(err)
return
}
spec, err := GenerateSpec(ctx, client, nil, WithImageConfig(image), withTrue())
spec, err := GenerateSpec(ctx, client, &containers.Container{ID: b.Name()}, WithImageConfig(image), withTrue())
if err != nil {
b.Error(err)
return
@ -63,7 +65,7 @@ func BenchmarkContainerStart(b *testing.B) {
b.Error(err)
return
}
spec, err := GenerateSpec(ctx, client, nil, WithImageConfig(image), withTrue())
spec, err := GenerateSpec(ctx, client, &containers.Container{ID: b.Name()}, WithImageConfig(image), withTrue())
if err != nil {
b.Error(err)
return

View File

@ -5,6 +5,7 @@ import (
"fmt"
"os"
"os/signal"
"path/filepath"
"runtime"
"strings"
"sync"
@ -12,6 +13,7 @@ import (
"time"
"github.com/containerd/containerd"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/namespaces"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
@ -98,7 +100,7 @@ func test(c config) error {
return err
}
logrus.Info("generating spec from image")
spec, err := containerd.GenerateSpec(ctx, client, nil, containerd.WithImageConfig(image), containerd.WithProcessArgs("true"))
spec, err := containerd.GenerateSpec(ctx, client, &containers.Container{ID: ""}, containerd.WithImageConfig(image), containerd.WithProcessArgs("true"))
if err != nil {
return err
}
@ -120,7 +122,7 @@ func test(c config) error {
w := &worker{
id: i,
wg: &wg,
spec: spec,
spec: *spec,
image: image,
client: client,
}
@ -158,7 +160,7 @@ type worker struct {
client *containerd.Client
image containerd.Image
spec *specs.Spec
spec specs.Spec
}
func (w *worker) run(ctx, tctx context.Context) {
@ -194,8 +196,9 @@ func (w *worker) run(ctx, tctx context.Context) {
}
func (w *worker) runContainer(ctx context.Context, id string) error {
w.spec.Linux.CgroupsPath = filepath.Join("/", fmt.Sprint(w.id), id)
c, err := w.client.NewContainer(ctx, id,
containerd.WithSpec(w.spec),
containerd.WithSpec(&w.spec),
containerd.WithNewSnapshot(id, w.image),
)
if err != nil {

View File

@ -196,18 +196,11 @@ func redisExample() error {
}
log.Printf("Successfully pulled %s image\n", image.Name())
spec, err := containerd.GenerateSpec(ctx, client, nil, containerd.WithImageConfig(image))
if err != nil {
return err
}
log.Printf("Successfully generate an OCI spec version %s based on %s image", spec.Version, image.Name())
container, err := client.NewContainer(
ctx,
"redis-server",
containerd.WithSpec(spec),
containerd.WithImage(image),
containerd.WithNewSnapshot("redis-server-snapshot", image),
containerd.WithNewSpec(containerd.WithImageConfig(image)),
)
if err != nil {
return err

View File

@ -10,7 +10,7 @@ import (
// GenerateSpec will generate a default spec from the provided image
// for use as a containerd container
func GenerateSpec(ctx context.Context, client *Client, c *containers.Container, opts ...SpecOpts) (*specs.Spec, error) {
s, err := createDefaultSpec()
s, err := createDefaultSpec(ctx, c.ID)
if err != nil {
return nil, err
}

View File

@ -38,7 +38,7 @@ func WithHostname(name string) SpecOpts {
// WithNewSpec generates a new spec for a new container
func WithNewSpec(opts ...SpecOpts) NewContainerOpts {
return func(ctx context.Context, client *Client, c *containers.Container) error {
s, err := createDefaultSpec()
s, err := createDefaultSpec(ctx, c.ID)
if err != nil {
return err
}

View File

@ -3,6 +3,7 @@
package containerd
import (
"context"
"io/ioutil"
"os"
"path/filepath"
@ -11,6 +12,7 @@ import (
"golang.org/x/sys/unix"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces"
specs "github.com/opencontainers/runtime-spec/specs-go"
)
@ -64,7 +66,11 @@ func defaultNamespaces() []specs.LinuxNamespace {
}
}
func createDefaultSpec() (*specs.Spec, error) {
func createDefaultSpec(ctx context.Context, id string) (*specs.Spec, error) {
ns, err := namespaces.NamespaceRequired(ctx)
if err != nil {
return nil, err
}
s := &specs.Spec{
Version: specs.Version,
Root: &specs.Root{
@ -154,7 +160,7 @@ func createDefaultSpec() (*specs.Spec, error) {
"/proc/sys",
"/proc/sysrq-trigger",
},
// TODO (@crosbymichael) make sure we don't have have two containers in the same cgroup
CgroupsPath: filepath.Join("/", ns, id),
Resources: &specs.LinuxResources{
Devices: []specs.LinuxDeviceCgroup{
{

View File

@ -6,13 +6,16 @@ import (
"context"
"testing"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/namespaces"
specs "github.com/opencontainers/runtime-spec/specs-go"
)
func TestGenerateSpec(t *testing.T) {
t.Parallel()
s, err := GenerateSpec(context.Background(), nil, nil)
ctx := namespaces.WithNamespace(context.Background(), "testing")
s, err := GenerateSpec(ctx, nil, &containers.Container{ID: t.Name()})
if err != nil {
t.Fatal(err)
}
@ -52,7 +55,8 @@ func TestGenerateSpec(t *testing.T) {
func TestSpecWithTTY(t *testing.T) {
t.Parallel()
s, err := GenerateSpec(context.Background(), nil, nil, WithTTY)
ctx := namespaces.WithNamespace(context.Background(), "testing")
s, err := GenerateSpec(ctx, nil, &containers.Container{ID: t.Name()}, WithTTY)
if err != nil {
t.Fatal(err)
}
@ -68,8 +72,10 @@ func TestSpecWithTTY(t *testing.T) {
func TestWithLinuxNamespace(t *testing.T) {
t.Parallel()
ctx := namespaces.WithNamespace(context.Background(), "testing")
replacedNS := specs.LinuxNamespace{Type: specs.NetworkNamespace, Path: "/var/run/netns/test"}
s, err := GenerateSpec(context.Background(), nil, nil, WithLinuxNamespace(replacedNS))
s, err := GenerateSpec(ctx, nil, &containers.Container{ID: t.Name()}, WithLinuxNamespace(replacedNS))
if err != nil {
t.Fatal(err)
}

View File

@ -1,8 +1,12 @@
package containerd
import specs "github.com/opencontainers/runtime-spec/specs-go"
import (
"context"
func createDefaultSpec() (*specs.Spec, error) {
specs "github.com/opencontainers/runtime-spec/specs-go"
)
func createDefaultSpec(ctx context.Context, id string) (*specs.Spec, error) {
return &specs.Spec{
Version: specs.Version,
Root: &specs.Root{},