AI Infra 训练营
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub

mount / umount —— 挂载文件系统

一句话定义

mount 把一个已格式化的设备(或目录、或网络存储)"接入"到目录树的某个挂载点。Linux 不像 Windows 用盘符——所有东西都通过 mount 出现在统一的文件树里。

典型场景

  • 装机时把新盘挂到 /data
  • K8s PV:底层 PV controller 帮你 mount 到节点上的 /var/lib/kubelet/...
  • 网络存储:NFS / iSCSI mount
  • 排查 df / lsblk 显示不一致:mount | grep ...
  • bind mount:把目录"映射"成另一个路径

看当前挂载

mount                              # 列出所有挂载(输出有点啰嗦)
mount | column -t                  # 对齐显示
mount | grep ext4                  # 过滤
findmnt                            # 树形结构(**更易读**)
findmnt /var                       # 看某挂载点详情
cat /proc/mounts                   # 内核视角的真实状态

findmnt 是看挂载的现代首选:

$ findmnt
TARGET                  SOURCE        FSTYPE     OPTIONS
/                       /dev/sda3     ext4       rw,relatime
├─/sys                  sysfs         sysfs      rw,nosuid,nodev,noexec
├─/proc                 proc          proc       rw,nosuid,nodev,noexec
├─/dev                  devtmpfs      devtmpfs   rw,nosuid
├─/boot                 /dev/sda2     ext4       rw,relatime
├─/var/lib/docker       overlay       overlay    rw,...
└─/data                 /dev/sdb1     ext4       rw,relatime

/proc/mounts 是内核的真相(mount 命令的输出可能滞后)。


手动挂载

mount /dev/sdb1 /data                              # 普通挂载
mount -t ext4 /dev/sdb1 /data                      # 指定文件系统类型(多数情况自动检测)
mount -o ro /dev/sdb1 /mnt/readonly                # 只读
mount -o noatime,nodiratime /dev/sdb1 /data        # 加挂载选项

常用 -o 选项

选项含义
ro / rw只读 / 读写
noatime不更新文件 atime(生产推荐:减少写放大)
nodiratime不更新目录 atime(noatime 通常已包含)
nodev不识别设备文件(安全)
nosuid忽略 setuid(安全)
noexec不允许执行二进制(安全)
discardTRIM 自动通知 SSD(SSD 推荐)
defaults等价 rw,suid,dev,exec,auto,nouser,async
remount重新挂载(改选项不卸载)
nofail挂载失败也不让系统启动失败(fstab 必加)

remount —— 不卸载就改选项

mount -o remount,ro /                              # 把 / 变只读
mount -o remount,rw /                              # 再改回来

只读模式是应急 fsck / 紧急调试的常见做法。


bind mount —— 把目录映射成另一个路径

mount --bind /data/foo /mnt/foo
# 之后 /mnt/foo 和 /data/foo 是同一个数据
# 修改一个,另一个也变

不是软链接 —— bind mount 在内核层做映射,对程序透明。

K8s 里 hostPath、emptyDir 都靠 bind mount 实现:

# kubelet 把 hostPath /etc/myapp bind 到容器内的 /config
mount --bind /etc/myapp /var/lib/kubelet/pods/.../volumes/.../config

bind mount 只读:

mount --bind /etc/cfg /mnt/cfg
mount -o remount,ro,bind /mnt/cfg

注意:mount --bind 不能直接 mount -o ro,bind ... —— 必须 bind 之后再 remount ro。这是 mount 历史遗留坑。


看 / 排查"挂载到哪里了"

findmnt /dev/sdb1                                  # 这个盘挂在哪?
findmnt -t ext4                                    # 所有 ext4
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS            # 自定义列
findmnt -R /var                                    # /var 下所有 mount 树

# 反查:某路径属于哪个 mount
df /path/to/file
# 或
findmnt --target /path/to/file

网络存储挂载

NFS

mount -t nfs server.example.com:/data /mnt/nfs
mount -t nfs -o vers=4,rsize=1048576,wsize=1048576 server:/data /mnt/nfs

iSCSI(先 login,后 mount)

iscsiadm -m discovery -t st -p 192.168.1.100
iscsiadm -m node -T iqn.2024.... -p 192.168.1.100 --login
# 之后 /dev/sdc 等设备出现
mount /dev/sdc1 /mnt/iscsi

Ceph RBD(K8s 常见)

rbd map mypool/myimage
mount /dev/rbd0 /mnt/ceph

K8s StorageClass 把这些操作自动化了,你通常不需要手动 mount。


umount —— 卸载

umount /data                                       # 按挂载点
umount /dev/sdb1                                   # 按设备
umount -l /data                                    # lazy(**umount 卡住时用**)
umount -f /data                                    # 强制(NFS 卡死时)

target is busy 怎么处理

$ umount /data
umount: /data: target is busy.

# 第 1 步:找谁占着
lsof +D /data
fuser -vm /data

# 第 2 步:杀掉 / 让它退出
kill <PID>

# 第 3 步:再 umount
umount /data

或者懒卸载(lazy):

umount -l /data
# 立刻断开 mount 入口,新进程访问不到
# 但旧持有 fd 的进程可以继续工作,最后一个 close 时真正释放

-l 是常用救命招——不破坏现有进程。

-f 强制(仅适合 NFS)

umount -f /mnt/nfs

NFS server 挂了,client 卡在 D 状态、umount 卡住。-f 让 NFS client 放弃。


挂载流程总结

新盘上线全流程:

# 1. 看设备
lsblk
# /dev/sdb 是新盘

# 2. 分区(如果需要)
parted /dev/sdb mklabel gpt
parted -a optimal /dev/sdb mkpart primary ext4 0% 100%

# 3. 格式化
mkfs.ext4 -L data /dev/sdb1

