3

docker容器资源限制:限制容器对内存/CPU的访问 - 人生的哲理

 2 years ago
source link: https://www.cnblogs.com/renshengdezheli/p/16662622.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一.系统环境

服务器版本 docker软件版本 CPU架构
CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 x86_64

默认情况下,容器没有资源限制,并且可以使用主机内核调度程序允许的尽可能多的给定资源。Docker 提供了控制容器可以使用多少内存或 CPU 的方法。

三.docker对于CPU和内存的限制

3.1 限制容器对内存的访问

重要的是不要让正在运行的容器消耗过多的主机内存。在 Linux 主机上,如果内核检测到没有足够的内存来执行重要的系统功能,它会抛出一个OOME或 Out Of Memory Exception,并开始杀死进程以释放内存。任何进程都可能被杀死,包括 Docker 和其他重要的应用程序。如果错误的进程被杀死,这可以会导致关闭整个系统。

Docker 可以强制执行内存硬限制,允许容器使用不超过给定数量的用户或系统内存,或软限制,允许容器根据需要使用尽可能多的内存,除非满足某些条件,例如何时内核检测到主机内存不足或争用。其中一些选项在单独使用或设置多个选项时具有不同的效果。这些选项中的大多数采用正整数,后跟b, k, m, g, 后缀来表示字节、千字节、兆字节或千兆字节。

常用的参数有

参数 参数解释
-m或者--memory= 容器可以使用的最大内存量。如果设置此选项,则允许的最小值为6m(6 兆字节)。也就是说,您必须将该值设置为至少 6 兆字节。
--memory-swap* 允许此容器交换到磁盘的内存量。
--memory-swappiness 默认情况下,主机内核可以换出容器使用的一定百分比的匿名页面。您可以设置--memory-swappiness为 0 到 100 之间的值,以调整此百分比。
--memory-reservation 允许您指定一个小于--memory在 Docker 检测到主机上的争用或内存不足时激活的软限制。如果使用--memory-reservation,则必须将其设置为低于--memory它才能优先。因为是软限制,所以不保证容器不超过限制。
--kernel-memory 容器可以使用的最大内核内存量。允许的最小值是4m。因为内核内存不能被换出,内核内存不足的容器可能会阻塞主机资源,这会对主机和其他容器产生副作用。
--oom-kill-disable 默认情况下,如果发生内存不足 (OOM) 错误,内核会终止容器中的进程。要更改此行为,请使用该--oom-kill-disable选项。仅在您还设置了该-m/--memory选项的容器上禁用 OOM kill。如果-m未设置该标志,主机可能会耗尽内存,内核可能需要终止主机系统的进程以释放内存。

本次主要使用hub.c.163.com/library/centos:latest镜像测试,没有该镜像需要自己docker pull一下

[root@k8smaster harbor]# docker images
REPOSITORY                                                        TAG        IMAGE ID       CREATED         SIZE
hub.c.163.com/library/centos                                      latest     328edcd84f1b   4 years ago     193MB

上传memload-7.0-1.r29766.x86_64.rpm安装包,用于模拟内存的使用

[root@k8smaster ~]# mkdir /memload

[root@k8smaster ~]# mv memload-7.0-1.r29766.x86_64.rpm /memload/

使用centos创建一个临时容器,-v /memload:/memload进行数据卷挂载,使容器/memload目录下有memload-7.0-1.r29766.x86_64.rpm安装包

[root@k8smaster ~]# docker run -it --rm -v /memload:/memload hub.c.163.com/library/centos:latest

#在容器里安装memload
[root@3c9083a7b318 /]# rpm -ivh /memload/memload-7.0-1.r29766.x86_64.rpm 
Preparing...                          ################################# [100%]
Updating / installing...
   1:memload-7.0-1.r29766             ################################# [100%]

#memload 1000使内存使用1000M
[root@3c9083a7b318 /]# memload 1000
Attempting to allocate 1000 Mebibytes of resident memory...
^C

