官方文档:https://docs.docker.com/config/containers/resource_constraints/
默认情况下,容器没有资源约束,可以使用主机内核调度器允许的给定资源。Docker提供了控制容器可以使用多少内存或CPU的方法,设置Docker run命令的运行时配置标志。本节详细介绍了何时应设置此类限制以及设置这些限制可能带来的影响。
这些特性中的许多都要求内核支持Linux功能。要检查支持,可以使用docker info命令。如果内核中禁用了某个功能,您可能会在输出末尾看到如下警告:
WARING: No swap limit support
linux OOM机制
Linux 会为每个进程算一个分数,最终它会将分数最高的进程kill
/proc/PID/oom_score_adj 范围在-1000到1000,值越高越容易被宿主机kill掉,如果将该值设置为-1000,则进程永远不会被宿主机kernel kill掉。
/proc/PID/oom_adj 范围为-17到+15,取值越高越容易被kill掉,如果是-17,则表示不能被kill,该设置参数的存在是为了和旧版本的Linux内核兼容。
/proc/PID/oom_score 这个值是系统综合进程的内存消耗量、CPU时间(utime+stime)、存活时间(uptime-start time)和oom_adj计算出的进程得分,消耗内存越多得分越高,越容易被宿主机kernel强制杀死。
docker内存限制
内存限制参数
选项 | 描述 |
---|---|
-m 或者 --memory= | 容器可以使用的最大内存量。如果设置此选项,则允许的最小值为4m(4 兆字节) |
–memory-swap* | 允许此容器交换到磁盘的内存量。查看–memory-swap详情。必须要在设置了物理内存(上一个选项)限制的前提才能设置交换分区限制。 |
–memory-swappiness | 默认情况下,主机内核可以换出容器使用的匿名页面的百分比。您可以设置–memory-swappiness为 0 到 100 之间的值来调整此百分比,0是能不用交换分区就不用交换分区,100是能用交换分区就用交换分区。查看–memory-swappiness详情。 |
–memory-reservation | 允许您指定的软限制小于–memory当 Docker 检测到主机上的争用或内存不足时激活该限制。如果使用–memory-reservation,则必须将其设置为低于–memory以使其优先。因为是软限制,所以不保证容器不超过限制。 |
–kernel-memory | 容器可以使用的最大内核内存量。允许的最小值为4m。由于内核内存与用户空间内存隔离,因此无法与用户空间内存直接交换,因此内核内存不足的容器可能会阻塞主机资源,这会对主机和其他容器产生副作用。查看–kernel-memory详情。 |
–oom-kill-disable | 默认情况下,如果发生内存不足 (OOM) 错误,内核会终止容器中的进程。要更改此行为,请使用该–oom-kill-disable选项。仅在您也设置了该-m/–memory选项的容器上禁用 OOM 杀手。如果-m未设置该标志,主机可能会耗尽内存,内核可能需要终止主机系统的进程以释放内存。 |
swap限制
–memory-swap 只有在设置了 --memory后才会有意义。使用swap,可以让容器将超出限制部分的内存置换到磁盘上,WARNING:经常将内存交换到磁盘的应用程序会降低性能。
不同的–memory-swap设置会产生不同的效果
–memory-swap 值为正数,那么–memory和–memory-swap都必须要设置,–memory-swap表示你能使用的内存和swap分区大小的总和,例如:–memory=300m,–memory-swap=1g,那么该容器能够使用300m内存和700m swap,即–memory是实际物理内存大小值不变,而swap的实际大小计算方式为(–memory-swap)-(–memory)=容器可用swap。
–memory-sawp 如果设置为0,则忽略该设置,并将该值视为未设置,即为设置交换分区。
–memory-swap 如果等于–memory的值,并且–memory设置为正整数,容器无权访问swap即也没有设置交换分区。
–memory-swap 如果设置为unset,如果宿主机开启了swap,则实际容器的swap值2*(–memory),即两倍于物理内存大小,但是并不准确(在容器中使用free命令所看到的swap空间并不精确,毕竟每个容器都可以看到具体大小,但是宿主机的swap是有上限而且不是所有容器看到的累计大小)。
内存限制
内存硬限制
docker run -d -it -m 512m -p 80:8080 --name tomcat-web tomcat:8.15
容器运行时可以在文件中修改
cat /sys/fs/cgroup/memory/docker/dockerID/memory.limit_in_bytes
内存软限制
docker run -d -it -m 512m --memory-reservation 256m -p 80:8080 --name tomcat-web tomcat:8.15
容器运行时可以在文件中修改
cat /sys/fs/cgroup/memory/docker/dockerID/memory.soft_limit_in_bytes
关闭oom机制
docker run -d -it -m 512m --oom-kill-disable -p 80:8080 --name tomcat-web tomcat:8.15
容器运行时可以在文件中修改
cat /sys/fs/cgroup/memory/docker/dockerID/memory.oom_control
限制交换分区
docker run -d -it -m 512m --memory-swap 1024m -p 80:8080 --name tomcat-web tomcat:8.15
容器运行时可以在文件中修改
cat /sys/fs/cgroup/memory/docker/dockerID/memory.memsw.limit_in_bytes
docker CPU限制
linux CPU
同一个单位时间内只能有一个进程在CPU上运行,那么这么多的进程怎么在CPU上执行和调度的呢
实时优先级:0-99
非实时优先级(nice):-20-19,对应100-139的进程优先级。
Linux kernel进程的调度基于CFS(Completely Fair Scheduler),完全公平调度(基于使用时间调度)
CPU密集型的场景:优先级越低越好,计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、数据处理、对视频进行高清解码等等,全是靠CPU运算能力。
IO密集型的场景:优先级值高点,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO速度远远低于CPU和内存的速度),比如Web应用,高并发,数据量大的动态网站来说,数据库应该为IO密集型。
磁盘的调度算法
cat /sys/block/sda/queue/scheduler
CPU
默认情况下,每个容器对祖籍CPU周期的访问权限是不受限制的,但是我们可以设置各种约束来限制给定容器访问主机的CPU周期,大多数拥挤使用的是默认的CFS调度方式,在Docker1.13及更高版本中,还可以配置实时优先级。
CPU参数:
–cpus 指定容器可以使用多少可用CPU资源,例如,如果主机有两个CPU,并且设置了–cpus=“1.5”,那么该容器将保证最多可以访问1.5个的CPU(如果是4核CPU,那么还可以是4核心上每核用一点,但是总计是1.5核心的CPU),这相当于设置–cpu-period="100000"和–cpu-quota=“150000”,–cpus主要在Docker1.13和更高版本中使用,目的是替代–cpu-period和–cpu-quota两个参数,从而使配置更简单,但是最大不能超出宿主机的CPU总核心数(在操作系统看到的CPU超线程后的数值)。
docker run -it --rm --cpus 2 centos bash
docker: Error response from daemon: Range of CPUs is from 0.01和1.00,as there are only 1 CPUs available.
See ‘docker run --help’ 分配给容器的CPU超出了宿主机CPU总数。
–cpu-period (CPU调度周期)设置CPU的CFS调度程序周期,必须与–cpu-quota一起使用,默认周期为100微秒。
(1Second=1000Millisecond=1000000Microsecond)
–cpu-quota 在容器上添加CPU CFS配额,计算方式为cpu-quota/cpu-period的结果值,早期的docker(1.12之前)使用此方式设置对容器的CPU限制值,新版本docker(1.13版本以上)通常使用–cpus设置此值。
–cpuset-cpus 用于指定容器运行的CPU编号,也就是我们所谓的绑核。
–cpuset-mem 设置使用那个CPU的内存,仅对非同一内存访问(NUMA)架构有效。
–cpu-shares 用于设置cfs中调度的相对最大比例权重,cpu-share的值越高的容器,将会分得更多的时间片(宿主机多核CPU总数为100%),假如容器A为1024,容器B为2048,那么容器B将最大是容器A可用CPU的两倍),默认的时间片1024,最大262214。
CPU限制
CPU资源限制是将分配给容器的2个核心分配到了宿主机每一核心CPU上,也就是容器的总CPU值是在宿主机的每一个核心CPU分配了部分比例。
限制CPU
docker run -d -it --cpus 2 -p 80:8080 --name tomcat-web tomcat:8.15
容器运行时可以在文件中修改
cat /sys/fs/cgroup/memory/docker/dockerID/cpu.cfs_quota_us
#每核心CPU会按照1000为单位转换成百分比进行资源划分,2个核心的CPU就是200000/1000/200%,4个核心400000/1000=400%,以此类推。
绑定CPU
docker run -d -it --cpus 2 --cpuset-cpus 2,3 -p 80:8080 --name tomcat-web tomcat:8.15
表示运行在第2和3核心上(从0开始的)
容器运行时可以在文件中修改
cat /sys/fs/cgroup/memory/docker/dockerID/cpuset.cpus
基于权重分配
docker run -d -it --cpus 2 --cpu-shares 100 -p 80:8080 --name tomcat-web tomcat:8.15
容器运行时可以在文件中修改
cat /sys/fs/cgroup/memory/docker/dockerID/cpu.shares