# 4. 挂载
mkdir -p /data
mount /dev/sdb1 /data

# 5. 验证
df -h /data
findmnt /data

# 6. 持久化(写 fstab —— 见 fstab.md)
echo "UUID=$(blkid -s UUID -o value /dev/sdb1) /data ext4 defaults,noatime,nofail 0 2" >> /etc/fstab

# 7. 测一遍 fstab 没写错
umount /data
mount -a
df -h /data                          # 还要在

K8s 视角

K8s 节点上 findmnt 输出有上百行,因为每个 pod 至少 1-2 个 bind mount:

findmnt | grep kubelet | head

每个 ConfigMap / Secret / hostPath 都是一次 bind mount。Pod 终止时 kubelet 负责 umount——但偶尔会卡(容器 runtime 错乱、CSI driver bug)。

排查"pod 卡 Terminating"

kubectl get pod my-pod
# Terminating 很久

# 节点上
ssh m4
findmnt | grep <pod-uid>
# 如果还有挂载,kubelet 在等 umount

# 看进程
lsof +D /var/lib/kubelet/pods/<pod-uid>

# 强制 unmount 残留(小心)
findmnt | grep <pod-uid> | awk '{print $1}' | xargs -r umount -l

挂载选项的性能影响

K8s 节点上 etcd / 大数据 / 数据库的挂载选项不一样:

场景推荐选项
通用defaults,noatime
etcd 数据盘defaults,noatime,nodiratime,discard
数据库(PG/MySQL)defaults,noatime,nobarrier(SSD/电池 controller)
容器 overlaydefaults(containerd / docker 自己管)
临时数据defaults,noatime,nodiratime

noatime 的意义

默认每次 read 文件 Linux 也会更新 atime(访问时间) → 每个 read 触发一次 write。noatime 关掉这个,大幅减少元数据写入。

生产挂载几乎一定加 noatime。

discard vs fstrim

SSD 需要 TRIM 通知"这些块不再用"。两种方式:

  • discard —— 实时(每次删文件都通知)。有时影响性能
  • fstrim —— 定期批量(cron / systemd timer 跑 fstrim /data)

推荐用 fstrim(定期)而不是实时 discard。Ubuntu 22+ 自带 fstrim.timer。


常见踩坑

坑 1:挂载到已有内容的目录

ls /data
# file1 file2 file3                  ← 原有内容

mount /dev/sdb1 /data
ls /data
# (空 / 或 sdb1 的内容)              ← 原有内容被"挡住"

挂载会把原有内容遮蔽(不是删,umount 之后还回来)。但程序在挂载时正在写 /data 的话 → 数据写到了已被遮蔽的旧空间、肉眼看不到。

养成挂载前 ls + 备份目录的习惯。

坑 2:mount 看到挂了、df 看不到

mount | grep sdb1                   # 看到
df -h | grep sdb1                   # 没看到

通常是挂载点路径不一致 / 类型不识别。findmnt / cat /proc/mounts 是更可靠的真相来源。

坑 3:fstab 写错导致系统启不来

下面这段写错 → 重启 → 卡 emergency mode:

/dev/wrong-device /data ext4 defaults 0 2

修:必须加 nofail:

/dev/sdb1 /data ext4 defaults,nofail 0 2

详见 fstab.md。

坑 4:用 /dev/sdX 而不是 UUID

/dev/sdb1 /data ext4 defaults 0 2

加新盘 / 重启之后 sdb 可能变成 sdc —— 挂载失败。

必须用 UUID:

blkid /dev/sdb1
# /dev/sdb1: UUID="abc-def-123..." TYPE="ext4"

# fstab:
UUID=abc-def-123... /data ext4 defaults,noatime 0 2

详见 fstab.md。

坑 5:bind mount 套娃

mount --bind /a /b
mount --bind /b /c
# /a /b /c 都是同一份数据
umount /b
# /c 还是访问 /a 的内容(bind 不传递)

这通常是好事——不互相依赖。但 K8s mount 卡死时 lazy umount 顺序错误可能让 /c 一直占用,得手动一层层处理。

坑 6:umount 之后磁盘还能写

umount /data
echo "test" > /data/file
ls /data
# 看到 file,但盘上没有!

/data 是个普通目录,umount 之后写入到了根分区的 /data 目录(被 mount 遮蔽的那个)。

K8s 里 pod 终止时如果 mount 残留,应用可能误写"假"位置。

防御:umount 后 ls -la /data 看是否预期。

坑 7:挂载点不存在

mount /dev/sdb1 /data
# mount: /data: mount point does not exist.

mkdir -p /data 先。

坑 8:FAT / NTFS 文件名编码问题

mount -t vfat /dev/sdc1 /mnt/usb
# 中文文件名乱码

加编码:

mount -t vfat -o iocharset=utf8,codepage=936 /dev/sdc1 /mnt/usb

服务器场景一般不挂 FAT,K8s 节点用不到。

坑 9:mount 卡住(NFS / iSCSI 卡死)

mount -t nfs server:/data /mnt
# 卡 30 秒以上

NFS server 不响应。

mount -t nfs -o timeo=5,retrans=2 server:/data /mnt   # 短超时

K8s 用 NFS PV 时,节点 down 会让所有挂这个 NFS 的 pod 卡在 Terminating。生产慎用 NFS。


关联命令

  • mkfs —— 先格式化才能 mount
  • fstab —— 持久化挂载
  • lsblk —— 看块设备拓扑
  • findmnt —— 看挂载(比 mount 命令更易读)
  • blkid —— 看 UUID / 类型
  • lsof —— umount 卡时找占用者
  • fuser -vm —— 同上,更短的输出
  • du / df —— 看用量
在 GitHub 上编辑此页