[root@3c9083a7b318 /]# exit
exit

当在容器执行memload 1000时,打开另外一个Linux终端,使用docker stats查看该容器的内存使用,发现此容器使用了1013MiB内存,3.32GiB表示物理机的最大内存

CONTAINER ID   NAME                                                                                                            CPU %     MEM USAGE / LIMIT    MEM %     NET I/O           BLOCK I/O         PIDS
3c9083a7b318   friendly_roentgen                                                                                               100.71%   1013MiB / 3.32GiB    29.79%    648B / 0B         32.5MB / 19.5MB   2

使用-m对容器的内存进行限制,-m 512m:表示容器内存最大使用512M,这时如果我们执行memload 1000,使用docker stats查看,最大内存也只能是512M

[root@k8smaster ~]# docker run -it --rm -m 512m -v /memload:/memload hub.c.163.com/library/centos:latest
[root@a81686360ba1 /]# 
[root@a81686360ba1 /]# exit
exit

3.2 限制容器对CPU的访问

默认情况下,每个容器对主机 CPU 周期的访问是无限制的。您可以设置各种约束来限制给定容器对主机 CPU 周期的访问。大多数用户使用和配置 默认的 CFS 调度程序。您还可以配置实时调度程序。

CFS 是用于普通 Linux 进程的 Linux 内核 CPU 调度程序。几个运行时标志允许您配置对容器拥有的 CPU 资源的访问量。当您使用这些设置时,Docker 会修改主机上容器的 cgroup 的设置。

常用的参数有

参数 参数解释
--cpus= 指定容器可以使用多少可用 CPU 资源。例如,如果主机有两个 CPU,并且您设置--cpus="1.5"了 ,则容器最多可以保证一个半的 CPU。这相当于设置--cpu-period="100000"和--cpu-quota="150000"。
--cpu-period= 指定 CPU CFS 调度程序周期,它与 --cpu-quota. 默认为 100000 微秒(100 毫秒)。大多数用户不会更改默认设置。对于大多数用例,--cpus是一种更方便的选择。
--cpu-quota= 对容器施加 CPU CFS 配额。--cpu-period容器在被限制之前被限制的每微秒数。因此充当有效上限。对于大多数用例,--cpus是一种更方便的选择。
--cpuset-cpus 限制容器可以使用的特定 CPU 或内核。如果您有多个 CPU,则容器可以使用的逗号分隔列表或连字符分隔的 CPU 范围。第一个 CPU 编号为 0。有效值可能是0-3(使用第一个、第二个、第三个和第四个 CPU)或1,3(使用第二个和第四个 CPU)。
--cpu-shares 将此标志设置为大于或小于默认值 1024 的值,以增加或减少容器的重量,并允许它访问或多或少比例的主机 CPU 周期。这仅在 CPU 周期受到限制时才会强制执行。当有足够多的 CPU 周期可用时,所有容器都会根据需要使用尽可能多的 CPU。这样,这是一个软限制。--cpu-shares不会阻止容器以 swarm 模式调度。它优先考虑可用 CPU 周期的容器 CPU 资源。它不保证或保留任何特定的 CPU 访问权限。

对CPU的限制一般是设置CPU的亲和性,查看cpu信息:两个CPU:On-line CPU(s) list: 0,1

[root@k8smaster ~]# lscpu 
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                2
On-line CPU(s) list:   0,1
Thread(s) per core:    1
Core(s) per socket:    2
座:                 1
NUMA 节点:         1
厂商 ID:           GenuineIntel
CPU 系列:          6
型号:              142
型号名称:        Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
步进:              10
CPU MHz:             1991.381
BogoMIPS:            3984.01
超管理器厂商:  VMware
虚拟化类型:     完全
L1d 缓存:          32K
L1i 缓存:          32K
L2 缓存:           256K
L3 缓存:           8192K
NUMA 节点0 CPU:    0,1
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec arat

使用centos镜像创建容器,里面运行5个cat进程

