Skip to content

Commit

Permalink
feat: implement cgroups v2
Browse files Browse the repository at this point in the history
  • Loading branch information
nixpig committed Dec 27, 2024
1 parent 9d9d69b commit f09e0fb
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 27 deletions.
14 changes: 3 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ This is a personal project for me to explore and better understand the OCI Runti
**🗒️ To do** (items remaining for _me_ to consider this 'complete')

- [ ] ~Unit tests~ Integration tests seem to be sufficing
- [ ] Implement [Cgroups v2](https://github.com/opencontainers/runtime-spec/blob/main/config-linux.md#control-groups)
- [ ] Implement optional [Seccomp](https://github.com/opencontainers/runtime-spec/blob/main/config-linux.md#seccomp)
- [ ] Implement optional [AppArmor](https://github.com/opencontainers/runtime-spec/blob/main/config.md#linux-process)
- [ ] Refactor and tidy-up
Expand Down Expand Up @@ -57,13 +56,6 @@ You can spin up this VM from the included `Vagrantfile`, just run `vagrant up`.

## Usage

> [!NOTE]
>
> Some jiggery-pokery is required for cgroups to work. Needs further investigation.
>
> $ sudo mkdir /sys/fs/cgroup/systemd
> $ sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd
### Docker

By default, the Docker daemon uses the `runc` container runtime. `brownie` can be used as a drop-in replacement for `runc`.
Expand Down Expand Up @@ -238,11 +230,11 @@ Tests are run on every build in [this Github Action](https://github.com/nixpig/b

#### cgroups v1 & v2 support

The OCI Runtime Spec test suite provided by opencontainers _does_ support cgroup v1.

The OCI Runtime Spec test suite provided by opencontainers [_does not_ support cgroup v2](https://github.com/opencontainers/runtime-tools/blob/6c9570a1678f3bc7eb6ef1caa9099920b7f17383/cgroups/cgroups.go#L73).

`brownie` currently implements cgroup v1 (v2 will be looked at in future!). However, like `runc` and other container runtimes, the `find x cgroup` tests pass and the `get x cgroup data` tests fail.
The OCI Runtime Spec test suite provided by opencontainers _does_ support cgroup v1.

`brownie` currently implements both cgroup v1 and v2. However, like `runc` and other container runtimes, the `find x cgroup` tests pass and the `get x cgroup data` tests fail.

<details>
<summary>Full list of cgroups tests</summary>
Expand Down
6 changes: 0 additions & 6 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,5 @@ Vagrant.configure("2") do |config|
tar -C /usr/local -xzf go.tar.gz
echo "PATH=$PATH:/usr/local/go/bin" >> /etc/environment
fi
# systemd cgroup jiggery-pokery
if ! grep -qs '/sys/fs/cgroup/systemd' /proc/mounts; then
mkdir -p /sys/fs/cgroup/systemd
mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd
fi
SHELL
end
43 changes: 43 additions & 0 deletions cgroups/cgroupsv1.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,40 @@ package cgroups
import (
"fmt"

"github.com/containerd/cgroups/v3"
"github.com/containerd/cgroups/v3/cgroup1"
"github.com/containerd/cgroups/v3/cgroup2"
"github.com/opencontainers/runtime-spec/specs-go"
)

func IsUnified() bool {
return cgroups.Mode() == cgroups.Unified
}

func AddV2(
containerID string,
devices []specs.LinuxDeviceCgroup,
pid int,
) error {
cg, err := cgroup2.NewSystemd(
"/",
fmt.Sprintf("%s.slice", containerID),
-1,
&cgroup2.Resources{
Devices: devices,
},
)
if err != nil {
return fmt.Errorf("create cgroups (id: %s): %w", containerID, err)
}

if err := cg.AddProc(uint64(pid)); err != nil {
return fmt.Errorf("add pid to cgroup2: %w", err)
}

return nil
}

func AddV1(
path string,
devices []specs.LinuxDeviceCgroup,
Expand All @@ -31,6 +61,19 @@ func AddV1(
return nil
}

func DeleteV2(containerID string) error {
cg, err := cgroup2.LoadSystemd("/", fmt.Sprintf("%s.slice", containerID))
if err != nil {
return fmt.Errorf("load cgroups (id: %s): ", containerID, err)

Check failure on line 67 in cgroups/cgroupsv1.go

View workflow job for this annotation

GitHub Actions / build

fmt.Errorf call needs 1 arg but has 2 args
}

if err := cg.DeleteSystemd(); err != nil {
return fmt.Errorf("delete cgroups (id: %s): %w", err)

Check failure on line 71 in cgroups/cgroupsv1.go

View workflow job for this annotation

GitHub Actions / build

fmt.Errorf format %w reads arg #2, but call has 1 arg
}

return nil
}

func DeleteV1(path string) error {
staticPath := cgroup1.StaticPath(path)

Expand Down
22 changes: 16 additions & 6 deletions container/container_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,22 @@ func (c *Container) Init(reexecCmd string, reexecArgs []string) error {
}

if c.Spec.Linux.CgroupsPath != "" && c.Spec.Linux.Resources != nil {
if err := cgroups.AddV1(
c.Spec.Linux.CgroupsPath,
c.Spec.Linux.Resources.Devices,
c.PID(),
); err != nil {
return err
if cgroups.IsUnified() {
if err := cgroups.AddV2(
c.ID(),
c.Spec.Linux.Resources.Devices,
c.PID(),
); err != nil {
return err
}
} else {
if err := cgroups.AddV1(
c.Spec.Linux.CgroupsPath,
c.Spec.Linux.Resources.Devices,
c.PID(),
); err != nil {
return err
}
}
}

Expand Down
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,23 @@ require (
github.com/stretchr/testify v1.9.0
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
github.com/thediveo/gons v0.9.9
golang.org/x/mod v0.21.0
golang.org/x/mod v0.22.0
golang.org/x/sys v0.27.0
)

require (
github.com/cilium/ebpf v0.16.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
15 changes: 15 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE=
github.com/containerd/cgroups/v3 v3.0.4 h1:2fs7l3P0Qxb1nKWuJNFiwhp2CqiKzho71DQkDrHJIo4=
github.com/containerd/cgroups/v3 v3.0.4/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
Expand Down Expand Up @@ -33,10 +38,14 @@ github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
Expand All @@ -49,10 +58,15 @@ github.com/thediveo/lxkns v0.28.0 h1:8qlq3OHoqm3BP2Kkub15l0zsnrWBVqtd1XiIswp/j5g
github.com/thediveo/lxkns v0.28.0/go.mod h1:Nc901fio1C1hBf7J04NCkmenjzPj+i2/FNsS98VhHeg=
github.com/thediveo/testbasher v1.0.7 h1:2ZSzFlOk8fLIWITXm8H7MEK5l22jDeHZCDMcs+1AqaI=
github.com/thediveo/testbasher v1.0.7/go.mod h1:a3aAe/ooBhkdIXJDURfiR1jSAZKNKf8DDJ2tkydfXbE=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
Expand All @@ -63,5 +77,6 @@ google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8i
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3 changes: 0 additions & 3 deletions test/oci-integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,6 @@ tests=(

mkdir -p $logdir

mkdir -p /sys/fs/cgroup/systemd
mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd

# run tests
for test in "${tests[@]}"; do
./validation/${test}/${test}.t 2>&1 | tee ${logdir}/${test}.log
Expand Down

0 comments on commit f09e0fb

Please sign in to comment.