14.1 磁盘配额(Quota)的应用与实作

Linux 是多用户系统,如果某个人狂塞影片把 /home 占满,其他人就没法用了。Quota 就是限制每个用户/群组/目录能用多少磁盘空间的机制

14.1.1 什么是 Quota

Quota 的典型用途:

  • WWW 服务器:每人网页空间限制
  • Mail 服务器:每人邮箱容量限制
  • 文件服务器:每人网络硬盘配额

Quota 的限制维度

  • 针对使用者(user):限制某个人
  • 针对群组(group):限制某个群组的总和
  • 针对目录(project):限制某个特定目录(XFS 独有,EXT 家族做不到)

两个限制项目

  • block 限制:限制磁盘容量(较常用)
  • inode 限制:限制可创建的文件数量

Soft / Hard / Grace Time 机制

概念说明
soft(柔性)警告线。超过 soft 时系统会发出警告,并开始倒计时
hard(硬性)绝对上限。达到 hard 时锁住磁盘使用权,无法再写入
grace time(宽限时间)soft→hard 之间的缓冲期。默认 7 天,期间不把用量降回 soft 以下,soft 值会变成新的 hard 限制
用量 < soft  → 一切正常
soft < 用量 < hard → grace time 倒计时,每次登录都会收到警告
用量 ≥ hard → 锁住,禁止新增文件

使用限制

  • EXT 家族只能针对整个文件系统,XFS 还可以针对单个目录(project 模式)
  • 只对一般用户有效,root 不受限制
  • 核心必须支持(CentOS 7 默认已支持)

14.1.2 XFS 文件系统的 Quota 实作流程

Step 1:修改 /etc/fstab,挂载时启用 quota

# 在 /etc/fstab 的第四字段加入:
#   usrquota  → 用户配额
#   grpquota  → 群组配额(与 prjquota 互斥)
#   prjquota  → 目录/项目配额
 
/dev/mapper/centos-home  /home  xfs  defaults,usrquota,grpquota   0 0

修改后 umount /home && mount -a 重新挂载。注意:XFS 的 quota 必须在挂载之初就声明,不能用 remount 事后加。

Step 2:用 xfs_quota 观察状态

xfs_quota -x -c "print"              # 查看哪些文件系统启用了 quota
xfs_quota -x -c "df -h" /home        # 查看用量
xfs_quota -x -c "report -ubih" /home # 查看用户配额报告
xfs_quota -x -c "state" /home        # 查看 quota 启用状态

-x 是专家模式,后面的 -c "指令" 执行具体操作。

Step 3:设置限制值

# 限制用户:bsoft=250M, bhard=300M
xfs_quota -x -c "limit -u bsoft=250M bhard=300M myquota1" /home
 
# 限制群组:bsoft=950M, bhard=1G
xfs_quota -x -c "limit -g bsoft=950M bhard=1G myquotagrp" /home
 
# 修改宽限时间为 14 天
xfs_quota -x -c "timer -ug -b 14days" /home

Step 4:测试

su - myquota1
dd if=/dev/zero of=test.img bs=1M count=310   # 超过 300M hard 限制 → "Disk quota exceeded"

14.1.3 Project 模式——针对目录限制

如果要对 /home/myquota 这个目录本身限制容量(不管是谁在里面创建文件),用 project 模式。注意 grpquotaprjquota 不能并存

# 1. /etc/fstab 改为 prjquota,重新挂载
# 2. 定义项目名称和 ID
echo "11:/home/myquota" >> /etc/projects       # ID:路径
echo "myquotaproject:11" >> /etc/projid         # 名称:ID
# 3. 初始化
xfs_quota -x -c "project -s myquotaproject"
# 4. 设置限制
xfs_quota -x -c "limit -p bsoft=450M bhard=500M myquotaproject" /home

这样 root 在该目录下创建文件也会被限制——是真正的按目录限额,不限用户。

14.1.4 Quota 管理指令

动作指令
暂时关闭限制(还在统计)xfs_quota -x -c "disable -up" /home
重新启用xfs_quota -x -c "enable -up" /home
完全关闭(需卸载重挂载才能恢复)xfs_quota -x -c "off -up" /home
移除所有限制值xfs_quota -x -c "remove -p" /home(需先 off)

实用技巧:如果 /var/spool/mail/home 不在同一文件系统,无法一次性设 quota。办法是把 /var/spool/mail 移到 /home/mail,再 ln -s /home/mail /var/spool/mail,然后给 /home 文件系统设 quota。

14.1.5 XFS vs EXT Quota 指令对照

操作XFSEXT 家族
fstab 参数usrquota/grpquota/prjquotausrquota/grpquota
配置文件不需要quotacheck
设置限制xfs_quota -x -c "limit..."edquota / setquota
观察报告xfs_quota -x -c "report..."repquota / quota
开关disable/enablequotaoff / quotaon