[root@k8smaster ~]# docker run -it --rm  -v /memload:/memload hub.c.163.com/library/centos:latest
[root@1a4fff793014 /]# 
[root@1a4fff793014 /]# cat /dev/zero > /dev/null &
[1] 15
[root@1a4fff793014 /]# cat /dev/zero > /dev/null &
[2] 16
[root@1a4fff793014 /]# cat /dev/zero > /dev/null &
[3] 17
[root@1a4fff793014 /]# cat /dev/zero > /dev/null &
[4] 18
[root@1a4fff793014 /]# cat /dev/zero > /dev/null &
[5] 19
[root@1a4fff793014 /]# exit 
exit

当在容器执行5个cat进程之后,打开另外一个Linux终端,查看每个cat进程运行在哪个CPU上,可以看到cat进程都运行在0号和1号CPU上

[root@k8smaster ~]# ps mo pid,comm,psr `pgrep cat`
   PID COMMAND         PSR
130120 cat               -
     - -                 0
130143 cat               -
     - -                 1
130144 cat               -
     - -                 0
130145 cat               -
     - -                 1
130146 cat               -
     - -                 1

--cpuset-cpus=0 设置容器里的进程都运行在0号CPU上

[root@k8smaster ~]# docker run -it --rm  --cpuset-cpus=0 -v /memload:/memload hub.c.163.com/library/centos:latest
[root@0c3b37f8e679 /]# cat /dev/zero > /dev/null &
[1] 15
[root@0c3b37f8e679 /]# cat /dev/zero > /dev/null &
[2] 16
[root@0c3b37f8e679 /]# cat /dev/zero > /dev/null &
[3] 17
[root@0c3b37f8e679 /]# cat /dev/zero > /dev/null &
[4] 18
[root@0c3b37f8e679 /]# cat /dev/zero > /dev/null &
[5] 19
[root@0c3b37f8e679 /]# 
[root@0c3b37f8e679 /]# exit
exit

--cpuset-cpus=1 设置容器里的进程都运行在1号CPU上

[root@k8smaster ~]# docker run -it --rm  --cpuset-cpus=1 -v /memload:/memload hub.c.163.com/library/centos:latest
[root@dac513abce35 /]# 
[root@dac513abce35 /]# cat /dev/zero > /dev/null &
[1] 15
[root@dac513abce35 /]# cat /dev/zero > /dev/null &
[2] 16
[root@dac513abce35 /]# 
[root@dac513abce35 /]# cat /dev/zero > /dev/null &
[3] 17
[root@dac513abce35 /]# cat /dev/zero > /dev/null &
[4] 18
[root@dac513abce35 /]# exit
exit

--cpuset-cpus=0,1 设置容器里的进程都运行在0,1号CPU上

[root@k8smaster ~]# docker run -it --rm  --cpuset-cpus=0,1 -v /memload:/memload hub.c.163.com/library/centos:latest
[root@244fe7eb8707 /]# cat /dev/zero > /dev/null &
[1] 15
[root@244fe7eb8707 /]# cat /dev/zero > /dev/null &
[2] 16
[root@244fe7eb8707 /]# cat /dev/zero > /dev/null &
[3] 17
[root@244fe7eb8707 /]# cat /dev/zero > /dev/null &
[4] 18
[root@244fe7eb8707 /]# cat /dev/zero > /dev/null &
[5] 19
[root@244fe7eb8707 /]# 
[root@244fe7eb8707 /]# exit
exit

--cpuset-cpus=0-7,14 设置容器里的进程都运行在0-7,14号CPU上,由于没有那么多CPU所以报错

[root@k8smaster ~]# docker run -it --rm  --cpuset-cpus=0-7,14 -v /memload:/memload hub.c.163.com/library/centos:latest
docker: Error response from daemon: Requested CPUs are not available - requested 0-7,14, available: 0-1.
See 'docker run --help'.

注意:还可以设置容器对NVIDIA GPU 的访问,不过目前暂时没用到。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK