By default, the container can use unlimited host CPU resources. As with memory resources, if there is no limit on the CPU resources that can be used by the container, it is likely to exhaust the CPU resources of the entire host in the event of abnormal CPU usage by the application in the container, leading to a greater disaster. This article shows you how to limit the CPU resources a container can use.

In the demo of this article, we will continue to use the Docker image U-stress created in the article “Docker: Limit the memory available to containers” for stress testing, and the article will not explain too much.

Limit the number of available cpus

On Docker 1.13 and later, it’s easy to limit the number of host cpus a container can use. You only need to specify the number of cpus the container can use with the –cpus option, and you can also specify a decimal such as 1.5. Let’s do a demo on a host with four cpus and a low load:

Create a container with –cpus=2 indicating that the container can use up to two cpus on the host:


     
  1. $ docker run -it --rm --cpus=2 u-stress:latest /bin/bash

Copy the code

Then create four busy processes using the stress command to consume CPU resources:


     
  1. # stress -c 4

Copy the code

Let’s first look at the output of the docker stats command:

The container CPU is loaded at 200%, which means twice the load of a single CPU. We can also think of it as having two cpus working for it at 100%.

Let’s take a look at the actual load of the host CPU using the top command:

Ha ha, a bit of a surprise! The actual situation is not that two cpus are 100% loaded and the other two 0%. All four cpus are at 50% load, so the total amount of CPU consumed by the container is 100% of the load of both cpus.

It seems that there is no such thing as a number of cpus for a process. The kernel can only calculate the percentage of CPU consumed by a process by the CPU time slice. This is why the various tools we see use percentages to illustrate CPU usage.

For rigor, let’s take a look at the official Docker documentation to explain the –cpus option:

Specify how much of the available CPU resources a container can use.

Sure enough, they use “how much”. And — the cpus option supports decimal values to indicate that the CPU can only be measured as a percentage.

It seems that the “number of cpus” I wrote in this article are inaccurate. Why use it if it’s not accurate? Easy to understand, of course. In addition, I don’t think there is any problem with “number of cpus” in the context of –cpus (read the origin of –cpus, which is also intended in the first place, if you are interested).

Although the –cpus option is fun to use, it was only supported in 1.13. For earlier versions to do the same thing we used two options: –cpu-period and –cpu-quota(versions 1.13 and later still support both options). The following command achieves the same result:


     
  1. $ docker run -it --rm --cpu-period=100000 --cpu-quota=200000 u-stress:latest /bin/bash

Copy the code

Such configuration option is not let a person very silly ah! What is 100,000? What’s 200,000? They are measured in microseconds, 100,000 for 100 milliseconds and 200,000 for 200 milliseconds. What they mean here is that the running process takes up to 200 milliseconds of CPU time for every 100 milliseconds (requiring two cpus to perform 100 milliseconds each). CFS BandWith Control is a good guide for those who want to understand both options thoroughly. We need to know that these two options are the truth of the matter, but the truth is often cruel! Thankfully, the –cpus option works, and it packs –cpu-period and –cpu-quota.

Specify a fixed CPU

We can’t make the container run on one or more cpus all the time with the –cpus option, but we can with the –cpuset-cpus option! This makes sense because in today’s multi-core systems, each core has its own cache, and frequent schedulers running on different cores will inevitably incur costs such as cache invalidation. To demonstrate how to set a container to use a fixed CPU, the following command sets the –cpuset-cpus option for the container, specifying the CPU number of the container to run as 1:

                                        
     
  1. $ docker run -it -- rm --cpuset -cpus= "1" u-stress :latest /bin /bash

Copy the code

Relaunch the stress test command:


     
  1. # stress -c 4

Copy the code

Then check the load of the host CPU:

This time only Cpu1 reached 100%, the other cpus were not used by the container. Stress -c 4 can be executed repeatedly, but Cpu1 is always doing the work.

The CPU load of the container is only 100% :

The –cpuset-cpus option also specifies more than one CPU at a time:


     
  1. $docker run it --rm --cpuset-cpus="1,3" u-stress:latest /bin/bash

Copy the code

Run the stress -c 4 command to check the host CPU load:

Both Cpu1 and Cpu3 are 100% loaded. The container’s CPU load is also 200% :

A disadvantage of the cpuset-cpus option is that cpus must be numbered on the operating system, which can be inconvenient in dynamically scheduled environments (where the container cannot predict which hosts it will run on, but only dynamically detects the CPU number on the system and generates docker run commands).

Set the CPU weight

When CPU resources are abundant, it makes no sense to set CPU weights. Only if containers compete for CPU resources can CPU weights be assigned to different containers for different CPU usage. The cpu-shares option is used to set the CPU weight, which defaults to 1024. We can set it to 2 to indicate a very low weight, but 0 to use the default value 1024.

Let’s run the two containers separately, specify that they both use Cpu0 and set –cpu-shares to 512 and 1024, respectively:


     
  1. $ docker run -it --rm --cpuset-cpus="0" --cpu-shares=512 u-stress:latest /bin/bash

  2. $ docker run -it --rm --cpuset-cpus="0" --cpu-shares=1024 u-stress:latest /bin/bash

Copy the code

Run the stress -c 4 command in both containers.

The load of host Cpu0 is 100% :

The load of the CPU in the container is:

Two containers share one CPU, so the total amount should be 100%. How much load each container gets depends on how the CPU-Shares option is set! Our Settings are 512 and 1024, so the ratio is 1:2. In this case, if you want 50% of each container, just set the — CPU-Shares option to the same value.

Four,

Limiting the CPU option is much cleaner than limiting the memory used by the container. But simplicity is definitely not simplicity, and most processes that simplify something complex lose detail or blur concepts, such as the evolution from –cpu-period and –cpu-quota to –cpus. This is certainly a good thing for users to slow down our learning curve and get started quickly.

Original: https://www.cnblogs.com/sparkdev/p/8052522.html