降低代码执行中得内存消耗_docker可以限制容器内存大小吗?

本文介绍了如何在Docker容器中限制内存使用以防止资源耗尽。通过设置内存限制,避免OOME问题,保护docker daemon安全。实践案例包括使用-m选项限制内存上限,理解--memory-swap与--memory的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

默认情况下容器使用的资源是不受限制的。也就是可以使用主机内核调度器所允许的最大资源。但是在容器的使用过程中,我们不可能让容器无限制的去使用主机资源,下面介绍下怎么去对Docker容器可用的内存做限制。


为什么要限制容器对内存的使用?

限制容器不能过多的使用主机的内存是非常重要的。对于 linux 主机来说,一旦内核检测到没有足够的内存可以分配,就会扔出 OOME(Out Of Memmory Exception),并开始杀死一些进程用于释放内存空间。

这里我们考虑一个比较常见的场景,大量的容器把主机的内存消耗殆尽,OOME 被触发后系统内核立即开始杀进程释放内存。如果内核杀死的第一个进程就是 docker daemon 会怎么样?结果就是所有的容器都不工作了!

针对这个问题,docker 尝试通过调整 docker daemon 的 OOM 优先级来进行缓解。内核在选择要杀死的进程时会对所有的进程打分,直接杀死得分最高的进程,接着是下一个。当 docker daemon 的 OOM 优先级被降低后(注意容器进程的 OOM 优先级并没有被调整),docker daemon 进程的得分不仅会低于容器进程的得分,还会低于其它一些进程的得分。这样 docker daemon 进程就安全多了。

可以通过下面的脚本直观的看一下当前系统中所有进程的得分情况:

#!/bin/bashfor proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do printf "%2d %5d %s"  "$(cat $proc/oom_score)"  "$(basename $proc)"  "$(cat $proc/cmdline | tr '0' ' ' | head -c 50)"done 2>/dev/null | sort -nr | head -n 40

此脚本输出得分最高的 40 个进程,并进行了排序(第一列显示进程的得分)

28b010045edd0ba915009448b73f4da8.png

压力测试工具 stress

为了测试容器的内存使用情况,我安装了压力测试工作 stress,并新创建了镜像 u-stress。

下面用的所有容器都会通过 u-stress 镜像创建(运行容器的宿主机为 ubuntu16.04 )。下面是创建 u-stress 镜像的 Dockerfile:

FROM ubuntu:latestRUN apt-get update &&  apt-get install stress

创建镜像的命令为:

docker build -t u-stress:latest .
0ce4fa6d3a74359aebc9093bbe704215.png

限制内存使用上限

先完成一个简单的用例:限制容器可以使用的最大内存为 300M。

-m(--memory=) 选项可以完成这样的配置:

$ docker run -it -m 300M --memory-swap -1 --name con1 u-stress /bin/bash
4548f8026433fb4d75acbe7344e64d72.gif

下面的 stress 命令会创建一个进程并通过 malloc 函数分配内存:

# stress --vm 1 --vm-bytes 500M

通过 docker stats 命令查看实际情况:

f2a7428100a0a3698e3876baf035731f.png

上面的 docker run 命令中通过 -m 选项限制容器使用的内存上限为 300M。同时设置 memory-swap 值为 -1,它表示容器程序使用内存的受限,而可以使用的 swap 空间使用不受限制(宿主机有多少 swap 容器就可以使用多少)。

下面我们通过 top 命令来查看 stress 进程内存的实际情况:

daf40cde3e0c3dcbd0a8e7091a686408.png

上面的截图中先通过 pgrep 命令查询 stress 命令相关的进程,进程号比较大(9296)的那个是用来消耗内存的进程,我们就查看它的内存信息。VIRT 是进程虚拟内存的大小,所以它应该是 500M。RES 为实际分配的物理内存数量,我们看到这个值就在 300M 上下浮动。

结果:成功的限制了容器能够使用的物理内存数量。


限制可用的 swap 大小

强调一下 --memory-swap 是必须要与 --memory 一起使用的。

正常情况下, --memory-swap 的值包含容器可用内存和可用 swap。所以 --memory="300m" --memory-swap="1g" 的含义为:

容器可以使用 300M 的物理内存,并且可以使用 700M(1G -300M) 的 swap。

--memory-swap 是容器可以使用的物理内存和可以使用的 swap 之和!

把 --memory-swap 设置为 0 和不设置是一样的,此时如果设置了 --memory,容器可以使用的 swap 大小为 --memory 值的两倍。

如果 --memory-swap 的值和 --memory 相同,则容器不能使用 swap。

下面 演示在没有 swap 可用的情况下向系统申请大量内存的场景:

$ docker run -it --rm -m 300M --memory-swap=300M u-stress /bin/bash# stress --vm 1 --vm-bytes 500M
bff22072c2fa27170e61146ed4b27a3c.png

e1c5f4ec7a0de955f3035e0dc3d9c9b2.gif

通过限制容器可用的物理内存,可以避免容器内服务异常导致大量消耗主机内存的情况(此时让容器重启是较好的策略),因此可以降低主机内存被耗尽带来的风险。

后面会分享更多devops方面内容,感兴趣的朋友可以关注下!!

671e82738463f97260ef38c19032db8e.gif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值