使用 PHP 创建和删除文件后 Docker 不释放内存

mps*_*ang 4 php memory debian docker kubernetes

我有一个 PHP 守护进程脚本,用于下载远程图像并在上传到对象存储之前将它们临时存储在本地。

PHP 内部内存使用量保持稳定,但 Docker/Kubernetes 报告的内存使用量不断增加。

我不确定这是否与 PHP、Docker 或预期的 Linux 行为有关。

重现问题的示例:

码头工人形象: php:7.2.2-apache

<?php
for ($i = 0; $i < 100000; $i++) {
    $fp = fopen('/tmp/' . $i, 'w+');
    fclose($fp);

    unlink('/tmp/' . $i);

    unset($fp);
}
Run Code Online (Sandbox Code Playgroud)

free -m在执行上述脚本之前调用容器内部:

          total        used        free      shared  buff/cache   available
Mem:           3929        2276         139          38        1513        1311
Swap:          1023         167         856
Run Code Online (Sandbox Code Playgroud)

并在执行脚本后:

          total        used        free      shared  buff/cache   available
Mem:           3929        2277         155          38        1496        1310
Swap:          1023         167         856
Run Code Online (Sandbox Code Playgroud)

显然内存已释放,但从docker stats php-apache主机调用表示其他内容:

CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
ccc19719078f        php-apache          0.00%               222.1MiB / 3.837GiB   5.65%               1.21kB / 0B         1.02MB / 4.1kB      7
Run Code Online (Sandbox Code Playgroud)

报告的初始内存使用量docker stats php-apache为 16.04MiB。

解释是什么?如何释放内存?

在具有资源限制的 Kubernetes 集群中运行此容器会导致 pod 失败并反复重启。

Ale*_*hin 6

是的,这里已经报告了类似的问题。

是贡献者之一的coolljt0725的答案,回答为什么输出中的REStop显示不同的内容,而不是docker stats(我将按原样引用他):

如果我理解正确的话,docker stats 中的内存使用量是从容器的内存 cgroup 中读取的,您可以看到该值与您从 cat /sys/fs/cgroup/memory/docker/665e99f8b760c0300f10d3d9b35b1a5e7b1dc08c8c08c08c08c08c08c08c08c08c08c08c08c8c08c8c8c88c88c88c88c888c888c88c888888878c88c88c888888878c8c8c8c888888888c8c88cgroupe5c80720cgroup 中读取的值与 490270720 相同。 ,并且该限制也是创建容器时由 -m 设置的内存 cgroup 限制。RES和内存cgroup的统计数据不同,RES不考虑caches,但是内存cgroup会,这就是为什么docker stats中的MEM USAGE比top中的RES多很多

用户在此处建议的内容实际上可能会帮助您查看实际内存消耗:

尝试设置docker run --memory?的参数,然后检查您的 /sys/fs/cgroup/memory/docker/<container_id>/memory.usage_in_bytes 它应该是正确的。

--memory在此处-m描述:

-m, --memory=""- 内存限制(格式:)<number>[<unit>]。数字是一个正整数。单位可以是一个bkm,或g。最小值是4M

现在如何避免不必要的内存消耗。正如您发布的那样,在 PHP 中取消链接文件不需要立即删除内存缓存。相反,以特权模式(带有--privileged标志)运行 Docker 容器,然后可以调用echo 3 > /proc/sys/vm/drop_cachessync && sysctl -w vm.drop_caches=3定期清除内存页面缓存。

作为奖励,fopen('php://temp', 'w+')在内存中临时使用和存储文件可以避免整个问题。