Non-Root User Cgroup Management: Creating and Assigning Processes to CPU-Limited Control Groups


36 views

While cgroups (control groups) traditionally require root privileges, modern Linux systems (kernel 4.6+) support delegated cgroup management through the cgroups v2 filesystem hierarchy. The key lies in proper filesystem permissions and namespace configuration.

Before attempting user-level cgroup management, verify these system conditions:

# Check cgroup v2 mount
mount | grep cgroup2
# Verify kernel version
uname -r
# Check for cpu controller availability
cat /sys/fs/cgroup/cgroup.controllers

System administrators must first enable user delegation:

# As root:
mkdir /sys/fs/cgroup/user.slice
echo '+cpu +memory +pids' > /sys/fs/cgroup/user.slice/cgroup.subtree_control
chown -R user:user /sys/fs/cgroup/user.slice

Once configured, users can create their own hierarchy:

# As regular user:
mkdir -p ~/my_cgroups/cpu_limited
echo "100000" > ~/my_cgroups/cpu_limited/cpu.max
echo "1" > ~/my_cgroups/cpu_limited/cpu.weight

To launch a process in your cgroup:

# Using cgroup-tools (if installed)
cgexec -g cpu:~/my_cgroups/cpu_limited my_command

# Manual method
echo $$ > ~/my_cgroups/cpu_limited/cgroup.procs
./my_application

Confirm your process is properly constrained:

cat /proc/$(pgrep my_application)/cgroup
cat ~/my_cgroups/cpu_limited/cpu.stat

If encountering permission errors:

  • Verify systemd unit files aren't overriding your cgroups
  • Check for existing cgroupv1 hierarchies that might conflict
  • Confirm your user has write access to all parent cgroup directories

For older systems without cgroupv2:

# Requires admin setup first
sudo cgcreate -a $USER -g cpu:/user_$USER
cgset -r cpu.cfs_period_us=100000 -r cpu.cfs_quota_us=50000 user_$USER
cgexec -g cpu:user_$USER ./cpu_intensive_process

Modern Linux systems (kernel 4.15+) with cgroups v2 support user delegation through the cgroup.subtree_control interface. The key filesystem locations are:

/sys/fs/cgroup/
└── user.slice
    └── user-{uid}.slice

System administrators must first enable user delegation:

# As root:
echo "+cpu +memory +pids" > /sys/fs/cgroup/cgroup.subtree_control
mkdir -p /sys/fs/cgroup/user.slice
chmod 755 /sys/fs/cgroup/user.slice

After configuration, regular users can create their own hierarchies:

# As regular user:
CGROUP_PATH="/sys/fs/cgroup/user.slice/user-$(id -u).slice/my-app"
mkdir -p "$CGROUP_PATH"

To restrict a process to use only one CPU core:

# Set CPU quota (100000 = 1 core)
echo "100000" > "$CGROUP_PATH/cpu.max"

# Launch process in cgroup
echo $$ > "$CGROUP_PATH/cgroup.procs"
./cpu_intensive_task

Memory limits can be similarly enforced:

# Set 1GB memory limit
echo "1G" > "$CGROUP_PATH/memory.high"

# Optional OOM killer setting
echo "1" > "$CGROUP_PATH/memory.oom.group"

Managing process groups efficiently:

# Move existing process
echo 12345 > "$CGROUP_PATH/cgroup.procs"

# Fork new process directly in cgroup
cgexec -g cpu,memory:my-app ./new_process
  • Permission denied: Verify user.slice permissions
  • No such file: Check if cgroups v2 is mounted (mount | grep cgroup2)
  • Invalid argument: Ensure kernel supports the specific controller