bigywater.tech
Docker · 41

内存限制与 swap:--memory-swap 的组合行为

--memory 和 --memory-swap 的数字怎么算?容器内存超了是被杀,还是被换到 swap?这篇把几种组合翻译成 cgroup 文件里的值,并用逐步分配内存的程序看每种设置下的实际表现。

50 / 110 / 200 MiB
--memory 64m 下 swap 为 0 / 64 MiB / 不限时,程序能分配到的内存量(前两个被 OOM 杀死)
swap.max = 内存+swap 总和 − 内存
--memory-swap 128m 配 --memory 64m 得到的 memory.swap.max = 64 MiB
151 MiB 在 swap
--memory-swap -1 时分配 200 MiB,memory.current 只有 54 MiB

cgroup 里的值

实测 · 本机执行输出
  虚拟机的 /proc/meminfo:MemTotal: 8124516 kB;SwapTotal: 1048572 kB;
  不限制:memory.max=max memory.swap.max=max
  --memory 64m:memory.max=67108864 memory.swap.max=67108864
  --memory 64m --memory-swap 64m:memory.max=67108864 memory.swap.max=0
  --memory 64m --memory-swap 128m:memory.max=67108864 memory.swap.max=67108864
  --memory 64m --memory-swap -1:memory.max=67108864 memory.swap.max=max

虚拟机有约 1 GiB swap。--memory 64m 单独使用时,swap 也被限制在 64 MiB(memory.swap.max = 67108864);--memory-swap 表示内存加 swap 的总和,所以 128m 配 64m 内存,swap 只有 64 MiB;--memory-swap 64m 则完全不允许 swap(0);-1 不限。

超限的表现

实测 · 本机执行输出
  不限制:最后一条输出「已分配 200 MiB(memory.current=204 MiB,swap.current=0 MiB)」;ExitCode=0 OOMKilled=False
  --memory 64m:最后一条输出「已分配 110 MiB(memory.current=54 MiB,swap.current=61 MiB)」;ExitCode=137 OOMKilled=True
  --memory 64m --memory-swap 64m:最后一条输出「已分配 50 MiB(memory.current=54 MiB,swap.current=0 MiB)」;ExitCode=137 OOMKilled=True
  --memory 64m --memory-swap 128m:最后一条输出「已分配 110 MiB(memory.current=54 MiB,swap.current=64 MiB)」;ExitCode=137 OOMKilled=True
  --memory 64m --memory-swap -1:最后一条输出「已分配 200 MiB(memory.current=54 MiB,swap.current=151 MiB)」;ExitCode=0 OOMKilled=False

分配 200 MiB:不允许 swap 的容器在 50 MiB 附近就被杀(137,OOMKilled=true);允许 64 MiB swap 的撑到 110 MiB(约 54 MiB 在内存、60 MiB 左右在 swap);swap 不限的把 200 MiB 都分配了,其中 151 MiB 被换到 swap,容器没被杀——代价是换页的开销,我没有测速度。

软限制

实测 · 本机执行输出
  memory.high / memory.low 等:high=max low=33554432 max=67108864
  docker stats --no-stream:552KiB / 64MiB 占 0.84%

--memory-reservation 对应 memory.low(32 MiB),docker stats 的 LIMIT 仍是 --memory 的 64MiB。memory.low 在内存紧张时才起作用,怎么起作用我没有实验。

分步演示

内存限制与 swap
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。虚拟机 MemTotal 8124516 kB、SwapTotal 1048572 kB;测试程序是 python:3.12-alpine 里的脚本,每次分配并写入 10 MiB(os.urandom),输出时读 /sys/fs/cgroup/memory.current 与 memory.swap.current;每种情形运行一次;实验后已删除容器和镜像
    • 没有验证:swap 的读写速度与性能影响、memory.high 的节流、cgroup v1 的行为、Linux 宿主机没有开 swap 或 swapaccount 时的表现、--oom-kill-disable(见后面的 OOM 一篇)
    京ICP备2026067502号-1京公网安备11010502063487号