14.2 软件磁盘阵列(Software RAID)

RAID(Redundant Arrays of Inexpensive Disks) 的核心价值是用多颗便宜磁盘组合出大容量、高性能、带数据保护能力的单一磁盘设备

14.2.1 常见 RAID 等级

RAID-0(等量模式 / Stripe)—— 性能最佳、零保护

数据被切成等量小块(chunk,一般 4K~1M),交错分散写入所有磁盘。写入 100MB → 两颗盘各写 50MB,写性能翻倍。

  • ✅ 性能最佳,总容量 = 所有磁盘之和
  • ❌ 任何一颗盘坏了 → 所有数据全毁(文件被切碎分散在各盘,缺一块就不完整)
  • 最少需 2 颗盘

RAID-1(映射模式 / Mirror)—— 完整备份

同一份数据同时写入两颗磁盘,内容完全一致,像照镜子。

  • ✅ 数据最安全——只要有一块盘还活着数据就在
  • ❌ 总容量只有总盘数的一半,写入性能差(数据要复制两份往 I/O 总线走)
  • 最少需 2 颗盘

RAID 1+0(RAID 10)—— 性能+安全最佳组合

先两两做 RAID-1(镜像),再把多组 RAID-1 组成 RAID-0(条带)。以 4 颗盘为例:Disk A+B 组 RAID-1 #1,Disk C+D 组 RAID-1 #2,两组再组 RAID-0。

  • ✅ 性能好、安全好、重建速度快(每组 RAID-1 独立重建,只需从配套盘复制)
  • ✅ 读写无需 parity 计算,比 RAID-5/6 快
  • ❌ 可用容量只有总容量的一半
  • 最少需 4 颗盘,目前业界最推荐的方案

RAID-5 —— 性能与容量的折中

类似 RAID-0 的交错写入,但每个 stripe 额外存一份同位检查码(Parity)分散在各盘上。任一颗磁盘损坏时,可通过 parity 和其他盘的数据反算重建。

  • ✅ 可用容量 = (n-1) 颗盘
  • ❌ 写入性能较差(每次写要算 parity),只能容忍 1 颗盘坏
  • ❌ 重建慢——所有盘要一起参与计算
  • 最少需 3 颗盘

RAID-6 —— RAID-5 升级版

两份 parity,可以同时坏 2 颗盘。可用容量 = (n-2) 颗盘。最少需 4 颗盘。

Spare Disk(预备磁盘)

一颗或多颗平时不用的闲置盘。当阵列中有盘损坏时,spare disk 自动顶上并开始重建。管理员只需事后把坏盘拔出来、换颗新的、设为新的 spare disk。配合热拔插(hot-swap)的话全程不需关机。

各等级对比(n 颗盘)

RAID-0RAID-1RAID-10RAID-5RAID-6
最少盘数22434
容错盘数0n-1n/212
可用容量n1n/2n-1n-2
写入性能n 倍1 倍n/2 倍< n-1< n-2
适用场景性能至上有备份数据绝对安全云/虚拟化一般数据大容量+安全

14.2.2 硬件 RAID vs 软件 RAID

硬件 RAID软件 RAID
实现方式专用 RAID 卡(有独立芯片)OS 内核软件模拟
CPU 消耗无(卡自己算)消耗系统 CPU
性能最好现代 PC 已足够快
热拔插中高端支持配合 mdadm 可模拟
设备文件名/dev/sd[a-p](OS 只看到一颗大磁盘)/dev/md0, /dev/md1
成本贵(万元台币起)免费

CentOS 的软件 RAID 用 mdadm 管理,可以以**分区(partition)**为 RAID 单位——不需要多块独立磁盘。

14.2.3 软件 RAID 实作(mdadm)

创建 RAID-5 + spare disk(4 颗数据盘 + 1 颗 spare):

# 先用 gdisk 创建 5 个分区,system ID 设为 FD00(Linux RAID)
 
# 创建 RAID
mdadm --create /dev/md0 --auto=yes --level=5 --chunk=256K \
      --raid-devices=4 --spare-devices=1 /dev/vda{5,6,7,8,9}
 
# 查看详情
mdadm --detail /dev/md0
cat /proc/mdstat

模拟磁盘损坏 & 恢复

# 标记某盘为故障
mdadm --manage /dev/md0 --fail /dev/vda7
# spare disk 自动顶上重建!→ 查看发现 vda9 变成了 active
 
# 移除坏盘
mdadm --manage /dev/md0 --remove /dev/vda7
# 物理换盘后加回来
mdadm --manage /dev/md0 --add /dev/vda7

全过程文件系统一直在线可用,不需要卸载。

格式化并挂载

mkfs.xfs -f -d su=256k,sw=3 -r extsize=768k /dev/md0
mkdir /srv/raid
mount /dev/md0 /srv/raid

