Linux control groups (cgroups) are the kernel feature that makes modern containerization possible. They partition system resources — CPU, memory, disk I/O, and network bandwidth — into isolated groups, ensuring that one process cannot monopolize the entire system. With cgroup v2, the Linux kernel introduced a unified hierarchy, improved resource accounting, and better support for modern workloads like containers and virtual machines.
For self-hosted server administrators, managing cgroups effectively is essential for resource allocation, troubleshooting, and ensuring fair scheduling across services. This guide compares three administration approaches: systemd-cgtop (real-time monitoring via systemd), cgroup-tools (command-line utilities), and libcgroup (the C library and legacy tools).
Understanding cgroup v2 vs cgroup v1
cgroup v2 represents a fundamental redesign over v1:
| Feature | cgroup v1 | cgroup v2 |
|---|---|---|
| Hierarchy | Multiple trees (one per controller) | Single unified tree |
| Controller Placement | Any level | Only at leaf nodes |
| Memory Accounting | Per-controller | Unified |
| I/O Control | blkio controller | io controller |
| CPU Control | cpu + cpuacct | cpu (unified) |
| Delegation | Complex | Clean (for containers) |
| BPF Integration | No | Yes (eBPF programs) |
Most modern distributions default to cgroup v2 (kernel 5.x+ with systemd 247+). You can check your system with:
| |
Tool Comparison at a Glance
| Feature | systemd-cgtop | cgroup-tools | libcgroup (cgexec) |
|---|---|---|---|
| Primary Role | Real-time monitoring | CLI administration | C library + legacy tools |
| Package | systemd | cgroup-tools (cgget, cgset) | libcgroup (cgexec, cgclassify) |
| Interactive UI | Yes (top-like) | No (command-line) | No |
| Resource Setting | No (view only) | Yes (cgset, cgcreate) | Yes (cgexec, cgclassify) |
| cgroup v2 Support | Full | Full | Partial (legacy tools) |
| Controller Management | systemd units only | Manual | Manual |
| Process Classification | Via systemd | cgclassify | cgclassify |
| Best For | Monitoring, overview | Fine-grained control | Legacy application support |
| Active Development | Active (systemd project) | Active (cgroup-tools) | Limited (maintenance) |
| GitHub | systemd/systemd (10,800+ ★) | brauner/cgroup-tools (community) | libcg/libcgroup (community) |
systemd-cgtop: Real-Time Resource Monitoring
systemd-cgtop provides a top-like view of cgroup resource usage, making it the fastest way to see which services and containers are consuming system resources. It works with both cgroup v1 and v2 and integrates seamlessly with systemd’s service management.
Basic Usage
| |
Understanding the Output
| |
Each row represents a cgroup. The hierarchy is shown through indentation, making it easy to see which services belong to which parent group. The unified cgroup v2 hierarchy means all resource controllers are visible in a single view.
Integration with systemd Services
| |
cgroup-tools: Fine-Grained Administration
The cgroup-tools package provides command-line utilities for creating, configuring, and querying cgroups directly — without going through systemd. This is essential for managing non-systemd processes, containers, and custom resource allocation schemes.
Core Commands
| |
Container Resource Management
For self-hosted container environments, cgroup-tools provides direct control over resource allocation:
| |
Docker Compose Integration
| |
libcgroup: Legacy Application Support
libcgroup is the original cgroup management library, providing both a C API for application integration and command-line tools. While the command-line tools (cgexec, cgclassify) remain useful, much of libcgroup’s functionality is now available through systemd and cgroup-tools.
libcgroup Configuration
The legacy cgconfig approach uses a configuration file:
| |
Process Classification with cgclassify
| |
Modern libcgroup Usage
For cgroup v2, libcgroup provides a compatibility layer:
| |
Why Self-Host with cgroup v2?
For self-hosted infrastructure, cgroup v2 provides several advantages over v1:
Unified Resource Management: With a single hierarchy, you can see and manage all resource controllers from one place. No more coordinating between multiple cgroup trees — CPU, memory, and I/O settings are all applied to the same cgroup path.
Better Container Isolation: cgroup v2’s delegation model allows containers to create their own sub-cgroups, enabling nested container runtimes. This is essential for running Docker-in-Docker or Kubernetes nodes on self-hosted infrastructure.
Pressure Stall Information (PSI): cgroup v2 integrates with the kernel’s PSI system, providing accurate resource pressure metrics. Instead of guessing whether a system is memory-constrained based on swap usage, PSI tells you exactly how long processes are stalled waiting for resources. For related reading on OOM prevention, see our Linux OOM prevention guide.
BPF-Based Resource Control: cgroup v2 supports attaching eBPF programs to cgroups, enabling custom resource management policies. You can write BPF programs that implement sophisticated throttling, accounting, or scheduling algorithms tailored to your workload. For an introduction to eBPF tooling, check our eBPF tracing guide.
Security and Resource Isolation Best Practices
- Set memory limits on all services — unbounded memory usage can trigger system-wide OOM kills
- Use IOWeight instead of IOLimit — weight-based scheduling is fairer than hard limits
- Monitor with systemd-cgtop regularly — catch resource hogs before they impact other services
- Test pressure scenarios — use
stress-ngto verify cgroup limits work as expected - Enable cgroup v2 at boot — add
systemd.unified_cgroup_hierarchy=1to kernel parameters if needed - Avoid cgroup v1/v2 hybrid mode — mixed hierarchies cause unpredictable behavior
| |
Choosing the Right cgroup Administration Tool
| Scenario | Recommended | Reason |
|---|---|---|
| Quick resource overview | systemd-cgtop | Interactive, real-time display |
| Non-systemd process management | cgroup-tools (cgexec) | Direct cgroup control |
| Container runtime integration | cgroup-tools | Programmatic API |
| Legacy application support | libcgroup (cgclassify) | Compatible with older tools |
| Automated resource policies | systemd unit files + cgroup-tools | Declarative + imperative |
| Troubleshooting resource issues | systemd-cgtop + PSI | Visual monitoring + pressure metrics |
| Custom scheduling algorithms | cgroup v2 + eBPF | Programmable control |
FAQ
What is the difference between cgroup v1 and cgroup v2?
cgroup v2 uses a single unified hierarchy for all resource controllers, while v1 had separate trees for CPU, memory, I/O, and other controllers. v2 also introduces better delegation for containers, improved memory accounting (including swap tracking), and integration with eBPF programs. Most modern distributions default to v2 — check with stat -fc %T /sys/fs/cgroup/ (should show cgroup2fs).
How do I enable cgroup v2 on my system?
If your system is running cgroup v1, add systemd.unified_cgroup_hierarchy=1 to your kernel boot parameters. In GRUB, edit /etc/default/grub:
| |
Then reboot. Most distributions with kernel 5.x+ and systemd 247+ use v2 by default.
Can I use systemd-cgtop with cgroup v1?
Yes, systemd-cgtop works with both cgroup v1 and v2. However, the display differs — v2 shows a unified hierarchy while v1 shows multiple controller trees. For the best experience, migrate to cgroup v2.
How do I set a hard CPU limit (not just weight) for a service?
In systemd, use CPUQuota= in the unit file:
| |
This limits the service to 50% of one CPU core. For cgroup v2 direct control:
| |
What happens when a cgroup exceeds its memory limit?
In cgroup v2, when a cgroup reaches memory.max, the kernel triggers an OOM kill within that cgroup — only processes in the offending cgroup are killed, protecting the rest of the system. This is a significant improvement over v1, where memory pressure could cascade across the entire system. You can monitor OOM events with cat /sys/fs/cgroup/memory.events.
Is libcgroup still maintained?
libcgroup receives maintenance updates but is not actively developed for new features. The command-line tools (cgexec, cgclassify) remain functional and useful, but for new deployments, prefer systemd’s native cgroup management or cgroup-tools. The C library is still used by some applications for programmatic cgroup control.