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:
parent
72bb45ac46
commit
d7864eb77b
@ -3,6 +3,8 @@ package containerd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkContainerCreate(b *testing.B) {
|
func BenchmarkContainerCreate(b *testing.B) {
|
||||||
@ -20,7 +22,7 @@ func BenchmarkContainerCreate(b *testing.B) {
|
|||||||
b.Error(err)
|
b.Error(err)
|
||||||
return
|
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 {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
return
|
return
|
||||||
@ -63,7 +65,7 @@ func BenchmarkContainerStart(b *testing.B) {
|
|||||||
b.Error(err)
|
b.Error(err)
|
||||||
return
|
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 {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -98,7 +100,7 @@ func test(c config) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logrus.Info("generating spec from image")
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -120,7 +122,7 @@ func test(c config) error {
|
|||||||
w := &worker{
|
w := &worker{
|
||||||
id: i,
|
id: i,
|
||||||
wg: &wg,
|
wg: &wg,
|
||||||
spec: spec,
|
spec: *spec,
|
||||||
image: image,
|
image: image,
|
||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
@ -158,7 +160,7 @@ type worker struct {
|
|||||||
|
|
||||||
client *containerd.Client
|
client *containerd.Client
|
||||||
image containerd.Image
|
image containerd.Image
|
||||||
spec *specs.Spec
|
spec specs.Spec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) run(ctx, tctx context.Context) {
|
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 {
|
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,
|
c, err := w.client.NewContainer(ctx, id,
|
||||||
containerd.WithSpec(w.spec),
|
containerd.WithSpec(&w.spec),
|
||||||
containerd.WithNewSnapshot(id, w.image),
|
containerd.WithNewSnapshot(id, w.image),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -196,18 +196,11 @@ func redisExample() error {
|
|||||||
}
|
}
|
||||||
log.Printf("Successfully pulled %s image\n", image.Name())
|
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(
|
container, err := client.NewContainer(
|
||||||
ctx,
|
ctx,
|
||||||
"redis-server",
|
"redis-server",
|
||||||
containerd.WithSpec(spec),
|
|
||||||
containerd.WithImage(image),
|
|
||||||
containerd.WithNewSnapshot("redis-server-snapshot", image),
|
containerd.WithNewSnapshot("redis-server-snapshot", image),
|
||||||
|
containerd.WithNewSpec(containerd.WithImageConfig(image)),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
2
spec.go
2
spec.go
@ -10,7 +10,7 @@ import (
|
|||||||
// GenerateSpec will generate a default spec from the provided image
|
// GenerateSpec will generate a default spec from the provided image
|
||||||
// for use as a containerd container
|
// for use as a containerd container
|
||||||
func GenerateSpec(ctx context.Context, client *Client, c *containers.Container, opts ...SpecOpts) (*specs.Spec, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func WithHostname(name string) SpecOpts {
|
|||||||
// WithNewSpec generates a new spec for a new container
|
// WithNewSpec generates a new spec for a new container
|
||||||
func WithNewSpec(opts ...SpecOpts) NewContainerOpts {
|
func WithNewSpec(opts ...SpecOpts) NewContainerOpts {
|
||||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||||
s, err := createDefaultSpec()
|
s, err := createDefaultSpec(ctx, c.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
10
spec_unix.go
10
spec_unix.go
@ -3,6 +3,7 @@
|
|||||||
package containerd
|
package containerd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -11,6 +12,7 @@ import (
|
|||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
|
"github.com/containerd/containerd/namespaces"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
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{
|
s := &specs.Spec{
|
||||||
Version: specs.Version,
|
Version: specs.Version,
|
||||||
Root: &specs.Root{
|
Root: &specs.Root{
|
||||||
@ -154,7 +160,7 @@ func createDefaultSpec() (*specs.Spec, error) {
|
|||||||
"/proc/sys",
|
"/proc/sys",
|
||||||
"/proc/sysrq-trigger",
|
"/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{
|
Resources: &specs.LinuxResources{
|
||||||
Devices: []specs.LinuxDeviceCgroup{
|
Devices: []specs.LinuxDeviceCgroup{
|
||||||
{
|
{
|
||||||
|
@ -6,13 +6,16 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/namespaces"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGenerateSpec(t *testing.T) {
|
func TestGenerateSpec(t *testing.T) {
|
||||||
t.Parallel()
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -52,7 +55,8 @@ func TestGenerateSpec(t *testing.T) {
|
|||||||
func TestSpecWithTTY(t *testing.T) {
|
func TestSpecWithTTY(t *testing.T) {
|
||||||
t.Parallel()
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -68,8 +72,10 @@ func TestSpecWithTTY(t *testing.T) {
|
|||||||
func TestWithLinuxNamespace(t *testing.T) {
|
func TestWithLinuxNamespace(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
ctx := namespaces.WithNamespace(context.Background(), "testing")
|
||||||
replacedNS := specs.LinuxNamespace{Type: specs.NetworkNamespace, Path: "/var/run/netns/test"}
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
package containerd
|
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{
|
return &specs.Spec{
|
||||||
Version: specs.Version,
|
Version: specs.Version,
|
||||||
Root: &specs.Root{},
|
Root: &specs.Root{},
|
||||||
|
Loading…
Reference in New Issue
Block a user