tmpfs 挂载点空间耗尽但内存和 swap 都充足的几种场景

4次阅读

tmpfs 报“No space left on device”但内存充足,主因是其资源隔离机制:1. 显式 size 限制已满;2. 受 memory cgroup 硬限约束;3. 未设 size 时默认上限保守(如 50% RAM 或 1GB);4.inode 耗尽;5. 用户 / 组磁盘配额生效。

tmpfs 挂载点空间耗尽但内存和 swap 都充足的几种场景

tmpfs 挂载点报“No space left on device”,但 宿主机内存和 swap 都充足 ,这种现象看似矛盾,实则源于 tmpfs 的资源隔离机制——它不共享全局内存池,而是受自身挂载参数和内核配额约束。以下是几种典型且高频的场景:

1. 显式设置了 size 限制,且已写满

这是最常见原因。只要挂载时指定了 size=(如 size=64m),该 tmpfs 就严格按此上限分配页,即使系统还有数 GB 空闲内存,也无法突破该值。

  • 例如:docker run --tmpfs /tmp:rw,size=128m nginx,容器内向 /tmp 写入超过 128MB 文件,立即失败
  • df -h /tmp 显示使用率 100%,而 free -h 显示内存剩余 8GB —— 两者互不影响

2. 容器或命名空间启用了 memory cgroup 限流

当容器运行在启用 memory.max(cgroup v2)或 memory.limit_in_bytes(v1)的环境中,tmpfs 分配会受该 cgroup 内存上限制约,而非主机总内存。

  • 即使宿主机有 32GB 内存,若容器被限制为 256MB,其内部 tmpfs 最多只能用约 200–230MB(因内核需预留部分内存管理开销)
  • 此时 cat /sys/fs/cgroup/memory.max 可查到硬限制,cat /sys/fs/cgroup/memory.current 接近该值即触发 tmpfs 拒绝写入

3. tmpfs 挂载时未设 size,但受内核默认策略限制

未指定 size= 时,Linux 并非“无限使用”,而是采用保守策略:

  • 对于普通挂载(如 mount -t tmpfs tmpfs /mnt),默认上限为 min(50% RAM, 1GB)(具体取决于内核版本与配置)
  • Docker 中未设 size--tmpfs,早期版本默认 64MB,新版默认为 half of available memory,但仍可能远低于物理总量(例如 16GB 主机 → 默认 8GB,但若容器运行在低内存节点或受 kubelet 调度约束,实际可用更少)

4. inode 耗尽(nr_inodes 限制)

tmpfs 同时受限于 inode 数量。即使空间未满,若创建了海量小文件(如日志轮转、缓存碎片),可能先触达 nr_inodes 上限。

  • 挂载时可显式设 nr_inodes=10000;未设置时,默认值通常为 max(1M, mempages/2),但并非无限
  • 验证方式:df -i /tmp 查看 Use%,若接近 100% 而 df -h /tmp 仅 30%,即为此类问题

5. 用户或组磁盘配额(quota)生效

极少数生产环境会对 tmpfs 挂载点启用基于用户 / 组的磁盘配额(需内核支持 + usrquota/grpquota 挂载选项)。

  • 即使挂载点本身有空间,某个 UID/GID 已达其 block limit,该用户进程写入就会失败
  • 检查命令:quota -u $USER -p /tmprepquota -a | grep tmp
text=ZqhQzanResources