Docker 容器资源管理,你真的学会了吗?( 四 )


而为了能够最快地进行选择,这里的逻辑也是尽可能的简单,除了明确标记不可杀掉的进程外,直接选择内存占用最多的进程 。(当然,还有一个额外的 oom_score_adj 可用于控制权重)
这种选择的最主要的两个好处是:
可以回收很多内存;可以避免缓解 OOM 后,该进程后续对内存的抢占引发后续再次的 OOM 。我们将注意力再回到 Docker 自身,在生产环境中,我们通常会用 Docker 启动多个容器运行服务 。当遇到 OOM 时,如果 Docker 进程被杀掉,那对我们的服务也会带来很大的影响 。
所以 Docker 在启动的时候默认设置了一个 -500 的 oom_score_adj 以尽可能地避免 Docker 进程本身被 OOM Killer 给杀掉 。
如果我们想让某个容器,尽可能地不要被 OOM Killer 杀掉,那我们可以给它传递 --oom-score-adj 配置一个比较低的数值 。
但是注意:不要通过 --oom-kill-disable 禁用掉 OOM Killer,或者给容器设置低于 dockerd 进程的 oom_score_adj 值,这可能会导致某些情况下系统的不稳定 。除非你明确知道自己的操作将会带来的影响 。
管理容器的内存资源
介绍完了 OOM,相比你已经知道了内存耗尽所带来的危害,我们来继续介绍如何管理容器的内存资源 。
(MoeLove)~ docker run --help |grep 'memory'--kernel-memory bytesKernel memory limit-m, --memory bytesMemory limit--memory-reservation bytesMemory soft limit--memory-swap bytesSwap limit equal to memory plus swap: '-1' to enable unlimited swap--memory-swappiness intTune container memory swappiness (0 to 100) (default -1)
可用的配置参数有上述几个,我们通常直接使用 --memory 参数来限制容器可用的内存大小 。我们同样使用几个示例进行介绍:
启动一个容器,并传递参数 --memory 10m 限制其可使用的内存为 10 m 。
(MoeLove)~ docker run --rm -it --memory 10m alpine/ #
那我们如何验证它的可用内存大小是多少呢?在物理机上,我们通常使用 free 工具进行查看 。但在容器环境内,它还是否生效呢?
/ # free -mtotalusedfreesharedbufferscachedMem:1593214491144118145643632-/+ buffers/cache:102945637Swap:84716937778
很明显,使用 free 得到的结果是宿主机上的信息 。当然,我们前面已经介绍了 docker stats 命令,我们使用它来查看当前的资源使用情况:
(MoeLove)~ docker stats --no-stream $(docker ps -ql)CONTAINER IDNAMECPU %MEM USAGE / LIMITMEM %NET I/OBLOCK I/OPIDSe260e91874d8busy_napier0.00%1.172MiB / 10MiB11.72%16.1kB /0B0B / 0B1
可以看到 MEM USAGE / LIMIT 那一列中的信息已经生效,是我们预期的样子 。
那我们是否还有其他方式查看此信息呢?当然有:
# 在容器内执行/ # cat /sys/fs/cgroup/memory/memory.limit_in_bytes 10485760
或者可以在宿主机上执行以下命令:
(MoeLove)~ cat/sys/fs/cgroup/memory/system.slice/docker-$(docker inspect --format '{{ .Id}}' $(docker ps -ql)).scope/memory.limit_in_bytes10485760
注意:以上命令在 Linux 5.2 内核下测试通过,不同版本之间目录结构略有差异 。
更新容器内存资源限制
当容器运行一段时间,其中的进程使用的内存变多了,我们想允许容器使用更多内存资源,那要如何操作呢?
我们仍然可以用前面介绍的 docker update 命令完成 。
比如使用如下命令,将可用内存扩大至 20m:
(MoeLove)~ docker update--memory 20m $(docker ps -ql)e260e91874d8# 验证是否生效(MoeLove)~ docker stats --no-stream $(docker ps -ql)CONTAINERIDNAMECPU %MEM USAGE / LIMITMEM %NET I/OBLOCK I/OPIDSe260e91874d8busy_napier0.00%1.434MiB / 20MiB7.17%35.3kB / 0B0B / 0B1
如果还不够,需要扩大至 100m 呢?
(MoeLove)~ docker update--memory 100m $(docker ps -ql)Error response from daemon: Cannot updatecontainer e260e91874d8181b6d0078c853487613907cd9ada2af35d630a7bef204654982: Memorylimit should be smaller than already set memoryswap limit, update the memoryswap at the same time
会发现这里有个报错信息 。大意是 memory limit 应该比已经配置的 memoryswap limit 小,需要同时更新 memoryswap 。
你可能会困惑,之前我们只是限制了内存为 10m,并且扩大至 20m 的时候是成功了的 。为什么到 100m 的时候就会出错?
这就涉及到了这些参数的特定行为了,我来为你一一介绍 。
内存限制参数的特定行为
这里的特定参数行为,主要是指我们前面使用的 --memory 和未介绍过的 --memory-swap 这两个参数 。
1. --memory 用于限制内存使用量,而 --memory-swap 则表示内存和 Swap 的总和 。
这解释了上面“Memory limit should be smaller than already set memoryswap limit”,因为 --memory-swap 始终应该大于等于 --memory (毕竟 Swap 最小也只能是 0 ) 。


推荐阅读