考点
- 文件系统基础:
inode、目录项、数据块、超级块 - 文件访问机制:文件描述符、VFS、页缓存(Page Cache)
- 常见文件系统:
ext4、xfs、tmpfs、overlayfs - 链接机制:硬链接、软链接
- 挂载与目录树:mount、bind mount、mount namespace
- 权限模型:
rwx、属主属组、umask、setuid/setgid/sticky bit - 空间问题排查:
df与du不一致、inode 耗尽 - 数据一致性:缓存落盘、
sync/fsync、日志文件系统 - 容器/K8s 相关:容器根文件系统、镜像分层、
overlay2、Volume 挂载
Q1:什么是 inode?inode 和文件名是什么关系?
核心要点
inode是文件元数据的索引结构,保存文件权限、属主、时间戳、大小、数据块位置等信息。- 文件名不在 inode 中,文件名存放在目录项里,目录本质上是“文件名 -> inode”的映射。
- 一个文件删除,本质上是删除目录项引用;只有当链接数归零且没有进程打开时,空间才真正释放。
- K8s/运维排障里,inode 耗尽会导致“磁盘看着还有空间,但不能创建文件”。
易错点
- 误以为文件名保存在 inode 中。
- 把“磁盘空间满”和“inode 满”混为一谈。
- 认为
rm后空间一定立即释放。
深挖点
- 如何查看 inode 使用情况:
df -i - 为什么小文件过多容易先耗尽 inode
- 已删除但仍被进程占用的文件,如何排查:
lsof | grep deleted
- 如何查看 inode 使用情况:
Q2:硬链接和软链接有什么区别?
核心要点
- 硬链接:多个文件名指向同一个 inode。
- 软链接:是一个独立文件,内容保存目标路径,类似快捷方式。
- 硬链接不能跨文件系统,一般不能对目录创建。
- 软链接可以跨文件系统,也可以指向目录。
易错点
- 认为删除原文件后硬链接失效,实际上不会,只要还有硬链接,数据仍在。
- 认为软链接和硬链接都共享 inode,这是错的,软链接有自己的 inode。
- 不清楚“跨文件系统”为什么硬链接不行:因为 inode 号只在本文件系统内有意义。
深挖点
ln和ln -s的底层差异- 为什么目录通常禁止硬链接:避免目录环,破坏文件系统遍历
- K8s 挂载配置文件时,为什么常会看到软链接结构
Q3:ext4、xfs、tmpfs 分别有什么特点?运维中怎么选?
核心要点
ext4:通用、稳定、兼容性好,传统 Linux 场景常用。xfs:大文件、高并发、扩展性好,很多云环境和容器节点常用。tmpfs:基于内存的临时文件系统,速度快,重启数据丢失。- K8s 中:
- 宿主机数据盘常见
xfs/ext4 emptyDir可配置为内存型,底层常依赖tmpfs
- 宿主机数据盘常见
易错点
- 认为
tmpfs不占内存,实际上本质上使用内存/交换空间。 - 认为
xfs一定比ext4好,实际要结合场景。 - 不知道某些容器存储驱动对底层文件系统有要求。
- 认为
深挖点
xfs和ext4在 inode 分配方式上的差异- 为什么容器场景常见
xfs - 如何查看文件系统类型:
df -T、mount、lsblk -f
Q4:为什么会出现 df 显示磁盘满了,但 du 看起来并没有那么大?
核心要点
df看的是文件系统整体已分配空间。du看的是目录树下当前可见文件占用。- 常见原因是:文件已删除,但仍被进程打开,所以
du看不到,df仍统计占用。 - 在日志场景、容器场景里非常常见。
易错点
- 只会用
du -sh /查目录,不会查已删除文件占用。 - 误以为重启服务前没办法释放,实际上可以通过关闭文件句柄释放。
- 误删日志后以为问题解决了。
- 只会用
深挖点
- 排查命令:
lsof | grep deleted - 为什么进程持有 fd 时,文件删除后空间不释放
- K8s 节点日志膨胀时,容器日志和宿主机文件的关系
- 排查命令:
Q5:文件系统中的 Page Cache 是什么?对读写性能有什么影响?
核心要点
- Page Cache 是内核用于缓存文件数据的内存区域。
- 读文件时,命中缓存可减少磁盘 IO;写文件时通常先写缓存,再异步刷盘。
- 因此“应用写成功”不一定代表“数据已持久化到磁盘”。
- 文件系统性能问题很多时候不是磁盘本身,而是缓存命中率、刷盘策略问题。
易错点
- 把 Page Cache 和 Buffer Cache、应用缓存完全混为一谈。
- 认为
write()返回成功就一定落盘了。 - 不理解为什么突然刷盘会引发 IO 抖动。
深挖点
sync、fsync、fdatasync的区别- 脏页回写机制
- 为什么数据库、中间件比普通应用更关注强制落盘
Q6:什么是日志文件系统?ext4/xfs 为什么恢复能力更强?
核心要点
- 日志文件系统会先记录元数据或事务日志,再真正修改文件系统结构。
- 宕机恢复时可通过日志回放,减少文件系统损坏。
ext4、xfs都属于带日志能力的文件系统。- 日志主要保障一致性,不等于保证应用数据绝不丢失。
易错点
- 认为有 journaling 就绝对不会丢数据。
- 混淆“元数据一致性”和“用户数据持久化一致性”。
- 认为日志文件系统不需要
fsck或其他修复工具。
深挖点
- metadata journaling 与 data journaling 的区别
- 宕机后恢复流程大致是什么
- 为什么数据库仍然需要自己的 WAL/redo log
Q7:什么是 OverlayFS?为什么容器镜像和容器写层经常提到它?
核心要点
OverlayFS是联合文件系统,可把多个目录层叠成一个统一视图。- 容器镜像通常是只读层,容器运行时再加一层可写层。
- Docker 常见存储驱动
overlay2就基于此实现。 - 容器内看起来是完整目录树,实际底层是多层叠加。
易错点
- 认为容器对文件的修改会回写到镜像层,实际上通常写到容器可写层。
- 不理解 copy-on-write 机制。
- 忽略容器频繁写小文件对存储性能的影响。
深挖点
- OverlayFS 的 lowerdir、upperdir、workdir、merged 分别是什么
- copy-up 在什么场景发生
- 为什么数据库不建议直接把高性能持久数据写在容器可写层,而应挂 Volume
Q8:K8s 中 Volume 挂载到底和 Linux 挂载机制有什么关系?
核心要点
- K8s 的 Volume 本质上最终还是落到 Linux 挂载机制上。
- 容器运行时会把宿主机目录、块设备、网络存储等挂载到容器命名空间中。
- 常见形式包括 bind mount、tmpfs、CSI 存储挂载。
- 所以排查 K8s 存储问题,经常要回到宿主机看
mount、findmnt、/proc/mounts。
易错点
- 只盯着 Pod YAML,不看宿主机实际挂载情况。
- 不理解容器和宿主机看到的是不同 mount namespace。
- 以为删除 Pod 就一定能清理所有挂载残留。
深挖点
- mount namespace 的作用
- bind mount 和普通 mount 的区别
- CSI 挂载失败时通常从哪些层排查:K8s 事件、kubelet、容器运行时、宿主机挂载
Q9:文件权限除了 rwx,还应该关注哪些特殊权限位?
核心要点
- 基本权限:读
r、写w、执行x - 特殊权限位:
setuidsetgidsticky bit
sticky bit常见于/tmp,表示目录下文件只能由文件所有者或 root 删除。umask决定新建文件/目录的默认权限。
- 基本权限:读
易错点
- 把目录的
rwx和文件的rwx理解成一样。 - 不清楚目录上的
x代表可进入/遍历,而不是执行文件。 - 忽略
umask导致权限不符合预期。
- 把目录的
深挖点
- 为什么
/tmp一般是1777 - setgid 目录对团队共享目录有什么作用
- ACL 和传统 rwx 权限模型的区别
- 为什么
Q10:inode 耗尽、磁盘耗尽、文件句柄耗尽,怎么快速区分?
核心要点
- 磁盘空间耗尽:看
df -h - inode 耗尽:看
df -i - 文件句柄耗尽:看进程
ulimit -n、系统file-max、报错如too many open files - 三类问题现象类似,都会导致创建文件失败或服务异常,但定位方法不同。
- 磁盘空间耗尽:看
易错点
- 统一按“磁盘满了”处理。
- 只清理大文件,不检查海量小文件。
- 忽略进程级 fd 限制和系统级 fd 限制的区别。
深挖点
/proc/sys/fs/file-max含义- 如何查看某个进程打开了多少 fd:
ls /proc/<pid>/fd | wc -l - K8s 节点上哪些组件容易出现 fd 泄漏或日志文件过多问题
速记笔记
- inode:存元数据,不存文件名;目录存“文件名 -> inode”映射
- 硬链接:同 inode;软链接:新文件,存路径
- df 看文件系统整体,du 看可见目录内容
- 删文件不一定释放空间:进程还占着 fd
- Page Cache:提升性能,但写成功不等于已落盘
- fsync:更接近真正持久化
- ext4/xfs:日志文件系统,恢复能力强
- tmpfs:内存文件系统,快但易失
- OverlayFS/overlay2:容器镜像分层 + 可写层
- K8s Volume 本质还是 Linux 挂载
- 排障三板斧:
- 空间:
df -h - inode:
df -i - 删除未释放:
lsof | grep deleted
- 空间: