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

Docker在使用PHP创建和删除文件后不会释放内存,php,docker,memory,debian,kubernetes,Php,Docker,Memory,Debian,Kubernetes,我有一个PHP守护程序脚本,在上传到对象存储之前,下载远程图像并将它们临时存储在本地 PHP内部内存使用率保持稳定,但Docker/Kubernetes报告的内存使用率不断增加 我不确定这是否与PHP、Docker或预期的Linux行为有关 复制问题的示例: Docker image:php:7.2.2-apache <?php for ($i = 0; $i < 100000; $i++) { $fp = fopen('/tmp/' . $i, 'w+'); fcl

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

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

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

复制问题的示例:

Docker image:
php:7.2.2-apache

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

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

    unset($fp);
}
在执行脚本之后:

          total        used        free      shared  buff/cache   available
Mem:           3929        2277         155          38        1496        1310
Swap:          1023         167         856
显然,内存已释放,但从主机调用
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
docker stats php apache报告的初始内存使用量为16.04MiB

原因是什么?如何释放内存


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

是,已报告类似问题

关于CoolJT0725,作者之一,在回答为什么
top
输出中的
RES
列显示了与
docker stats
不同的内容时(我只想按原样引用他):

如果我理解正确,docker stats中的内存使用量是从容器的内存cgroup中读取的,您可以看到该值与从cat/sys/fs/cgroup/memory/docker/665E99F8B760C0300F10D3D9B35B1A55E5FDCF1B7E4A0E27C1B6FF100981D9A69/memory.usage中读取的490270720值相同,单位为字节,该限制也是内存cgroup限制,在创建容器时由-m设置。RES和memory cgroup的统计数据是不同的,RES不考虑缓存,但memory cgroup考虑缓存,这就是为什么docker stats中MEM的使用要比top中的RES多得多

用户的建议实际上可能会帮助您了解实际的内存消耗情况:

尝试设置
docker run--memory
的参数,然后检查您的
/sys/fs/cgroup/memory/docker//memory.usage(以字节为单位)
应该是对的

--memory
-m
描述如下:

-m
-memory=”“
-内存限制(格式:
[]
)。数字是一个正整数。单位可以是
b
k
m
g
中的一种。最小值为
4M

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


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

Alex提到的问题解释了容器内的
free-m
和主机中的
docker stats
之间的内存使用差异。后者包括缓冲区/缓存

在PHP中取消文件链接并不需要立即删除内存缓存


相反,在特权模式下运行Docker容器时,我可以周期性地调用
echo3>/proc/sys/vm/drop\u caches来清除内存页面缓存。

内存被进程和内核使用。如果不是PHP,请使用所有内存查找进程。感谢您的回答和参考!这就解释了内存使用的差异。不幸的是,在这种情况下,cgroup是最敏感的。PHP脚本中的文件操作增加了缓冲区/缓存,容器无法释放它。只有主机可以调用
echo3>/proc/sys/vm/drop\u缓存
。您知道从容器访问文件系统时如何避免OOM吗?那么,为什么
fopen('php://temp“,“w+”)
工作起来很有魅力,但是
fopen(“/tmp/”.$i,“w+”)
不能释放内存吗?原因是什么@mpskovvang@AlexKarshin@Q-bart您可以在文档中阅读:
php://temp 一旦存储的数据量达到预定义的限制(默认值为2 MB),将使用临时文件。
。收到了,谢谢。实际上,我还有一个小问题:docker容器不能从将大量数据写入文件(logger)的进程中释放内存,所以我很感兴趣的是为什么它是可能的,以及如何在我的电脑中修复它case@Q-巴特:你应该单独提出一个问题,然后我是否应该将你的答案合并到我的答案中,形成一个综合完整的答案?是的,如果有一个详细完整的答案,那就太好了。我还发现了一个更漂亮的命令
sync&&sysctl-wvm.drop\u caches=3
。作为奖励信息,我发现使用
fopen('php://temp“,”w+”)
将文件临时存储在内存中可以避免整个问题。没有未刷新的记忆挂起。我编辑了我的答案。如果我遗漏了什么,请随意编辑
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