Docker、AUFS、inode耗尽和一个小工具

— 问题 —

遇到过这样的错误吧:

No space left on device

然而当 df -H 的时候,又是这样:

# df -H

Filesystem Size Used Avail Use% Mounted on
 udev 1.1G 4.1k 1.1G 1% /dev
 tmpfs 210M 758k 209M 1% /run
 /dev/xvda1 43G 18G 23G 45% /

明明还有那么多空间。。。当然,有经验的人肯定立刻就想到了:

# df -i

Filesystem Inodes IUsed IFree IUse% Mounted on
 udev 253256 430 252826 1% /dev
 tmpfs 255939 473 255466 1% /run
 /dev/xvda1 2621440 2618687 2753 100% /

原来是 inode 耗尽了。

— 原因 —

Inode 全名 Index Node ,主要是用于保存文件大小、类型等文件系统对象(文件、目录)的元数据,它本身并不存储实际数据,一个文件或者文件夹都对应一个 inode 。

Inode 的总数和大小是在创建文件系统时候指定的,文件系统创建后就不能更改。所以在你创建了大量的文件、文件夹和链接( symlink )之后,你的 inode 资源就会越来越少了。

Inode 耗尽应该算是在 Docker 下使用 AUFS 常见的问题了。众所周知, AUFS 是 Docker 最先支持的存储驱动,具备速度快、节省存储空间、管理简单等优点,尽管 Linux 内核并不直接支持 AUFS ,但不妨碍很多 Ubuntu 用户直接使用 AUFS 。

但是我们也不能就这么简单地把锅甩给 AUFS ,还是要自己做好应用程序的监控和设计。

— 工具 —

这里介绍一个简单、方便的工具: inodes ( https://github.com/tripflex/inodes ) ,这个工具可以方便计算指定文件夹的inodes使用情况,你再也不必使用 find + for + df 这些网上流传的各种命令组合了。

安装非常简单,只需要下载二进制文件就可以了:

# wget -O /bin/inodes https://raw.smyl.es/inodes/master/inodes
 # chmod +x /bin/inodes

使用也简单,参数不多:

参数 示例 说明
-d inodes -d /path/to/dir 可选。要查看的路径,默认使用当前目录。
-t inodes -t 50000 可选。树形显示使用超过了50000个 inode 的目录。
-e inodes -e 100 可选。过滤掉使用inode小于100个的目录。

这个应用执行后结果大概是这样的:

 

20161202105914

— 解决 —

首先找到inode到底都被哪些目录占用了,方法可采用上面介绍的工具,但是这个过程可能比较耗时,甚至几个小时。

然后,清除没有用的东西即可:比如镜像容器Volume

删除没用的镜像:

# docker images -qf dangling=true | xargs docker rmi

删除没用的Volume:

# docker volume ls -qf dangling=true |xargs docker volume rm

再不行,备份数据,重新格式化或者加硬盘,在创建文件系统的时候,指定一个比较大的inode数,比如:

# mkfs -t ext4 -N

或者干脆换不使用 inode 的文件系统,比如 btrfs 或 DeviceMapper 。

— 建议 —

关于如何使用 Docker + AUFS ,官方有一份详细的说明 ( https://docs.docker.com/engine/userguide/storagedriver/aufs-driver/ ),大家可以参考下。其中说道了 Volume ,由于 Volume 略过了存储驱动,所以就省去了一些必要的初始化设置工作和 CoW ,所以重 IO 的数据都推荐使用 Volume 。

这里其实有一个问题, 如果 Docker 镜像中定义了 Volume ,而启动的时候又没有通过 -v 选项为定义的 Volume 指定绑定的 HOST 路径,那么 Docker 就会自动在
/var/lib/docker/volumes/ 文件夹下面创建一个 Volume 供新启动的容器使用。

坑爹的地方在于,如果你通过 docker rm 命令删除这个容器的时候, Docker 默认是不会删除这些默认创建的 Volume 的。

那么这里大叔就给大家一些建议:

  • 有一说一,没用的 Volume 别写到 Dockerfile 里去
  • 写到了 Dockerfile ,就尽量为其指定宿主机路径
  • 删除的时候使用 -v 选项
K8S中文社区微信公众号
分享到:更多 ()