Skip to content

磁盘管理

磁盘扩容、挂载、空间告警排查,这些活儿运维天天干。但磁盘这块概念多、层级多——设备、分区、文件系统、挂载点、LVM、RAID,一层套一层,不把这些关系搞清楚,排查"磁盘满了""扩容没生效""重启后挂载丢了"这类问题就会一团乱。这篇按从底层到上层的顺序把这些概念串起来。

一、磁盘、分区、文件系统、挂载点

排查磁盘问题时,有四个概念特别容易混,先厘清:

概念是什么例子
设备系统识别到的物理或虚拟磁盘/dev/sdb
分区磁盘上划分出来的一段独立区域/dev/sdb1
文件系统组织数据的方式,决定文件怎么存怎么查xfs、ext4
挂载点文件系统接到目录树里的入口/data/mnt/backup

排查磁盘问题的顺序就是从这四层从下往上走:系统有没有识别到盘 → 分区表对不对 → 文件系统建了没 → 挂载了没。任何一层断了,上面的都白搭。

查看块设备和挂载关系:

bash
lsblk               # 块设备树:磁盘→分区→挂载点,最直观的总览
blkid               # 看 UUID 和文件系统类型
df -h               # 看各挂载点的空间使用情况
df -i               # 看 inode 使用情况

lsblk 是磁盘总览的最好工具,一眼看清设备、分区、挂载点三层关系。df -h 看空间,df -i 看 inode——有个经典坑:磁盘空间明明没满(df -h 还有余量)却写不进文件,十有八九是 inode 用完了(df -i 那一列 100%)。通常是某个目录里塞了几百万个小文件,每个文件占一个 inode,空间没占多少但 inode 耗光了。

二、分区

分区表是磁盘上的"目录",记录每个分区从哪到哪。老格式叫 MBR(DOS),只能支持 2TB 以下磁盘、最多 4 个主分区;现代格式叫 GPT,支持大磁盘、最多 128 个分区、还有备份分区表(主分区表坏了能恢复)。新盘现在基本都用 GPT。

bash
fdisk -l             # 查看所有磁盘分区(MBR 和 GPT 都能看)
parted -l            # 更详细,操作 GPT 也更方便

给新磁盘分区的流程,以 parted 为例:

bash
lsblk                # 先看磁盘设备名,确认是 /dev/sdb
parted /dev/sdb      # 进入 parted 交互模式

parted 交互模式里几个常用命令:mklabel gpt 创建 GPT 分区表(注意这步会清空原有分区!)、mkpart primary 0% 100% 创建一个占满整盘的主分区、print 看当前分区表、quit 退出。

分区完成之后通知内核重新读分区表:

bash
partprobe /dev/sdb       # 通知内核重新扫描分区
lsblk                    # 确认 /dev/sdb1 出现了

云环境有个坑:有些云主机的设备名重启之后可能变,比如这次是 /dev/sdb,重启后变成 /dev/sdc。所以挂载的时候别依赖设备名,用 UUID——UUID 是文件系统格式化时生成的,不会变。这就是为什么 fstab 里都推荐写 UUID 而不是 /dev/sdb1

三、格式化

在分区上创建文件系统:

bash
mkfs.xfs /dev/sdb1
mkfs.ext4 /dev/sdb1

XFS 和 ext4 是两个主流选择。简单说:RHEL 7+ 默认用 XFS,适合大文件大数据;ext4 是通用选择,Ubuntu 上常见。两者都支持在线扩容,但都不支持在线缩容(XFS 压根不支持缩,ext4 要先卸载)。

格式化会清空分区上原有数据,这是不可逆的。所以生产环境执行 mkfs 之前,一定要再确认一遍设备和挂载情况:

bash
lsblk -f             # 看当前文件系统类型,确认这块盘不是正在用的
mount | grep sdb     # 确认这块盘没被挂载使用

格式化错盘导致数据全没的事故真实发生过——把正在跑业务的盘 mkfs 了,数据直接归零。多确认两秒,值得。

四、挂载与 fstab

挂载就是把文件系统接到目录树的某个位置:

bash
mkdir -p /data
mount /dev/sdb1 /data
df -h /data

手动 mount 重启后就失效了,持久化挂载要写进 /etc/fstab。fstab 里推荐用 UUID 指定设备:

bash
blkid /dev/sdb1            # 获取这块盘的 UUID

/etc/fstab 一行长这样:

UUID=xxxx-xxxx /data xfs defaults 0 0

六列从左到右:设备标识(用 UUID=xxxx-xxxx,比设备路径可靠)、挂载点(/data)、文件系统类型(xfs)、挂载选项(defaults 是一组默认参数)、dump 备份标志(通常 0)、fsck 检查顺序(根分区是 1,其他是 2,0 表示跳过)。

写完 fstab 之后,务必先用 mount -a 测试一遍——它会按 fstab 把所有未挂载的条目挂载一遍。如果 fstab 有语法错误,mount -a 会立刻报错,你当场就能改;但如果直接重启,fstab 写错可能导致系统进 emergency mode(紧急模式),连正常登录都难,得接控制台修。这一步测试值千金。