关键是格式化时的 stripe 参数对齐(su=chunk大小, sw=数据盘数)。

开机自动挂载:写 /etc/mdadm.conf(UUID)+ /etc/fstab

关闭 RAID(不再需要时):

umount /srv/raid
# 从 /etc/fstab 和 /etc/mdadm.conf 删掉相关行
dd if=/dev/zero of=/dev/md0 bs=1M count=50    # 擦除 RAID metadata
mdadm --stop /dev/md0                           # 停止
dd if=/dev/zero of=/dev/vda5 bs=1M count=10    # 擦除每个成员分区的 superblock
# ... vda6, vda7, vda8, vda9 同理

注意:如果不擦除分区上的 RAID metadata,重启后系统可能又把 /dev/md127 给重建出来。

14.3 逻辑卷轴管理员(Logical Volume Manager)

这是本章最重要的部分——也是你之前问的 PV、VG、LV 在哪里 的答案。

14.3.1 为什么需要 LVM?

传统的”物理盘 → 分区 → 格式化 → 挂载”有硬伤:分区大小是死的/home 当初分了 50G,用光了怎么办?只能备份→删分区→重建更大的→恢复数据。如果想缩小呢?同样折腾。

LVM 的核心价值:文件系统容量可以在线弹性调整,不影响已有数据。

LVM 的重点是弹性,不是性能也不是数据安全(那些靠 RAID)。

14.3.2 核心概念:PV, PE, VG, LV

回顾之前给的类比,现在展开讲:

物理磁盘(/dev/sda, /dev/sdb...)           ← 多块铁
  ↓ pvcreate
PV(Physical Volume,实体卷轴)            ← 标记为"LVM 可用"
  ↓ vgcreate / vgextend
VG(Volume Group,卷轴群组)               ← 多个 PV 拼成的"大池子"
  ↓ lvcreate
LV(Logical Volume,逻辑卷轴)             ← 从池子切出的"逻辑分区"
  ↓ mkfs.xfs → mount
文件系统 ← 挂载使用                          ← 跟普通分区一样

逐层解释

① PV(Physical Volume)— 最底层

把实体 partition(或整颗 disk)用 pvcreate 转成 LVM 能认的格式。system ID 建议改为 8e(Linux LVM),但不改也能用。

pvcreate /dev/vda{5,6,7,8}   # 将 4 个分区标记为 PV
pvscan                         # 查看所有 PV
pvdisplay /dev/vda5            # 查看某个 PV 详情

② PE(Physical Extent)— LVM 的最小储存单位

PE 是整个 LVM 的最小分配单位——就像文件系统里的 block 一样。创建 VG 时指定 PE 大小(默认 4MB),之后所有 LV 的分配和调整都以 PE 为单位。

PE = 给 LV 塞数据的”最小砖块”。LV 放大缩小,就是往 LV 里加 PE 块或从中抽 PE 块。

③ VG(Volume Group)— 大池子

把多个 PV 合并成一个 VG,变成一块逻辑上的”超大磁盘”。VG 的大小就是所有 PV 容量之和,且可以在线加盘扩容

vgcreate -s 16M vbirdvg /dev/vda{5,6,7}   # 创建 VG,PE=16M
vgdisplay vbirdvg                            # 查看 VG
vgextend vbirdvg /dev/vda8                   # 扩容:把 vda8 加入

④ LV(Logical Volume)— 可用的”逻辑分区”

从 VG 中切出来的”分区”,设备名为 /dev/VG名称/LV名称(如 /dev/vbirdvg/vbirdlv)。LV 的大小必须是 PE 的整数倍。

lvcreate -L 2G -n vbirdlv vbirdvg   # 创建 2GB 的 LV
lvscan                                # 查看所有 LV
lvdisplay /dev/vbirdvg/vbirdlv       # 查看 LV 详情

LV 数据写入有两种模式

  • 线性模式(linear,默认):先写满第一个 PV,再用第二个 PV…,推荐
  • 交错模式(striped):类似 RAID-0,同时往多个 PV 写。性能好但任何一 PV 损坏则全 LV 数据毁灭。要性能+安全直接用 RAID,LVM 不是干这个的

14.3.3 LVM 完整实作流程

# 1. PV 阶段
pvcreate /dev/vda{5,6,7,8}
 
# 2. VG 阶段
vgcreate -s 16M vbirdvg /dev/vda{5,6,7}
vgextend vbirdvg /dev/vda8   # 把剩余盘也加进去
 
# 3. LV 阶段
lvcreate -L 2G -n vbirdlv vbirdvg
 
# 4. 文件系统阶段
mkfs.xfs /dev/vbirdvg/vbirdlv
mkdir /srv/lvm
mount /dev/vbirdvg/vbirdlv /srv/lvm

