Skip to content

Commit af398a1

Browse files
committed
feat(cgroups): add cgroup v2 support with pre-move pattern
Implement cgroup v2 management for urunc containers using a split-policy architecture that separates vCPU (workload) threads from I/O (overhead) threads. Key changes: - Introduce pkg/cgroup/manager.go with a Manager handling cgroup lifecycle - Initialize cgroups during container creation via setupCgroups() in create.go - Move the runtime process to the overhead cgroup before exec - Move vCPU threads to the workload cgroup after a 200ms delay in start.go - Add cgroup configuration support in urunc_config.go - Add unit tests for cgroup manager behavior Signed-off-by: Panos Mavrikos <pmavrikos@nubificus.co.uk>
1 parent 78fd2b4 commit af398a1

8 files changed

Lines changed: 984 additions & 12 deletions

File tree

cmd/urunc/create.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/sirupsen/logrus"
3030
"github.com/urfave/cli/v3"
3131
m "github.com/urunc-dev/urunc/internal/metrics"
32+
"github.com/urunc-dev/urunc/pkg/cgroup"
3233
"github.com/urunc-dev/urunc/pkg/unikontainers"
3334
"golang.org/x/sys/unix"
3435
)
@@ -260,6 +261,16 @@ func createUnikontainer(cmd *cli.Command, uruncCfg *unikontainers.UruncConfig) (
260261
return err
261262
}
262263

264+
// Setup cgroups
265+
err = setupCgroups(cmd, unikontainer, containerPid)
266+
if err != nil {
267+
// Clean up on cgroup creation failure
268+
if unikontainer.CgroupMgr != nil {
269+
_ = unikontainer.CgroupMgr.Delete()
270+
}
271+
return fmt.Errorf("failed to setup cgroups: %w", err)
272+
}
273+
263274
// execute CreateRuntime hooks
264275
err = unikontainer.ExecuteHooks("CreateRuntime")
265276
if err != nil {
@@ -279,6 +290,51 @@ func createUnikontainer(cmd *cli.Command, uruncCfg *unikontainers.UruncConfig) (
279290
return err
280291
}
281292

293+
// setupCgroups creates and configures cgroups for the container
294+
func setupCgroups(cmd *cli.Command, u *unikontainers.Unikontainer, pid int) error {
295+
// Check if cgroups are disabled
296+
if u.Spec.Linux == nil || u.Spec.Linux.CgroupsPath == "" {
297+
logrus.Debug("Cgroups disabled or no cgroup path specified")
298+
return nil
299+
}
300+
301+
// Check if systemd cgroup driver is enabled
302+
useSystemd := cmd.Bool("systemd-cgroup")
303+
304+
// Create cgroup manager config
305+
cgroupCfg := cgroup.Config{
306+
CgroupPath: u.Spec.Linux.CgroupsPath,
307+
ContainerID: u.State.ID,
308+
Resources: u.Spec.Linux.Resources,
309+
SandboxCgroupOnly: u.UruncCfg.Cgroup.SandboxCgroupOnly,
310+
OverheadPath: u.UruncCfg.Cgroup.OverheadPath,
311+
UseSystemd: useSystemd,
312+
}
313+
314+
// Create cgroup manager
315+
cgroupMgr, err := cgroup.NewManager(cgroupCfg)
316+
if err != nil {
317+
return fmt.Errorf("failed to create cgroup manager: %w", err)
318+
}
319+
320+
// Create cgroups and add reexec process
321+
if err := cgroupMgr.Create(context.Background(), u.Spec.Linux.Resources, pid, useSystemd); err != nil {
322+
return fmt.Errorf("failed to create cgroups: %w", err)
323+
}
324+
325+
// Store manager in unikontainer
326+
u.CgroupMgr = cgroupMgr
327+
328+
logrus.WithFields(logrus.Fields{
329+
"cgroup_path": u.Spec.Linux.CgroupsPath,
330+
"sandbox_cgroup_only": u.UruncCfg.Cgroup.SandboxCgroupOnly,
331+
"use_systemd": useSystemd,
332+
"pid": pid,
333+
}).Info("Cgroups created successfully")
334+
335+
return nil
336+
}
337+
282338
func createReexecCmd(initSock *os.File, logPipe *os.File) *exec.Cmd {
283339
selfPath := "/proc/self/exe"
284340
reexecCommand := &exec.Cmd{

cmd/urunc/start.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"errors"
2020
"fmt"
2121
"os"
22+
"time"
2223

2324
"github.com/sirupsen/logrus"
2425
"github.com/urfave/cli/v3"
@@ -111,5 +112,16 @@ func startUnikontainer(cmd *cli.Command) error {
111112
return err
112113
}
113114

115+
if unikontainer.CgroupMgr != nil && unikontainer.CgroupMgr.UsingSplitPolicy() {
116+
vmmPid := unikontainer.State.Pid
117+
time.Sleep(200 * time.Millisecond)
118+
119+
if err := unikontainer.CgroupMgr.MoveVCPUThreads(vmmPid); err != nil {
120+
logrus.WithError(err).Warn("Failed to move vCPU threads to sandbox cgroup")
121+
} else {
122+
logrus.Info("Successfully moved vCPU threads to sandbox cgroup")
123+
}
124+
}
125+
114126
return unikontainer.ExecuteHooks("Poststart")
115127
}

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ require (
3333
github.com/Microsoft/go-winio v0.6.2 // indirect
3434
github.com/Microsoft/hcsshim v0.13.0 // indirect
3535
github.com/cilium/ebpf v0.20.0 // indirect
36-
github.com/containerd/cgroups/v3 v3.1.0 // indirect
3736
github.com/containerd/console v1.0.5 // indirect
3837
github.com/containerd/containerd/api v1.10.0 // indirect
3938
github.com/containerd/continuity v0.4.5 // indirect

0 commit comments

Comments
 (0)