4
votes

Objective

Clarify the behaviour of K8S container cpu usage when limit is set far below available CPU, and confirm if the understanding how to set limit is correct.

Background

I have a node of 2CPU, hence 2000m can be the upper limit. Every namespace is set with the LimitRange which limits CPU to 500m for container.

kind: LimitRange
metadata:
  name: core-resource-limits
    spec:
      limits:
      - default:
          cpu: 500m
          memory: 2Gi
        defaultRequest:
          cpu: 100m
        type: Container

Indication

Even when 2 CPU are available (no other process/container waiting) and a container is runnable, it can only use 0.5 CPU, and 1.5 CPU will be left unused. Is this correct?

How to set LimitRange

I believe I can set the limit such as 75-80% of available 2 CPU to better utilise the CPU resource. Because in case there are multiple containers trying to claim CPU more than requests, K8S will allocate the CPU among containers based on the request value of each containers, as per the documentations (some from OpenShift but believe it is the same with K8S). Is this correct?

kind: LimitRange
metadata:
  name: core-resource-limits
    spec:
      limits:
      - default:
          cpu: 1500m
          memory: 2Gi
        defaultRequest:
          cpu: 100m
        type: Container

CPU Requests

The CPU request represents a minimum amount of CPU that your container may consume, but if there is no contention for CPU, it can use all available CPU on the node. If there is CPU contention on the node, CPU requests provide a relative weight across all containers on the system for how much CPU time the container may use.

CPU Limits

Each container in a pod can specify the amount of CPU it is limited to use on a node. CPU limits control the maximum amount of CPU that your container may use independent of contention on the node. If a container attempts to exceed the specified limit, the system will throttle the container. This allows the container to have a consistent level of service independent of the number of pods scheduled to the node.

kubernetes / understanding CPU resources limits

The 6% of CPU means 6% (CPU requests) of the nodes CPU time is reserved for this pod. So it guaranteed that it always get at lease this amount of CPU time. It can still burst up to 12% (CPU limits), if there is still CPU time left.

How are Kubernetes CPU limits enforced?

Checking one of my containers, I see that Kubernetes set CpuPeriod, CpuQuota for them. The Docker docs (https://docs.docker.com/engine/reference/run/) mention the CFS documentation (https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt), and from the information there, it seems that these are hard limits

1
Your assessment looks right, but if you're optimizing for node CPU utilization, why set limits at all?Jonah Benton
If a deployment doesn't set request/limit values and there are no defaults for the project which get applied when a deployment doesn't have any, then Kubernetes doesn't really have a way of working out best node to run a pod by comparing how much resources are available on a node vs what a pod requires. So without setting these, all Kubenetes can base things on is number of pods on a node, which means it could overload a specific node with pods which actually require more CPU than node can provide.Graham Dumpleton
In other words, this information helps Kubernetes work out best where to schedule things.Graham Dumpleton
While all you said is not incorrect, the underlying motivation is missing: it's about guarantees (like: what gets scheduled, OOMed, etc.). Have a look what Tim Hockin, the ultimate capacity in this space, has to say about this topic in his KubeCon talk 'Everything You Ever Wanted To Know About Resource Scheduling' with this slide deck and this video.Michael Hausenblas

1 Answers

3
votes

Kubernetes in Action 1st Edition by Marko Luksa

14.1.3. Understanding how CPU requests affect CPU time sharing

But if one container wants to use up as much CPU as it can, while the other one is sitting idle at a given moment, the first container will be allowed to use the whole CPU time (minus the small amount of time used by the second container, if any). After all, it makes sense to use all the available CPU if no one else is using it, right? As soon as the second container needs CPU time, it will get it and the first container will be throttled back.

enter image description here


Even when 2 CPU are available (no other process/container waiting) and a container is runnable, it can only use 0.5 CPU, and 1.5 CPU will be left unused. Is this correct?

So this is correct.