You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kubernetes Pod内存占用为何远高于其内部进程内存总和?

问题背景
  • 技术栈为nginx + php-fpm,相同部署配置在多个项目运行稳定,仅单个项目持续出现内存溢出问题
  • 异常项目PHP-FPM容器内存持续累积,直至php-fpm进程被OOMKilled,最终导致Pod终止
  • 监控数据存在明显统计偏差:
    • 云监控、k9s的%MEM/L列均显示Pod内存占用持续走高
    • 容器内执行top命令统计的进程内存占用处于极低水平,健康Pod与异常Pod的php-fpm进程数量、单进程内存消耗基本持平
  • 内存变化规律:
    • 内存增长速率与流量正相关,无流量时内存曲线保持平稳
    • Pod长时间不接收流量时,已占用的内存会逐步释放
    • 单独跟踪单个php-fpm进程,进程处理完请求后可正常释放内存,无进程级内存泄漏特征
  • 已完成排查动作:
    • 将PHP-FPM进程数量限制在较小范围,长期监控单进程内存无异常
    • 容器内执行ipcs未查询到已分配的System V共享内存
    • 应用接入Memcached后,内存异常问题自行消失
  • 核心疑问:
    • 未被进程统计到的隐藏内存来自哪里?
    • 为何Pod内存统计值与容器内进程内存统计总和存在差值?
    • 如何排查定位这部分“暗内存”?
问题解答

为什么Pod内存统计和容器内top结果存在差值

top默认展示的进程内存指标是RSS(常驻集大小),仅统计进程私有、已驻留物理内存的匿名页,以及进程映射的共享内存中被该进程实际访问的部分。以下几类内存完全不会被top统计到,但会100%计入Pod对应的cgroup内存统计(也就是云监控、k9s读取的内存值,OOM判定时也会全额计入配额):

  • 基于文件映射的page cache:包括程序读写本地文件产生的文件缓存页
  • tmpfs内存文件系统占用的页:比如/dev/shm、内存模式emptyDir挂载点下写入的所有内容
  • POSIX共享内存、通过mmap(MAP_ANONYMOUS|MAP_SHARED)创建的共享匿名映射:ipcs默认仅展示System V类型的IPC共享内存,这类内存不会出现在ipcs输出中
  • 内核态为cgroup内进程分配的内存:包括socket收发缓冲区、slab分配器维护的dentry/inode缓存、网络连接相关内核数据结构

暗内存的根因判断

结合所有观测特征:内存增长与流量正相关、无流量时内存可自行回收、接入Memcached后问题消失、同配置其他项目无异常,99%的概率是该项目未接入外部缓存时,将大量请求缓存、会话数据或高频访问的大文件存储在容器本地文件系统,产生了巨量page cache占用:

  • 其他项目要么本地文件读写量极小,要么已经接入外部缓存,因此不会触发该问题
  • 无流量时内核会逐步回收可驱逐的page cache,因此内存会缓慢下降
  • 接入Memcached后,原有的本地文件读写缓存逻辑全部改为访问远端缓存服务,本地不再产生大量文件IO,page cache不会持续累积,问题自然消失
  • 之前用ipcs没查到共享内存属于正常情况,page cache不属于System V IPC范畴,本来就不会被ipcs统计
  • 补充CPU对照实验的异常结果也符合该特征:大量本地文件IO会额外消耗CPU在内核态页管理、文件系统逻辑上,接入Memcached后本地IO消失,CPU占用也会同步下降,与观测结果一致。

排查定位步骤

按顺序操作即可快速定位:

  1. 进入异常Pod查看cgroup内存拆分统计:
    • cgroup v1环境执行cat /sys/fs/cgroup/memory/memory.stat
    • cgroup v2环境执行cat /sys/fs/cgroup/memory.stat
      重点核对字段:
    • file字段值:对应page cache、tmpfs、POSIX共享内存的总占用,如果该值与观测到的暗内存大小基本一致,可直接确认是文件类缓存/共享内存占用
    • sock、slab、kernel_stack字段值:如果这几个值异常偏高,说明是内核态内存占用,常见原因为socket缓冲区泄漏、slab对象泄漏
  2. 如果确认file字段占比过高,先执行df -h查看/dev/shm、所有tmpfs挂载点的占用,再执行lsof | grep -E "(deleted|/tmp|/var/lib/php)"排查是否存在大量已删除但未被进程关闭句柄的临时文件——php如果频繁创建临时文件且未正常关闭句柄,即使文件被删除,对应的page cache也不会释放,直到进程退出或关闭句柄
  3. 执行free -h查看输出中的buff/cache列数值,如果该值与暗内存差值基本匹配,可进一步坐实页缓存占用的判断
  4. 临时验证(需要容器持有CAP_SYS_ADMIN权限):在Pod内存涨到高位时执行echo 3 > /proc/sys/vm/drop_caches,如果执行后监控显示内存直接回落至正常水平,可100%确认是page cache累积导致的问题。

修复方案

  • 根本修复:对齐接入Memcached的逻辑,不要在容器本地存储高频访问的大体积缓存、会话数据,全部下沉到外部缓存服务
  • 临时缓解:调整php-fpm配置,合理设置pm.max_requests参数,让worker进程处理一定数量请求后自动重启,进程退出时会自动释放持有的文件句柄,关联的可回收page cache会被内核逐步回收;不推荐生产环境长期使用定时触发drop_caches的方案,会带来短暂的IO性能波动。
  • 注意:该问题不属于php-fpm进程私有内存泄漏,之前跟踪单进程RSS正常已经排除了这类可能,不需要在php进程内存限制参数上做无用调优。

内容的提问来源于stack exchange,提问作者Rax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:06:19