diff --git a/cmd/cri-containerd/options/options.go b/cmd/cri-containerd/options/options.go index 4c58d5577..1e3efb045 100644 --- a/cmd/cri-containerd/options/options.go +++ b/cmd/cri-containerd/options/options.go @@ -70,6 +70,8 @@ type Config struct { SandboxImage string `toml:"sandbox_image"` // StatsCollectPeriod is the period (in seconds) of snapshots stats collection. StatsCollectPeriod int `toml:"stats_collect_period"` + // SystemdCgroup enables systemd cgroup support. + SystemdCgroup bool `toml:"systemd_cgroup"` } // CRIContainerdOptions contains cri-containerd command line and toml options. @@ -122,6 +124,8 @@ func (c *CRIContainerdOptions) AddFlags(fs *pflag.FlagSet) { "gcr.io/google_containers/pause:3.0", "The image used by sandbox container.") fs.IntVar(&c.StatsCollectPeriod, "stats-collect-period", 10, "The period (in seconds) of snapshots stats collection.") + fs.BoolVar(&c.SystemdCgroup, "systemd-cgroup", + false, "Enables systemd cgroup support.") fs.BoolVar(&c.PrintDefaultConfig, "default-config", false, "Print default toml config of cri-containerd and quit.") } diff --git a/pkg/server/container_create.go b/pkg/server/container_create.go index 2ed7e1906..064685407 100644 --- a/pkg/server/container_create.go +++ b/pkg/server/container_create.go @@ -26,6 +26,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/contrib/apparmor" "github.com/containerd/containerd/contrib/seccomp" + "github.com/containerd/containerd/linux/runcopts" "github.com/containerd/typeurl" "github.com/docker/docker/pkg/mount" "github.com/golang/glog" @@ -221,7 +222,10 @@ func (c *criContainerdService) CreateContainer(ctx context.Context, r *runtime.C opts = append(opts, containerd.WithSpec(spec, specOpts...), - containerd.WithRuntime(defaultRuntime, nil), + containerd.WithRuntime( + defaultRuntime, + &runcopts.RuncOptions{SystemdCgroup: c.config.SystemdCgroup}, + ), containerd.WithContainerLabels(map[string]string{containerKindLabel: containerKindContainer}), containerd.WithContainerExtension(containerMetadataExtension, &meta)) var cntr containerd.Container @@ -344,7 +348,8 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3 setOCILinuxResource(&g, config.GetLinux().GetResources()) if sandboxConfig.GetLinux().GetCgroupParent() != "" { - cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id) + cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id, + c.config.SystemdCgroup) g.SetLinuxCgroupsPath(cgroupsPath) } diff --git a/pkg/server/container_create_test.go b/pkg/server/container_create_test.go index 499472e3a..483b0e1a1 100644 --- a/pkg/server/container_create_test.go +++ b/pkg/server/container_create_test.go @@ -149,7 +149,7 @@ func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandbox assert.Equal(t, spec.Process.NoNewPrivileges, true) t.Logf("Check cgroup path") - assert.Equal(t, getCgroupsPath("/test/cgroup/parent", id), spec.Linux.CgroupsPath) + assert.Equal(t, getCgroupsPath("/test/cgroup/parent", id, false), spec.Linux.CgroupsPath) t.Logf("Check namespaces") assert.Contains(t, spec.Linux.Namespaces, runtimespec.LinuxNamespace{ diff --git a/pkg/server/helpers.go b/pkg/server/helpers.go index 64ed8fec4..3ee8ce465 100644 --- a/pkg/server/helpers.go +++ b/pkg/server/helpers.go @@ -20,6 +20,7 @@ import ( "encoding/json" "fmt" "os" + "path" "path/filepath" "strconv" "strings" @@ -134,8 +135,13 @@ func makeContainerName(c *runtime.ContainerMetadata, s *runtime.PodSandboxMetada } // getCgroupsPath generates container cgroups path. -func getCgroupsPath(cgroupsParent string, id string) string { - // TODO(random-liu): [P0] Handle systemd. +func getCgroupsPath(cgroupsParent, id string, systemdCgroup bool) string { + if systemdCgroup { + // Convert a.slice/b.slice/c.slice to c.slice. + p := path.Base(cgroupsParent) + // runc systemd cgroup path format is "slice:prefix:name". + return strings.Join([]string{p, "cri-containerd", id}, ":") + } return filepath.Join(cgroupsParent, id) } diff --git a/pkg/server/helpers_test.go b/pkg/server/helpers_test.go index 40302f105..2fa5aaf92 100644 --- a/pkg/server/helpers_test.go +++ b/pkg/server/helpers_test.go @@ -161,3 +161,27 @@ func TestGetRepoDigestAndTag(t *testing.T) { assert.Equal(t, test.expectedRepoTag, repoTag) } } + +func TestGetCgroupsPath(t *testing.T) { + testID := "test-id" + for desc, test := range map[string]struct { + cgroupsParent string + systemdCgroup bool + expected string + }{ + "should support regular cgroup path": { + cgroupsParent: "/a/b", + systemdCgroup: false, + expected: "/a/b/test-id", + }, + "should support systemd cgroup path": { + cgroupsParent: "/a.slice/b.slice", + systemdCgroup: true, + expected: "b.slice:cri-containerd:test-id", + }, + } { + t.Logf("TestCase %q", desc) + got := getCgroupsPath(test.cgroupsParent, testID, test.systemdCgroup) + assert.Equal(t, test.expected, got) + } +} diff --git a/pkg/server/sandbox_run.go b/pkg/server/sandbox_run.go index 8789f4bbd..6a4babafc 100644 --- a/pkg/server/sandbox_run.go +++ b/pkg/server/sandbox_run.go @@ -22,6 +22,7 @@ import ( "strings" "github.com/containerd/containerd" + "github.com/containerd/containerd/linux/runcopts" "github.com/containerd/typeurl" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/golang/glog" @@ -146,7 +147,11 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run containerd.WithSpec(spec, specOpts...), containerd.WithContainerLabels(map[string]string{containerKindLabel: containerKindSandbox}), containerd.WithContainerExtension(sandboxMetadataExtension, &sandbox.Metadata), - containerd.WithRuntime(defaultRuntime, nil)} + containerd.WithRuntime( + defaultRuntime, + &runcopts.RuncOptions{SystemdCgroup: c.config.SystemdCgroup}, + ), + } container, err := c.client.NewContainer(ctx, id, opts...) if err != nil { return nil, fmt.Errorf("failed to create containerd container: %v", err) @@ -258,7 +263,8 @@ func (c *criContainerdService) generateSandboxContainerSpec(id string, config *r // Set cgroups parent. if config.GetLinux().GetCgroupParent() != "" { - cgroupsPath := getCgroupsPath(config.GetLinux().GetCgroupParent(), id) + cgroupsPath := getCgroupsPath(config.GetLinux().GetCgroupParent(), id, + c.config.SystemdCgroup) g.SetLinuxCgroupsPath(cgroupsPath) } // When cgroup parent is not set, containerd-shim will create container in a child cgroup diff --git a/pkg/server/sandbox_run_test.go b/pkg/server/sandbox_run_test.go index 2d53d1772..90f907c77 100644 --- a/pkg/server/sandbox_run_test.go +++ b/pkg/server/sandbox_run_test.go @@ -56,7 +56,7 @@ func getRunPodSandboxTestData() (*runtime.PodSandboxConfig, *imagespec.ImageConf } specCheck := func(t *testing.T, id string, spec *runtimespec.Spec) { assert.Equal(t, "test-hostname", spec.Hostname) - assert.Equal(t, getCgroupsPath("/test/cgroup/parent", id), spec.Linux.CgroupsPath) + assert.Equal(t, getCgroupsPath("/test/cgroup/parent", id, false), spec.Linux.CgroupsPath) assert.Equal(t, relativeRootfsPath, spec.Root.Path) assert.Equal(t, true, spec.Root.Readonly) assert.Contains(t, spec.Process.Env, "a=b", "c=d")