<p>I'm confused with the relationship between two parameters: <code>requests</code> and <code>cpu.shares</code> of the cgroup which is updated once the Pod is deployed. According the readings I've done so far, <code>cpu.shares</code> reflects some kind of priority when trying to get the chance to consume the CPU. And it's a relative value.</p>
<p>So my question why kubernetes considers the <code>request</code> value of the CPU as an absolute value when scheduling? When it comes to the CPU processes will get a time slice to get executed based on their priorities (according to the CFS mechanism). To my knowledge, there's no such thing called giving such amounts of CPUs (1CPU, 2CPUs etc.). So, if the <code>cpu.share</code> value is considered to prioritize the tasks, why kubernetes consider the exact request value (Eg: 1500m, 200m) to find out a node?</p>
<p>Please correct me if I've got this wrong. Thanks !!</p>

<p>Answering your questions from the main question and comments:</p>
<blockquote>
<p>So my question why kubernetes considers the <code>request</code> value of the CPU as an absolute value when scheduling?</p>
</blockquote>
<blockquote>
<p>To my knowledge, there's no such thing called giving such amounts of CPUs (1CPU, 2CPUs etc.). So, if the <code>cpu.share</code> value is considered to prioritize the tasks, why kubernetes consider the exact request value (Eg: 1500m, 200m) to find out a node?</p>
</blockquote>
<p>It's because decimal CPU values from the requests <a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-cpu" rel="nofollow noreferrer">are always converted to the values in milicores, like 0.1 is equal to 100m which can be read as &quot;one hundred millicpu&quot; or &quot;one hundred millicores&quot;</a>. Those units are specific for Kubernetes:</p>
<blockquote>
<p>Fractional requests are allowed. A Container with  <code>spec.containers[].resources.requests.cpu</code>  of  <code>0.5</code>  is guaranteed half as much CPU as one that asks for 1 CPU. The expression  <code>0.1</code>  is equivalent to the expression  <code>100m</code>, which can be read as &quot;one hundred millicpu&quot;. Some people say &quot;one hundred millicores&quot;, and this is understood to mean the same thing. A request with a decimal point, like  <code>0.1</code>, is converted to  <code>100m</code>  by the API, and precision finer than  <code>1m</code>  is not allowed. For this reason, the form  <code>100m</code>  might be preferred.</p>
</blockquote>
<blockquote>
<p>CPU is always requested as an absolute quantity, never as a relative quantity; 0.1 is the same amount of CPU on a single-core, dual-core, or 48-core machine.</p>
</blockquote>
<p>Based on the above one, remember that you can specify to use let's say 1.5 CPU of the node by specifying <code>cpu: 1.5</code> or <code>cpu: 1500m</code>.</p>
<blockquote>
<p>Just wanna know lowering the <code>cpu.share</code> value in cgroups (which is modified by k8s after the deployment) affects to the cpu power consume by the process. For an instance, assume that A, B containers have 1024, 2048 shares allocated. So the available resources will be split into 1:2 ratio. So would it be the same as if we configure cpu.share as 10, 20 for two containers. Still the ratio is 1:2</p>
</blockquote>
<p>Let's make it clear  - it's true that the ratio is the same, but the values are different. 1024 and 2048 in <code>cpu.shares</code> means <code>cpu: 1000m</code> and <code>cpu: 2000m</code> defined in Kubernetes resources, while 10 and 20 means <code>cpu: 10m</code> and <code>cpu: 20m</code>.</p>
<blockquote>
<p>Let's say the cluster nodes are based on Linux OS. So, how kubernetes ensure that request value is given to a container? Ultimately, OS will use configurations available in a cgroup to allocate resource, right? It modifies the <code>cpu.shares</code> value of the cgroup. So my question is, which files is modified by k8s to tell operating system to give <code>100m</code> or <code>200m</code> to a container?</p>
</blockquote>
<p>Yes, your thinking is correct. Let me explain in more detail.</p>
<p>Generally on the Kubernetes node <a href="https://medium.com/omio-engineering/cpu-limits-and-aggressive-throttling-in-kubernetes-c5b20bd8a718" rel="nofollow noreferrer">there are three cgroups under the root cgroup</a>, named as <em>slices</em>:</p>
<blockquote>
<p>The k8s uses <code>cpu.share</code> file to allocate the CPU resources. In this case, the root cgroup inherits 4096 CPU shares, which are 100% of available CPU power(1 core = 1024; this is fixed value). The root cgroup allocate its share proportionally based on children’s <code>cpu.share</code> and they do the same with their children and so on. In typical Kubernetes nodes, there are three cgroup under the root cgroup, namely <code>system.slice</code>, <code>user.slice</code>, and <code>kubepods</code>. The first two are used to allocate the resource for critical system workloads and non-k8s user space programs. The last one, <code>kubepods</code> is created by k8s to allocate the resource to pods.</p>
</blockquote>
<p>To check which files are modified we need to go to the <code>/sys/fs/cgroup/cpu</code> directory. <a href="https://gist.github.com/mcastelino/b8ce9a70b00ee56036dadd70ded53e9f#cpu-resource-management" rel="nofollow noreferrer">Here we can find directory called <code>kubepods</code></a> (which is one of the above mentioned <em>slices</em>) where all <code>cpu.shares</code> files for pods are here. In <code>kubepods</code> directory we can find two other folders - <code>besteffort</code> and <code>burstable</code>. Here is worth mentioning that Kubernetes have a three <a href="https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#qos-classes" rel="nofollow noreferrer">QoS classes</a>:</p>
<ul>
<li><a href="https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#create-a-pod-that-gets-assigned-a-qos-class-of-guaranteed" rel="nofollow noreferrer">Guaranteed</a></li>
<li><a href="https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#create-a-pod-that-gets-assigned-a-qos-class-of-burstable" rel="nofollow noreferrer">Burstable</a></li>
<li><a href="https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#create-a-pod-that-gets-assigned-a-qos-class-of-besteffort" rel="nofollow noreferrer">BestEffort</a></li>
</ul>
<p>Each pod has an assigned QoS class and depending on which class it is, the pod is located in the corresponding directory (except guaranteed, pod with this class is created in <code>kubepods</code> directory).</p>
<p>For example, I'm creating a pod with following definition:</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-deployment
spec:
  selector:
    matchLabels:
      app: test-deployment
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: test-deployment
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 300m
      - name: busybox
        image: busybox
        args:
        - sleep
        - &quot;999999&quot;
        resources:
          requests:
            cpu: 150m
