20.Docker资源限制
docker资源限制
https://docs.docker.com/config/containers/resource_constraints/
默认情况下,容器没有资源限制,并且可以使用主机内核调度程序允许的尽可能多的给定资源。Docker提供了一些方法来控制容器可以使用多少内存或CPU,从而设置docker run
命令的运行时配置标志。
其中许多功能都要求您的内核支持Linux功能。要检查支持,可以使用 docker info
命令。如果您的内核中禁用了功能,则可能在输出末尾看到警告,如下所示:
WARNING: No swap limit support
对于Linux主机,如果没有足够的内存来执行系统任务,就会抛出OOM(Out of Memory Exception,内存溢出、内存泄漏)随后系统会开始杀死进程以释放内存,凡是运行在宿主机的进程都可能被kill,如果主要的系统进程被Kill,会导致和该进程相关的服务全部宕机;产生OOM异常时,Docker创世通过调整守护进程上的OOM优先级来减轻风险,以便它比其他进程更不可能被杀死;不推荐通过守护进程或容器上手动设置--oom-score-adj
为极端负数,或通过在容器上设置--oom-kill-disable
来绕过安全措施。
OOM优先级机制
Linux会为每个进程算一个分数,最终它会将分数最高的进程kill。
#范围为-1000到1000,值越高越容易被宿主机kill,如果设置为-1000,进程永远不会被宿主机kernel kill
/proc/PID/oom_score_adj
#范围从-17到+15,取值越高越容易被干掉,如果是-17表示不能被kill,该参数的存在是为了和旧版本Linux内核兼容
/proc/PID/oom_adj
#这个值是系统综合进程的内存消耗量、CPU时间(Utime+stime)、存活时间(uptime- start time)和oom_adj计算出的进程得分,消耗内存越多得分越高,越容易被主机kernel强制杀死
/proc/PID/oom_score
内存限制
Option | Description |
---|---|
-m or --memory= |
容器可以使用的最大内存量。如果设置此选项,则允许的最小值为“4m”(4 MB)。 |
--memory-swap * |
此容器允许交换到磁盘的内存量,必须要在设置了物理内存限制的前提下才能设置交换分区限制。 |
--memory-swappiness |
默认情况下,设计容器使用交换分区的倾向。您可以将“-memory swappeiness”设置为0到100之间的值,以调整此百分比。值越高越倾向使用 |
--memory-reservation |
允许您指定小于“-memory”的软限制,当Docker检测到主机上存在争用或内存不足时,将激活该限制。如果使用“-memory reservation”,则必须将其设置为低于“-memory”,才能使其优先。因为这是一个软限制,它不能保证容器不超过限制。 |
--kernel-memory |
容器可以使用的最大内核内存量。允许的最小值为“4m”。由于内核内存与用户空间内存隔离,因此无法与用户空间内存直接交换,因此内存内核不足的容器可能会阻塞主机资源,这可能会对主机和其他容器产生影响,因此建议不要设置。 |
--oom-kill-disable |
默认情况下,如果发生内存不足(OOM)错误,内核将终止容器中的进程。要更改此行为,请使用“-oom kill disable”选项。仅在还设置了“-m/--memory”选项的容器上禁用OOM killer。如果没有设置“-m”标志,主机可能会耗尽内存,内核可能需要终止主机系统的进程以释放内存。 |
--oom-score-adj |
宿主机kernel对进程使用的内存进行评分,评分较高的将被内核kill掉,可以指定一个容器的评分,但不推荐 |
内存限制验证
#测试镜像
docker pull lorel/docker-stress-ng
#查看帮助
docker run -it --rm lorel/docker-stress-ng --help
内存大小硬限制
#启动两个工作进程,每个进程最大允许使用内存256M,且宿主机不限制当前容器最大内存
docker run -it --rm --name limittest001 lorel/docker-stress-ng --vm 2 --vm-bytes 256M
docker stats
#宿主机限制容器最大内存
docker run -it --rm -m 256m --name limittest002 lorel/docker-stress-ng --vm 2 --vm-bytes 256M
docker stats
#宿主机cgroup验证(单位 字节)
cat /sys/fs/cgroup/memory/docker/{conrainer ID}/memory.limit_in_bytes
#或者使用echo修改、一般只能增加;缩小内存会报错write error:Divice or resource busy
echo 268435456 > /sys/fs/cgroup/memory/docker/{conrainer ID}/memory.limit_in_bytes
内存大小软限制
#软限建议小于硬限制
docker run -it --rm --name limittest003 --memory-reservation 512m lorel/docker-stress-ng --vm 2 --vm-bytes 256m
#宿主机cgroup验证
cat /sys/fs/cgroup/memory/docker/{conrainer ID}/memory.soft_limit_in_bytes
关闭OOM机制
#需要有限制才可关闭
dokcer run -it --rm --name limittest004 --oom-kill-disable nginx:web
WARNING: Disabling the OOM killer on containers without setting a '-m/--memory' limit may be dangerous.
docker run -it --rm -m 256m --name limittest004 --oom-kill-disable nginx:web
#宿主机cgroup验证
cat /sys/fs/cgroup/memory/docker/{conrainer ID}/memory.oom_control
限制交换分区
#不建议使用
docker run -it --rm -m 1024m --name limittest005 --memory-swap 2048m nginx:web
#宿主机cgroup验证
cat /sys/fs/cgroup/memory/docker/{conrainer ID}/memory.memsw.limit_in_bytes
CPU限制
同一个单位时间内只能有一个进程在CPU上运行,那么这么多进程怎么在CPU上执行和调度呢?
-
实时优先级:
0 - 99
-
非实时优先级(nice):
-20 - 19
对应100-139的进程优先级
Linux kernel进程的调度基于CFS(Completey Fair Scheduler),完全公平调度
场景 | 优先级 | 说明 |
---|---|---|
CPU密集型场景 | 越低越好 | 计算密集型任务的特点是要进行大量的计算,消耗CPU资源;比如数据处理、对视频进行高清解码等 |
IO密集型场景 | 较高 | 涉及到网络、硬盘IO的任务都是IO密集型任务,这类任务消耗CPU较少,任务大部分时间都在等待IO操作完成;比如web应用,高并发,数据量大的动态网站;数据库 |
硬盘调度算法
cat /sys/block/sda/queue/sheduler
noop deadline [cfq]
#noop算法不进行优化,使用原生硬盘IO 建议ssd盘使用
#deadline sata盘建议使用
#cfq默认基于时间
Option | Description |
---|---|
--cpus=<value> |
指定容器可以使用多少可用CPU资源。例如,如果主机有两个cpu,并且您设置了“-CPUs=”1.5“,那么容器最多保证有一个半cpu。这相当于设置 --cpu period=“100000”和 --cpu quota=“150000”`。 |
--cpu-period=<value> |
指定CPU CFS调度程序周期,与“-CPU配额”一起使用。默认为100000微秒(100毫秒)。大多数用户不会更改默认设置。对于大多数用例,--cpu 是一个更方便的选择。 |
--cpu-quota=<value> |
对容器施加CPU CFS配额。计算方式为cpu-quota/cpu-period的结果,早起使用(docker1.12及以前)使用此方法限制CPU限制值,新版本docker(docker1.13及以上版本)通常使用--cpus |
--cpuset-cpus |
限制容器可以使用的特定CPU或核心。如果您有多个CPU,则容器可以使用以逗号分隔的列表或以连字符分隔的CPU范围。第一个CPU编号为0。有效值可以是“0-3”(使用第一、第二、第三和第四个CPU)或“1,3”(使用第二和第四个CPU)。 |
--cpu-shares |
用于设置cfs中调度的相对最大比例权重,cpu-share的值越高的容器,将会分得更多的时间片默认时间片1024,最大262144 |
CPU限制验证
#测试镜像
docker pull lorel/docker-stress-ng
#查看帮助
docker run -it --rm --name limittest lorel/docker-stress-ng --vm 4
docker stats
#查看CPU限制
cat /sys/fs/cgroup/cpuset/docker/{conrainer ID}/cpuset.cpus
#进行限制
docker run -it --rm --name limittest -cpus 2 lorel/docker-stress-ng --cpu 4 --vm 4
将容器运行在指定的CPU上
docker run -it --rm --name limittest -cpus 2 --cpuset-cpus 1,3 lorel/docker-stress-ng --cpu 4 --vm 4
#手工修改
echo "0,2-3" > /sys/fs/cgroup/cpuset/docker/{conrainer ID}/cpuset.cpus
基于cpu-share对CPU进行切分
#启动两个容器
docker run -it --rm --name limittest001 --cpu-shares 1024 lorel/docker-stress-ng --cpu 4 --vm 4
docker run -it --rm --name limittest002 --cpu-shares 2048 lorel/docker-stress-ng --cpu 4 --vm 4
#查看CPU限制
cat /sys/fs/cgroup/cpuset/docker/{conrainer ID}/cpu.shares
#手工修改
echo 1024 > /sys/fs/cgroup/cpuset/docker/{conrainer ID}/cpu.shares