资源限制
默认情况下,在Docker中一个容器是没有任何资源限制的,因此它几乎能够耗尽Docker Host之上能够分配的所有资源,宿主机能调度多少,它就能使用多少;
在此基础之上,Docker提供了一个途径控制内存、CPU,因为内存是不可压缩性资源,而CPU则是可压缩性资源,所以当一个容器内的进程耗尽内存,并且申请更多的时候可能会导致OOM,而CPU没关系,另外这些所谓的资源限制,依赖于Linux Kernel capabilities来实现;
Memory
在Linux主机之上,如果Linux内核探测到当前宿主机已经没有足够内存可用,导致无法实现某些重要的系统功能,那么它就会抛出一个OOME的异常,并且开始启动去killing 某些 processes 以释放内存资源,一旦发生OOME任何进程都有可能被杀死,甚至docker daemon也会,为此Docker特地调整了Docker daemon的OOM优先级,以免被内核杀死,但容器的优先级并未调整,所以容器则有可能在宿主机上运行的这个进程;
Docker可以强制执行硬内存限制,允许容器使用不超过给定数量的用户或系统内存或软限制,这允许容器使用尽可能多的内存,除非满足某些条件,例如内核检测到主机上的低内存或争用。当单独使用或设置了多个选项时,其中一些选项会产生不同的效果;
大部分的选项取正整数,跟着一个后缀b,k, m,g,,表示字节,千字节,兆字节或千兆字节;
选项 |
描述 |
-m or –memory= |
容器可以使用的最大内存量。如果设置此选项,则允许的最小值为4m。 |
–memory-swap* |
允许此容器交换到磁盘的内存量,*表示可以用设置更多的值,必须先设置-m才能设置此项。 |
–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杀手。如果-m 未设置该标志,则主机可能会耗尽内存,并且内核可能需要终止主机系统的进程才能释放内存。 |
–memory-swap
--memory-swap是一个修饰符标志,只有在--memory设置时才有意义。使用swap允许容器在容器耗尽可用的所有RAM时将多余的内存需求写入磁盘。对于经常将内存交换到磁盘的应用程序,性能会受到影响;
–memory-swap |
–memory |
功能 |
正数S |
正数M |
容器可用总资源为S,其中ram为M,swap为(S-M),若S=M,则无可用swap资源 |
0 |
正数M |
相当于未设置swap(unset) |
unset |
正数M |
若Docker主机启用了swap,则容器可用swap为2*M |
-1 |
正数M |
若Docker主机企业了swap,则容器可用swap为Docker主机最大可分配的swap资源 |
注意:在容器内使用free命令可以看到的swap空间并不具有其所展现出的空间指示意义 |
–memory-swappiness
1、值为0将关闭匿名页面交换;
2、值100将所有匿名页面设置为可交换;
3、默认情况下,如果未设置--memory-swappiness,则值将从主机继承;
–kernel-memory
内核内存限制以分配给容器的总内存表示。请考虑以下方案:
无限内存,无限内核内存:这是默认设置。
无限内存,有限的内核内存:当所有cgroup所需的内存量大于主机上实际存在的内存量时,这是合适的。您可以将内核内存配置为永远不会覆盖主机上可用的内容,而需要更多内存的容器需要等待它。
有限的内存,无限的内核内存:整体内存有限,但内核内存不受限制。
有限的内存,有限的内核内存:限制用户和内核内存对于调试与内存相关的问题非常有用。如果容器使用意外数量的任一类型的内存,则内存不足而不会影响其他容器或主机。在此设置中,如果内核内存限制低于用户内存限制,则内核内存不足会导致容器遇到OOM错误。如果内核内存限制高于用户内存限制,则内核限制不会导致容器遇到OOM。
当您打开任何内核内存限制时,主机会根据每个进程跟踪“高水位线”统计信息,因此您可以跟踪哪些进程(在本例中为容器)正在使用多余的内存。通过/proc/<PID>/status在主机上查看,可以在每个过程中看到这一点。
CPU
默认情况下,每个容器对主机CPU周期的访问权限是不受限制的。
您可以设置各种约束来限制给定容器访问主机的CPU周期。
大多数用户使用和配置 默认CFS调度程序。
在Docker 1.13及更高版本中,您还可以配置 实时调度程序。
配置默认CFS调度程序
CFS是用于普通Linux进程的Linux内核CPU调度程序。多个运行时标志允许您配置容器具有的CPU资源访问量。使用这些设置时,Docker会修改主机上容器的cgroup的设置。
选项 |
描述 |
–cpus=<value> |
指定容器可以使用的可用CPU资源量。例如,如果主机有两个CPU并且你已设置–cpus=”1.5″,则容器最多保证一个半CPU。这相当于设置–cpu-period=”100000″ 和 –cpu-quota=”150000″。可在Docker 1.13及更高版本中使用。 |
–cpu-period=<value> |
指定CPU CFS调度程序周期,它与并用 –cpu-quota。默认为100微秒。大多数用户不会更改默认设置。如果您使用Docker 1.13或更高版本,请–cpus 使用。 |
–cpu-quota=<value> |
对容器施加CPU CFS配额。–cpu-period限制前容器限制为每秒的微秒数。作为有效上限。如果您使用Docker 1.13或更高版本,请–cpus改用。 |
–cpuset-cpus |
限制容器可以使用的特定CPU或核心。如果您有多个CPU,则容器可以使用逗号分隔列表或连字符分隔的CPU范围。第一个CPU编号为0.有效值可能是0-3(使用第一个,第二个,第三个和第四个CPU)或1,3(使用第二个和第四个CPU)。 |
–cpu-shares |
将此标志设置为大于或小于默认值1024的值,以增加或减少容器的重量,并使其可以访问主机的CPU周期的较大或较小比例。仅在CPU周期受限时才会强制执行此操作。当有足够的CPU周期时,所有容器都会根据需要使用尽可能多的CPU。这样,这是一个软限制。–cpu-shares不会阻止容器以群集模式进行调度。它为可用的CPU周期优先考虑容器CPU资源。它不保证或保留任何特定的CPU访问权限。 |
Memory资源限制
可以看到下图,启动了3个吃内存的线程,而后使用stats查看可以看出,容器做了内存限制,最大吃512Mib内存,实际上已经吃了511.9Mib内存;
CPU资源限制
可以从第一张图看出,docker对容器做了限制,最多使用2颗CPU,并且之能在CPU0、CPU2上使用,并且stress运行10个吃CPU的进程,结合第二张图可以看到,CPU0、CPU2均已饱和;