From d7864eb77bb0609133432b8c8ffc34ff4bbb894e Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Mon, 9 Oct 2017 15:37:19 -0400 Subject: [PATCH] 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 --- benchmark_test.go | 6 ++++-- cmd/containerd-stress/main.go | 11 +++++++---- docs/getting-started.md | 9 +-------- spec.go | 2 +- spec_opts.go | 2 +- spec_unix.go | 10 ++++++++-- spec_unix_test.go | 12 +++++++++--- spec_windows.go | 8 ++++++-- 8 files changed, 37 insertions(+), 23 deletions(-) diff --git a/benchmark_test.go b/benchmark_test.go index 844bed2fc..e2d81ed8a 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -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 diff --git a/cmd/containerd-stress/main.go b/cmd/containerd-stress/main.go index a62c03285..b76dbc79b 100644 --- a/cmd/containerd-stress/main.go +++ b/cmd/containerd-stress/main.go @@ -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 { diff --git a/docs/getting-started.md b/docs/getting-started.md index be48f3bdf..c80ef1237 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -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 diff --git a/spec.go b/spec.go index fc1201467..850f470a0 100644 --- a/spec.go +++ b/spec.go @@ -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 } diff --git a/spec_opts.go b/spec_opts.go index e3edecbe9..2dbf8214a 100644 --- a/spec_opts.go +++ b/spec_opts.go @@ -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 } diff --git a/spec_unix.go b/spec_unix.go index 36f9b2d77..9a0b537dc 100644 --- a/spec_unix.go +++ b/spec_unix.go @@ -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{ { diff --git a/spec_unix_test.go b/spec_unix_test.go index 402c53f25..053831658 100644 --- a/spec_unix_test.go +++ b/spec_unix_test.go @@ -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) } diff --git a/spec_windows.go b/spec_windows.go index 8fa1305c9..16a58b446 100644 --- a/spec_windows.go +++ b/spec_windows.go @@ -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{},