Control groups (cgroups) are the Linux kernel feature that organises processes into groups, and limits and accounts for their resources: CPU, memory, disk I/O, and number of processes. They’re the foundation of containers (Docker, Kubernetes), and of systemd’s service management. Modern distributions use cgroups v2, a single unified hierarchy.

Check your cgroup version

stat -fc %T /sys/fs/cgroup/        # cgroup2fs = v2, tmpfs = v1/hybrid
cat /proc/self/cgroup              # which cgroup your shell is in

Ubuntu 22.04+, Debian 11+, RHEL 9 and AlmaLinux 9 use v2 by default.

How systemd organises cgroups

systemd puts every service, user session and container into its own cgroup:

systemd-cgls                 # tree of cgroups and processes
systemd-cgtop                # live CPU, memory and I/O per cgroup (like top)
systemctl status nginx       # shows the service's CGroup and its processes

Slices group units: system.slice (services), user.slice (logged-in users), and machine.slice (VMs and containers).

Limit a service’s resources (systemd)

Use a drop-in override, rather than editing the packaged unit:

sudo systemctl edit myapp.service
[Service]
MemoryMax=1G          # hard limit: OOM-killed above this
MemoryHigh=800M       # soft limit: throttled and reclaimed above this
CPUQuota=150%         # at most 1.5 CPUs worth of time
CPUWeight=50          # relative share when CPUs are busy (default 100)
IOWeight=50           # relative disk I/O share
TasksMax=512          # max processes/threads
sudo systemctl daemon-reload && sudo systemctl restart myapp
systemctl show myapp -p MemoryMax -p CPUQuotaPerSecUSec

This is a great way to stop one misbehaving app (a memory leak, a runaway worker) from taking down a whole VPS. See systemd unit files.

One-off limits with systemd-run

Run a command in a temporary, limited cgroup:

sudo systemd-run --scope -p MemoryMax=2G -p CPUQuota=100% tar czf /backups/site.tgz /var/www
systemd-run --user --scope -p MemoryMax=500M ./script.sh

That’s handy for backups and batch jobs on busy servers. Compare nice and ionice.

Docker uses cgroups too

Container limits are cgroup settings:

docker run -d --memory=512m --cpus=1.5 --pids-limit=200 nginx
docker stats

See Docker CPU and memory limits.

Read the raw values

cgroup v2 exposes files under /sys/fs/cgroup/:

cat /sys/fs/cgroup/system.slice/nginx.service/memory.current
cat /sys/fs/cgroup/system.slice/nginx.service/memory.max
cat /sys/fs/cgroup/system.slice/nginx.service/cpu.stat
cat /sys/fs/cgroup/system.slice/nginx.service/memory.events      # oom, oom_kill counts

Troubleshooting: OOM kills inside a cgroup

When a service exceeds MemoryMax, the kernel kills a process in that cgroup, not elsewhere on the system:

journalctl -k | grep -i "memory cgroup out of memory"
systemctl status myapp       # "Main process exited, code=killed, status=9/KILL"

Raise the limit, fix the leak, or add MemoryHigh below MemoryMax, so the app slows down before it’s killed. See Linux OOM killer.

cgroups vs namespaces

  • cgroups limit and measure how much a group of processes can use.
  • namespaces control what they can see (processes, network, mounts).

Containers combine both. See Linux namespaces.

Practical defaults for a small VPS

On a server that runs several services, a few limits go a long way: cap memory-hungry background jobs (backups, image processing, indexing) with MemoryMax, give the web server and database a higher CPUWeight than batch work, and set TasksMax on apps that spawn workers, so a fork bomb or runaway pool can’t exhaust the process table. Leave headroom for the system itself: if all services together are allowed more memory than the VPS has, the limits won’t prevent the global OOM killer from stepping in.

Quick reference

Task Command / setting
cgroup version stat -fc %T /sys/fs/cgroup/
Tree / live usage systemd-cgls / systemd-cgtop
Limit a service systemctl edit X → MemoryMax=, CPUQuota=
One-off limit systemd-run --scope -p MemoryMax=… cmd
Docker limits --memory, --cpus
OOM events memory.events, journalctl -k

Related: Linux capabilities and systemctl commands.

  • Linux
  • systemd
  • Containers