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" /homeStep 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 模式。注意 grpquota 和 prjquota 不能并存。
# 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 指令对照
| 操作 | XFS | EXT 家族 |
|---|---|---|
| fstab 参数 | usrquota/grpquota/prjquota | usrquota/grpquota |
| 配置文件 | 不需要 | quotacheck |
| 设置限制 | xfs_quota -x -c "limit..." | edquota / setquota |
| 观察报告 | xfs_quota -x -c "report..." | repquota / quota |
| 开关 | disable/enable | quotaoff / 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-0 | RAID-1 | RAID-10 | RAID-5 | RAID-6 | |
|---|---|---|---|---|---|
| 最少盘数 | 2 | 2 | 4 | 3 | 4 |
| 容错盘数 | 0 | n-1 | n/2 | 1 | 2 |
| 可用容量 | n | 1 | n/2 | n-1 | n-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/lvm14.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 层 | 文件系统层 |
|---|---|---|---|---|
| 创建 | pvcreate | vgcreate -s PE大小 VG名 PV列表 | lvcreate -L 容量 -n LV名 VG名 | mkfs.xfs |
| 查看 | pvscan / pvdisplay | vgscan / vgdisplay | lvscan / lvdisplay | df / xfs_info |
| 扩容 | — | vgextend VG名 新PV | lvresize -L +容量 LV | xfs_growfs |
| 缩容 | — | vgreduce VG名 PV | lvreduce(慎用) | EXT: resize2fs;XFS 不支持 |
| 删除 | pvremove | vgremove | lvremove | — |
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 快照 |