五、SWAP

SWAP 是磁盘上划出来的一块区域,当物理内存不够用的时候,内核会把不活跃的内存页换到 SWAP 上,腾出物理内存给更需要的进程。本质是用磁盘当"溢出的内存",速度比物理内存慢几个数量级,所以只是应急,不是常态方案。

bash
free -h              # 看内存和 SWAP 使用量
swapon --show        # 看当前 SWAP 设备

创建 SWAP 文件:

bash
fallocate -l 2G /swapfile          # 创建 2G 大小的文件
chmod 600 /swapfile                # SWAP 文件权限要严格(只 root 可读写)
mkswap /swapfile                   # 格式化为 SWAP
swapon /swapfile                   # 启用

写入 /etc/fstab 永久生效:

/swapfile none swap sw 0 0

数据库服务器(MySQL、PostgreSQL、Redis)通常不希望依赖 SWAP——数据库一旦开始大量换出到 SWAP,性能会断崖式下跌,本来毫秒级的查询变成秒级。偶尔换出一点点是正常的,但如果看到 SWAP 在频繁大量活动(thrashing),说明物理内存严重不足,得加内存或者优化配置,而不是放任它用 SWAP。

六、LVM

LVM(Logical Volume Manager)在物理磁盘和文件系统之间加了一层抽象,最大的好处是能动态扩容——不用停服务、不用卸载文件系统,就能给逻辑卷加空间。云环境之外(云盘本身能在线扩容)的物理服务器,LVM 几乎是标配。

LVM 是三层结构:PV(物理卷)是把磁盘分区初始化成 LVM 能管的;VG(卷组)是多个 PV 组成的存储池;LV(逻辑卷)是从 VG 里划出来的逻辑空间,文件系统就建在 LV 上。

创建流程:

bash
pvcreate /dev/sdb1                          # 把分区初始化成物理卷
vgcreate vg_data /dev/sdb1                  # 创建卷组 vg_data
lvcreate -n lv_data -l 100%FREE vg_data    # 用全部剩余空间建逻辑卷
mkfs.xfs /dev/vg_data/lv_data               # 在逻辑卷上建文件系统

扩容流程(加了新磁盘之后):

bash
pvcreate /dev/sdc1                # 新磁盘初始化成 PV
vgextend vg_data /dev/sdc1        # 把新 PV 加进卷组(VG 变大)
lvextend -r -l +100%FREE /dev/vg_data/lv_data   # 扩 LV 并同步扩文件系统

注意 -r 参数——它会自动扩展文件系统(内部调 xfs_growfsresize2fs),不用你手动再跑一遍扩容命令。忘了 -r 的话,逻辑卷是大了,但文件系统还是原来的大小,白扩。

查看 LVM 状态:pvs 看物理卷、vgs 看卷组、lvs 看逻辑卷。

LVM 扩容方便,但缩容麻烦——前面说了 XFS 不支持在线缩容,ext4 也要先卸载。所以规划存储的时候,"以后不够再缩"不是个好假设,空间宁可一开始规划宽松点。

七、RAID

RAID 用多块磁盘组合成逻辑存储,提供性能提升或冗余保护。常见级别:

级别特点适用场景
RAID 0条带化,性能好但无冗余,坏一块盘数据全丢不重要、追求性能的数据
RAID 1镜像,容量减半,坏一块还能继续跑系统盘、重要数据
RAID 5奇偶校验,可坏 1 块盘,空间利用率高一般业务存储
RAID 10镜像+条带,性能好且冗余,最少 4 块盘高性能高可靠场景

Linux 软件 RAID 用 mdadm 管理:

bash
cat /proc/mdstat              # 看当前 RAID 状态(哪几块盘、是否降级)
mdadm --detail /dev/md0       # 看指定 RAID 设备的详细信息

云环境里基本不需要自己搞 RAID——云平台的底层存储通常已经做了冗余(多副本、分布式存储),你在云主机上看到的一块"云盘"背后已经是高可靠的。再套一层软件 RAID 没什么额外收益,反而增加复杂度。云盘的可靠性保障和 RAID 解决的物理盘故障,根本不是一个层面的事。

八、排查空间占用

磁盘告警的排查分两步:先定位是哪个目录在吃空间,再找到具体的大文件

bash
df -h                 # 确认哪个分区满了
du -sh /*             # 根目录下各目录的占用,看哪个大
du -sh /var/*         # 逐层深入
find /var -type f -size +1G -ls     # 直接列出大于 1G 的文件

还有一种很迷惑的情况:文件删了,但空间没释放。明明 rm 掉了一个几十 G 的日志文件,df -h 显示空间一点没少。原因是还有进程持有这个文件的文件描述符——文件从目录里消失了,但 inode 没释放,空间还占着。排查用:

bash
lsof | grep deleted

输出里带 (deleted) 标记的,就是这种"已删除但还被占着"的文件。解决办法:重启那个持有文件的进程(让文件描述符释放),或者让进程重新打开日志文件(比如 systemctl reload nginx,nginx 会重新打开日志文件,旧的就被释放了)。