Skip to main content
Topic: chcgs: cgroups without daemons (and without pain) (Read 239 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

chcgs: cgroups without daemons (and without pain)

Adding basic Linux cgroup support to a piece of software, especially after cgroups v2, isn't that difficult: it's easily doable with mkdir and echo (or write if you're using a "real" programming language). It's the stage dinit currently finds itself in, and it's two lines of code in a run file for runit/s6.

However, it gets kind of clunky when adding resource limits and doing delegation; the non-systemd init system with the most advanced official control group support I'm aware of (nosh) still hardcodes a lot of things, and you have to explicitly script a bunch of things that just shouldn't be necessary. I mean, look at this (yes, it needs to be spoilered):

Spoiler (click to show/hide)

If you're familiar with nosh, you might reply that nosh generates service definitions from a template, so it's okay if the commands are barely more usable than low-level mkdir and echo. That still leaves a niche for a tool that figures out the needed setup at runtime. That's why I came up chcgs™: https://codeberg.org/Capezotte/chcgs/

The above file then becomes few lines of sh:
Code: [Select]
#!/bin/sh
read -r thr_max < /proc/sys/kernel/threads-max &&
exec chcgs -o pids.max=$((thr_max/100)) '../[email protected]' \
  setuidgid 'ossec\aagentd-log' cyclog 'ossec@agentd'

Just find the file you want to use in the the kernel documentation, and add a -o ${file}=${value} to the command line; chcgs figures out the cgroup.subtree_control part for you.

The only mandatory argument is the cgroup you want to run the program in; like dinit's run-in-cgroup option, it can be relative or absolute (and if it's relative, it's relative to chcgs's current control group). If you want to run a program in the control group after setting it up, just provide it as an additional argument (but the program is optional; if there's no program, it just tweaks a control group that already exists).

There's a second utility, cgpoll, which just waits (optionally with a timeout) for a cgroup to go vacant or to have a process in it. It provides an easy way to, say, nuke a cgroup with chcgs -o cgroup.kill=1 $CGROUP after a timeout if you have a misbehaving service that leaves orphans behind.

For more, and a detailed description, there's manpages in the repository.

The project requires skalibs to build (yes, it's "the s6 library", but this project doesn't require s6, it fits nicely in runit scripts, and this will work to manage dinit services with a run-in-cgroup option). Once skalibs is installed, it's the familiar git clone plus make && sudo make install build process (no configure).

I'm already using it with a few simple containers with arachsys/containers (where stuff like docker and podman is overkill, but chroot isn't quite enough).

Feedback is welcome.