---
title: "cgroups v2 Resource Control and Systemd Integration"
description: "An in-depth guide to the latest cgroups v2 resource control features and how they integrate with systemd"
keywords: ["cgroups", "resource control", "systemd", "linux", "process management"]
category: "linux"
---

The unified cgroups v2 hierarchy introduced in Linux kernel version 5.3 provides a simplified and more powerful resource control system compared to the legacy cgroups v1. At the core of cgroups v2 is the concept of a unified hierarchy, where all subsystems are mounted under a single root directory, such as /sys/fs/cgroup. This unified approach simplifies management and configuration, as users no longer need to deal with multiple, disparate hierarchies.

One key cgroups v2 feature is the cpu.max control, which allows you to specify a CPU bandwidth limit for a cgroup. The cpu.max parameter accepts two values: a quota and a period. For example, setting cpu.max="50000 100000" would limit the cgroup to 50% of a single CPU core. This fine-grained CPU bandwidth control is useful for workloads with strict performance requirements.

The memory.max and memory.high control files in cgroups v2 provide flexible memory usage limits. memory.max sets an absolute cap on the memory usage of a cgroup, while memory.high allows you to define a "high water mark" that triggers aggressive reclaim when crossed. These memory limits help prevent rogue processes from exhausting system memory.

Cgroups v2 also introduces the io.max control, which allows you to throttle I/O bandwidth on a per-device basis. For example, you could limit a cgroup to 10MB/s of read throughput and 5MB/s of write throughput on the /dev/sda block device using io.max="rbps=10485760,wbps=5242880". This granular I/O control is valuable for managing the performance of storage-intensive workloads.

A powerful feature of cgroups v2 is the ability to delegate control of a subset of the hierarchy to unprivileged users. This is achieved using the "cgroup.subtree_control" file, which allows users to enable or disable specific controllers on a per-cgroup basis. This delegation model enables self-service resource management without the need for root privileges.

Systemd, the dominant init system on modern Linux distributions, has deep integration with cgroups v2. Systemd uses the unified cgroups hierarchy and exposes cgroups functionality through its own resource control mechanisms, such as CPU and memory limits, I/O throttling, and more. Systemd also introduces the concept of "slices", which are hierarchical cgroups that provide a structured way to organize and manage system processes.

Cgroups v2 includes the "pressure stall information" (PSI) feature, which provides detailed reporting on CPU, memory, and I/O pressure experienced by a cgroup. PSI metrics can be accessed through the "pressure" pseudo-files, such as cpu.pressure, memory.pressure, and io.pressure. This visibility into resource contention is invaluable for troubleshooting performance issues and optimizing resource utilization.

The cpu.weight control in cgroups v2 allows you to specify a relative CPU scheduling weight for a cgroup, similar to the CPU shares concept in cgroups v1. This weight-based CPU scheduling is useful for workloads with varying CPU requirements, as it ensures that higher-priority cgroups receive a larger share of the available CPU cycles.

Finally, cgroups v2 introduces the memory.swap.max control, which sets a limit on the amount of swap space that can be used by a cgroup. This is particularly important for containerized environments, where you may want to restrict the amount of swap space used by individual containers to prevent them from overwhelming the system's swap capacity.The unified cgroups v2 hierarchy also includes the ability to set I/O priorities for a cgroup using the io.weight control. This allows you to assign a relative weight to the I/O operations of a cgroup, ensuring that higher-priority workloads receive preferential access to the storage subsystem. For example, setting io.weight="1000 500" would give a cgroup twice the I/O priority of another cgroup with a weight of 500.

Cgroups v2 introduces a new controller called "io.latency", which enables fine-grained control over I/O latency for a cgroup. This controller allows you to specify a target maximum latency for read and write operations, and the kernel will automatically throttle the I/O of the cgroup to maintain the desired latency levels. This is particularly useful for latency-sensitive applications, such as databases or real-time systems, where consistent I/O performance is critical.

Another notable feature of cgroups v2 is the ability to set a limit on the number of tasks (processes and threads) that can be created within a cgroup using the pids.max control. This can be helpful in preventing a runaway process from spawning an excessive number of child processes, which could potentially exhaust system resources. The pids.max control accepts a numeric value or the special "max" keyword to specify an unlimited number of tasks.