</code></pre>
<p>Based on earlier mentioned definitions, this pod will have assigned Qos class <code>Burstable</code>, thus it will be created in the <code>/sys/fs/cgroup/cpu/kubepods/burstable</code> directory.</p>
<p>Now we can check <code>cpu.shares</code> set for this pod:</p>
<pre><code>user@cluster /sys/fs/cgroup/cpu/kubepods/burstable/podf13d6898-69f9-44eb-8ea6-5284e1778f90 $ cat cpu.shares
460
</code></pre>
<p>It is correct as one pod is taking 300m and the second one 150m and it's <a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#how-pods-with-resource-limits-are-run" rel="nofollow noreferrer">calculated by multiplying 1024</a>. For each container we have sub-directories as well:</p>
<pre><code>user@cluster /sys/fs/cgroup/cpu/kubepods/burstable/podf13d6898-69f9-44eb-8ea6-5284e1778f90/fa6194cbda0ccd0b1dc77793bfbff608064aa576a5a83a2f1c5c741de8cf019a $ cat cpu.shares
153
user@cluster /sys/fs/cgroup/cpu/kubepods/burstable/podf13d6898-69f9-44eb-8ea6-5284e1778f90/d5ba592186874637d703544ceb6f270939733f6292e1fea7435dd55b6f3f1829 $ cat cpu.shares
307
</code></pre>
<p>If you want to read more about Kubrenetes CPU management, I'd recommend reading following:</p>
<ul>
<li><a href="https://medium.com/omio-engineering/cpu-limits-and-aggressive-throttling-in-kubernetes-c5b20bd8a718" rel="nofollow noreferrer">CPU limits and aggressive throttling in Kubernetes</a></li>
<li><a href="https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/" rel="nofollow noreferrer">Control CPU Management Policies on the Node</a></li>
<li><a href="https://medium.com/@kkwriting/kubernetes-resource-limits-and-kernel-cgroups-337625bab87d" rel="nofollow noreferrer">Kubernetes resource limits and kernel cgroups</a></li>
<li><a href="https://www.infoq.com/presentations/evolve-kubernetes-resource-manager/" rel="nofollow noreferrer">How to Evolve Kubernetes Resource Management Model</a></li>
</ul>
