Linux下使用bcache为HDD机械硬盘添加SSD缓存
在这篇教程中,我记录了一次为服务器上的大容量机械硬盘(HDD)添加SSD缓存的完整过程。我的目标是从一块已安装操作系统的SSD上,分割出一部分空间,利用Linux内核强大的bcache功能,来为HDD提供高速读写缓存,从而显著提升其I/O性能。 这个过程涉及分区调整、文件系统缩容、设备名变化等多个“坑”,本教程将一一记录并提供解决方案。
〇、环境与目标
- 硬件配置:
- 一块 50GB SSD,已安装操作系统 (
/dev/vda) - 一块 2TB HDD,用作数据盘 (
/dev/vdb) 
 - 一块 50GB SSD,已安装操作系统 (
 - 核心目标:
- 将 50GB 的 SSD 系统分区无损缩小至 30GB。
 - 利用剩余的 20GB 空间作为缓存分区。
 - 将 20GB 的SSD缓存与 2TB 的HDD绑定,创建一个名为 
bcache0的高性能虚拟设备。 
 
一、进入正确的救援环境(踩坑点一)
调整一个正在运行的系统分区是极其危险且不被允许的。因此,第一步必须进入一个完全独立于目标硬盘的“离线”救援环境。
1.1 错误的尝试
最初,我通过服务商面板进入了“救援模式”,但执行e2fsck检查磁盘时,系统提示设备已被挂载:
root@rescue:~# e2fsck -f /dev/vda1
/dev/vda1 is mounted.
e2fsck: Cannot continue, aborting.尝试卸载时,又提示目标忙:
root@rescue:~# umount /dev/vda1
umount: /: target is busy.通过df -h命令我发现,这个救援系统依然是从我自己的硬盘启动的,/dev/vda1被挂载为了根目录/。在这种模式下,我无法对自己“动刀”。
1.2 正确的诊断与进入
真正的救援模式应该从独立的介质(如网络、虚拟CD-ROM)启动。在重新启用救援模式后,我使用fdisk -l才知道哪哈错了:
root@rescue:~# fdisk -l
Disk /dev/vda: 4 GiB ...  <-- 这是一个独立的4GB救援系统盘
Device      Start   End    Sectors Size Type
/dev/vda1    2048 8388573 8386526   4G Linux filesystem
Disk /dev/vdb: 50 GiB ...  <-- 这才是我的目标SSD系统盘
Device      Start       End   Sectors Size Type
/dev/vdb1    2048 104857565 104855518  50G Linux filesystem
Disk /dev/vdc: 1.95 TiB ... <-- 这是我的HDD数据盘看到这就脱了!它表明我当前的环境是安全且正确的。救援系统运行在/dev/vda上,我的目标SSD /dev/vdb和HDD /dev/vdc都处于离线状态,可以安全操作。
记住救援模式下的设备名:
- 目标SSD: 
/dev/vdb - 目标HDD: 
/dev/vdc 
二、无损调整SSD分区
这是整个过程中风险最高的一步,在操作前请务必备份好 /dev/vdb1 上的所有重要数据!
2.1 检查并修复文件系统
在调整大小前,必须确保文件系统是健康的。
sudo e2fsck -f /dev/vdb1过程中,系统可能会发现一些不一致,比如“Free blocks count wrong”,并询问Fix<y>?。对所有问题都输入y并回车,让工具自动修复。
技巧:可以使用
e2fsck -fy /dev/vdb1命令来自动对所有问题回答“yes”。
2.2 缩小文件系统
关键原则: 必须先缩小文件系统,再缩小其所在的分区。 我将把文件系统缩小到29GB,比目标分区大小30GB略小,以留出安全余量。
sudo resize2fs /dev/vdb1 29G2.3 重新划分分区
使用fdisk工具对50GB的SSD (/dev/vdb)进行操作。
sudo fdisk /dev/vdb在fdisk的交互式命令行中,依次执行:
- 输入 
d:删除当前的分区1。 - 输入 
n:创建新分区。Partition number:1(回车)First sector:2048(直接回车,使用默认的起始扇区,这至关重要!)Last sector:+30G(创建一个30GB的分区)
 - 关键提问:系统会检测到旧的文件系统签名,并提问: 
Partition #1 contains a ext4 signature.Do you want to remove the signature? [Y]es/[N]o:必须输入N并回车! 选择No是为了保留我之前缩小的文件系统和数据。 - 再次输入 
n:创建第二个分区(缓存分区)。Partition number:2(回车)First sector: (直接回车,使用默认值)Last sector: (直接回车,使用所有剩余空间)
 - 输入 
p:检查新的分区表,确认/dev/vdb1约30GB,/dev/vdb2约20GB。 - 输入 
w:确认无误后,保存更改并退出。 
三、在救援模式下创建bcache设备
分区准备就绪,接下来就是将HDD和SSD缓存分区绑定。
3.1 格式化设备
- 将HDD (
/dev/vdc) 格式化为后端设备 (Backing Device):sudo make-bcache -B /dev/vdc - 将新的SSD分区 (
/dev/vdb2) 格式化为缓存设备 (Caching Device):sudo make-bcache -C /dev/vdb2 
3.2 附加缓存
# 查看并复制cset.uuid
sudo bcache-super-show /dev/vdb2
# 将<CSET_UUID>替换为上面复制的值
echo <CSET_UUID> > /sys/block/vdc/bcache/attach此时,lsblk应该能看到新的/dev/bcache0设备了。救援模式下的任务全部完成!
四、重启进入主系统并激活bcache(踩坑点二)
现在,可以从服务商面板禁用救援模式,让服务器正常启动,然后通过SSH登录。
4.1 问题诊断:设备名改变与bcache设备消失
登录主系统后,我发现/dev/bcache0不见了。 首先,检查磁盘名称,发现发生了设备名漂移:
root@smcjnvsss8:~# fdisk -l
Disk /dev/vda: 50 GiB ... <-- 在主系统里,SSD变成了vda
Device      Start      End   Sectors Size Type
/dev/vda1      2048 62916607  62914560  30G Linux filesystem
/dev/vda2  62916608 10485551  41938944  20G Linux filesystem
Disk /dev/vdb: 1.95 TiB ... <-- HDD变成了vdb记住主系统下的设备名:
- SSD缓存分区: 
/dev/vda2 - HDD: 
/dev/vdb 
接着,我尝试手动注册设备,但系统报错No such file or directory,这说明bcache内核模块没有自动加载。
4.2 解决方案:加载模块并手动注册
- 安装bcache工具(如果系统没有预装):
sudo apt-get update sudo apt-get install bcache-tools - 手动加载内核模块:
sudo modprobe bcache - 使用正确的设备名重新注册:
sudo echo /dev/vda2 > /sys/fs/bcache/register sudo echo /dev/vdb > /sys/fs/bcache/register 
执行完毕后,再次运行lsblk,激动人心的/dev/bcache0设备终于出现了!
五、格式化、挂载并永久使用
这是最后的收尾工作,让我的新设备真正可用。
- 格式化bcache设备:
sudo mkfs.ext4 /dev/bcache0 - 创建挂载点:
sudo mkdir /data - 挂载设备:
sudo mount /dev/bcache0 /data - 设置开机自动挂载(最稳妥的方式):
- 获取设备的UUID:
 复制sudo blkid /dev/bcache0UUID="..."引号内的长字符串。 - 编辑
fstab文件:sudo nano /etc/fstab - 在文件末尾添加新的一行(请替换成你自己的UUID):
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data ext4 defaults 0 2 - 保存并退出。
 
 - 获取设备的UUID:
 
总结
至此,我已经成功地完成了从规划、分区、踩坑到最终配置的全过程。服务器现在拥有一个由SSD高速缓存的2TB数据盘,兼顾了容量与性能。
核心要点回顾:
- 环境是关键:必须在真正的离线救援环境中操作目标磁盘。
 - 顺序很重要:必须先缩小文件系统,再缩小分区。
 - 注意设备名:救援模式和主系统的设备名可能会变化,要随时用
fdisk -l或lsblk确认。 - 模块要加载:主系统可能需要手动加载
bcache内核模块才能识别设备。 - 善用UUID:在
fstab中使用UUID挂载,可以避免因设备名变化导致的启动失败问题。 
希望这篇详细的实战记录能帮助到有同样需求的你!