Cgroups v2 also introduces the "unified" controller, which provides a way to define custom metrics and control parameters for a cgroup. This allows system administrators and application developers to create their own resource management policies tailored to the specific needs of their workloads. The unified controller is exposed through a set of user-defined control files, which can be used to monitor and manipulate the custom metrics and controls.

The integration of cgroups v2 with systemd simplifies resource management for system administrators. Systemd's "slice" abstraction maps directly to the cgroups v2 hierarchy, allowing you to easily organize and manage processes using familiar systemd commands, such as "systemctl set-property" to apply cgroup settings. Additionally, systemd's "Delegate=" option can be used to grant unprivileged users the ability to manage specific slices, enabling self-service resource control without the need for root access.Cgroups v2 also includes support for the "memory.min" control, which allows you to specify a minimum amount of memory that must be guaranteed for a cgroup, even under memory pressure. This can be useful for ensuring that critical applications or services always have access to a baseline level of memory resources, preventing them from being starved by other, less important workloads. The memory.min control complements the memory.max and memory.high controls, providing a more comprehensive set of memory management tools.

The "cpu.util" control in cgroups v2 offers a different approach to CPU bandwidth management compared to the cpu.max control. Instead of specifying a hard limit, cpu.util allows you to define a target CPU utilization percentage for a cgroup. The kernel will then automatically adjust the CPU time allocated to the cgroup to maintain the specified utilization level, which can be beneficial for workloads with variable CPU demands that need to be kept within a certain utilization range.

Cgroups v2 also introduces the "io.opt" control, which enables optimization of I/O operations for a cgroup. This control allows you to specify preferred I/O access patterns, such as sequential or random, and the kernel will then attempt to schedule the I/O operations in a way that aligns with the specified pattern. This can lead to improved I/O performance and reduced system overhead for workloads with predictable I/O access patterns.

The integration of cgroups v2 with systemd's "Delegate=" option not only allows unprivileged users to manage specific slices, but also enables the delegation of cgroup controllers to those users. This means that users can be granted the ability to configure and monitor the resource limits and metrics for the cgroups they are responsible for, without needing elevated privileges. This delegation model promotes self-service resource management and helps to distribute the workload of system administration.

Cgroups v2 also includes support for the "memory.oom.group" control, which allows you to specify a cgroup that should receive the "out-of-memory" (OOM) kill notification when a process within the cgroup exceeds its memory limit. This can be useful for implementing custom OOM handling strategies, such as automatically restarting or migrating critical services when they are terminated due to memory exhaustion.The cgroups v2 "cpu.weight" control provides a more flexible approach to CPU scheduling compared to the legacy "cpu.shares" mechanism in cgroups v1. Rather than using a fixed share value, cpu.weight allows you to specify a relative weight between 1 and 10000, with higher values granting more CPU time to the associated cgroup. This weight-based scheduling ensures that critical workloads receive a larger portion of the available CPU resources, while still allowing less important tasks to consume excess capacity.

Cgroups v2 also introduces the concept of "cpu.pressure", which is part of the pressure stall information (PSI) feature. The cpu.pressure pseudo-file reports on the level of CPU contention experienced by a cgroup, with values ranging from 0 (no contention) to 100 (full contention). This information can be used to monitor the CPU utilization of a cgroup and trigger scaling actions, such as adding more CPU resources or migrating the cgroup to a less-loaded system, to maintain the desired performance levels.

The "memory.swap.max" control in cgroups v2 allows you to set a limit on the amount of swap space that can be used by a cgroup. This is particularly important in containerized environments, where you may want to restrict the swap usage of individual containers to prevent them from exhausting the system's swap capacity and causing performance issues. By setting a reasonable memory.swap.max value, you can ensure that containers do not rely too heavily on swap, which can degrade overall system responsiveness.

Cgroups v2 also includes support for the "io.latency.target" control, which builds upon the io.latency controller. This control allows you to specify a target maximum I/O latency for a cgroup, and the kernel will automatically throttle the I/O operations of the cgroup to maintain the desired latency levels. This can be especially useful for latency-sensitive applications, such as databases or real-time systems, where consistent I/O performance is critical to their operation.

The integration of cgroups v2 with systemd's "Slice" abstraction provides a structured way to organize and manage system processes. Systemd slices can be nested, allowing you to create a hierarchical resource management scheme that mirrors the cgroups v2 hierarchy. This enables fine-grained control over resource allocation, as you can apply different resource limits and policies to individual slices or groups of slices, ensuring that critical services receive the necessary resources while less important workloads are constrained.