14.3.4 在线放大 LV 容量——LVM 的核心杀招

三步走:确保 VG 有空间 → 扩展 LV → 扩展文件系统。全程在线,不用卸载

# 1. 确认 VG 有剩余空间
vgdisplay vbirdvg | grep Free
 
# 2. 扩展 LV(+500M)
lvresize -L +500M /dev/vbirdvg/vbirdlv
 
# 3. 扩展文件系统(XFS)
xfs_growfs /srv/lvm

注意:XFS 只能放大不能缩小。要能缩放的用 EXT4(resize2fs)。

LV 放大后,xfs_info 能看到 agcount(allocation group 数量)增加了——新增的空间格式化为新的 AG 并入 superblock,原有数据完全不受影响。

14.3.5 LVM Thin Volume——按需分配

传统 LV 一创建就占满指定容量。Thin Volume 则是”声明 5T,实际用多少占多少”——在 VG 里创建 thin pool,从 pool 里分配 thin LV。适合给用户承诺大容量但初期用不到的场景。

14.3.6 LVM 快照(Snapshot)

快照是将某一时刻 LV 的状态”冻结”下来。原理:快照区不存完整数据,只存”被修改过的 PE 的旧版本”。创建快照时 LV 上的数据不动,之后每当 LV 上有数据被修改,原始数据先复制到快照区,再执行修改。快照区存的就是”变化前的样子”。快照常用来做备份前的瞬间冻结——创建快照 → 挂载快照 → 备份快照里的数据 → 删除快照,期间主 LV 正常使用不受影响。

14.3.7 LVM 指令速查

操作PV 层VG 层LV 层文件系统层
创建pvcreatevgcreate -s PE大小 VG名 PV列表lvcreate -L 容量 -n LV名 VG名mkfs.xfs
查看pvscan / pvdisplayvgscan / vgdisplaylvscan / lvdisplaydf / xfs_info
扩容vgextend VG名 新PVlvresize -L +容量 LVxfs_growfs
缩容vgreduce VG名 PVlvreduce(慎用)EXT: resize2fs;XFS 不支持
删除pvremovevgremovelvremove

14.3.8 全链路总结:从物理磁盘到挂载点

结合第二章、第七章、第十四章,把”从铁片到你能用的目录”这条链路串起来:

物理磁盘(/dev/sda, /dev/sdb...)               ← 第零章/第二章
  └─ MBR / GPT 分区表                            ← 第二章
       └─ 分区(/dev/sda1, /dev/sda2...)        ← 第二章
            ├─ 传统路线:格式化 → 挂载           ← 第七章
            │
            └─ LVM 路线:                        ← 第十四章
                 ↓ pvcreate
               PV(/dev/sda1 被标记为 LVM 可用)
                 ↓ vgcreate
               VG(多个 PV 汇成大池子)
                 ↓ lvcreate
               LV(/dev/vgname/lvname,类比分区的"逻辑卷")
                 ↓ mkfs.xfs
               文件系统(inode / block / superblock)
                 ↓ mount
               挂载点(一个目录,用户从这里读写)

mount point 在这一整条链路的最末端——它是文件系统和目录树的”接口”。不管你下面用了多少层抽象(分区、LVM、RAID),最终用户看到的都是”一个目录”,数据是怎么存下去的由下面几层透明处理。这就是 Linux “一切皆文件”的威力。

关键命令

命令用途
xfs_quota -x -c "limit -u bsoft=... bhard=... 用户" 挂载点设置用户磁盘配额
xfs_quota -x -c "report -ubih" 挂载点查看配额报告
xfs_quota -x -c "timer -ug -b 14days" 挂载点设置宽限时间
xfs_quota -x -c "disable -up" 挂载点暂时关闭配额限制
mdadm --create /dev/md0 --level=5 --raid-devices=4 --spare-devices=1 /dev/vda{5..9}创建软件 RAID5
mdadm --detail /dev/md0查看 RAID 详情
mdadm --manage /dev/md0 --fail /dev/vda7模拟磁盘故障
mdadm --manage /dev/md0 --remove /dev/vda7从 RAID 中移除磁盘
mdadm --manage /dev/md0 --add /dev/vda7添加新磁盘到 RAID
mdadm --stop /dev/md0停止 RAID
pvcreate /dev/vda5创建 PV
vgcreate -s 16M vbirdvg /dev/vda{5,6,7}创建 VG
vgextend vbirdvg /dev/vda8扩展 VG
lvcreate -L 2G -n vbirdlv vbirdvg创建 LV
lvresize -L +500M /dev/vbirdvg/vbirdlv扩展 LV
xfs_growfs /srv/lvm扩展 XFS 文件系统
lvcreate -s -L 1G -n snap1 /dev/vbirdvg/vbirdlv创建 LV 快照