Kubernetes CPU requests and limits, explained through cgroups

lkanwoqwp1 pts0 comments

Kubernetes Resource Management: CPU Request and Limit in PracticeSkip to main content<br>Aleksander Roszig<br>April 4, 2026 | 10 min ReadKubernetes Resource Management: CPU Request and Limit in Practice<br>Kubernetes has been with us for 11 years now, and resource management is one of its most fundamental functions . Yet it remains one of the most common issues we observe in projects. Many people don&rsquo;t know how to properly use resource management mechanisms or use them incorrectly. It&rsquo;s still one of the most discussed topics in the Kubernetes world.<br>In this article, I&rsquo;d like to explain how CPU request and CPU limit work. In this post, we&rsquo;ll focus on CPU, and in the next part (Kubernetes memory request and limit), we&rsquo;ll discuss memory management.<br>Kubernetes Resource Management – How Does CPU Resource Allocation Work?<br>The answer is: cgroups .<br>Cgroups version 1 have been available since Linux kernel 2.6.24 (January 2008). They are the foundation of containerization technologies like Docker, Podman, and LXC. Today, most systems use cgroups v2, which were declared stable in kernel 4.5 in 2016 – and this is the version we&rsquo;ll continue to reference.<br>&ldquo;Control groups, usually called cgroups, are a Linux kernel feature that enables organizing processes into hierarchical groups, whose use of various types of resources can then be limited and monitored.&rdquo; - https://man7.org/linux/man-pages/man7/cgroups.7.html In practice, this means that all processes in a container can be placed in a single cgroup, for which we set parameters of controllers, such as CPU or memory.<br>Kubelet, which is responsible for creating containers, uses among others the following controllers:<br>cpu<br>cpuset<br>memory<br>hugetlb<br>pids<br>When setting CPU requests and limits, we&rsquo;re interested in the cpu controller .<br>According to the Linux kernel documentation: &ldquo;CPU controllers regulate the distribution of processor cycles. This controller implements weight and absolute bandwidth limitation models for standard scheduling policy, as well as absolute bandwidth allocation model for real-time scheduling policy.&rdquo;<br>We&rsquo;ll focus on standard scheduling mode (normal scheduling), because that&rsquo;s how Kubernetes works by default. With certain changes, it&rsquo;s possible to run real-time applications on Kubernetes, but it&rsquo;s not the default platform for this type of workload and is not yet supported in cgroups version 2.<br>CPU Request – Weight Model (weight)<br>CPU request in Kubernetes corresponds to the weight model in cgroups.<br>This is the amount of CPU we guarantee ourselves under load.<br>If we set in a Deployment:<br>resources:<br>requests:<br>cpu: 500m<br>Kubernetes converts this to a shares value (in cgroups v1) or weight (in cgroups v2). It does this using the MilliCPUToShares() function:<br>// MilliCPUToShares converts the milliCPU to CFS shares.<br>func MilliCPUToShares(milliCPU int64) uint64 {<br>if milliCPU == 0 {<br>// Docker converts zero milliCPU to unset, which maps to kernel default<br>// for unset: 1024. Return 2 here to really match kernel default for<br>// zero milliCPU.<br>return MinShares<br>// Conceptually (milliCPU / milliCPUToCPU) * sharesPerCPU, but factored to improve rounding.<br>shares := (milliCPU * SharesPerCPU) / MilliCPUToCPU<br>if shares MaxShares {<br>return MaxShares<br>return uint64(shares)<br>In simplified form:<br>shares = milliCPU * 1024 / 1000<br>For our set request value of 500m, the calculation will be: 500 * 1024 / 1000 = 512<br>This value goes to the cgroups part that is responsible for CPU time allocation. In cgroups v1, this is the cpu.shares parameter, and in cgroups v2, it is cpu.weight. This means our pod will have a weight of 512 relative to other pods, which have their own shares/weight values.<br>Next, it&rsquo;s used by the Linux scheduler . In many distributions with kernel version above 6.6, such as Amazon Linux 2023, Ubuntu 22.04.5+, 24.04+, Red Hat Enterprise Linux 10, there&rsquo;s already a newer EEVDF scheduler version. The Linux scheduler is the part of the kernel that handles CPU resource allocation. Even if you sometimes see the &ldquo;CFS&rdquo; metric name in Kubernetes code, which refers to an older scheduler that was added to the Linux kernel in October 2007 in version 2.6.23, your node still uses the scheduler provided by your Linux system.<br>How Does CPU Sharing Work in Kubernetes?<br>Let&rsquo;s assume we have 3 pods and for each of them a cgroup has been created with the following values:<br>cgroupmilliCPU parameterG1150G2100G350<br>The total sum of weights is 300. The Linux scheduler will allocate CPU time proportionally to these weights. This means that if all three cgroups are active and competing for CPU time. We can also calculate shares = milliCPU * 1024 / 1000 to see how this translates to percentages:<br>cgroupmilliCPU parameterCPU Time AllocationsharesG1150~50% (150/300)~50% (153/306)G2100~33% (100/300)~33% (102/306)G350~16%(50/300)~16%(51/306)<br>We set how much time each cgroup can get at full CPU...

cgroups rsquo kubernetes linux kernel shares

Related Articles