最近运维的一台服务器,突然收到了磁盘告警。上去一看,df -h
显示根目录 /dev/vda1
的使用率已经超过 95%。
这台服务器是 CentOS 7.2 老系统,上面跑着几个网站,网站文件都放在 /www/wwwroot
目录下。很明显,是网站数据把硬盘塞满了。
业务不能停,直接加一块硬盘是最快的办法。服务商给加了一块盘,系统里识别为 /dev/vdb
。
现在的目标很明确:
- 把
/www/wwwroot
里的所有数据,都挪到新硬盘上。 - 整个过程不能停掉 Nginx,网站要一直能访问。
- 不能修改任何 Nginx 或网站代码里的路径配置。
- 数据不能丢。
一番琢磨,最终的方案是利用软链接来"骗"过系统和程序。思路清晰,操作起来也放心。
准备新家:处理新硬盘
活儿要一步步干。先把新硬盘准备好,让它在系统里能用起来。这个过程分为三小步:分区、格式化、挂载。
1. 给新硬盘分区
一块全新的硬盘,就像一个没划分房间的毛坯房,得先给它分区。我用的是 fdisk
命令。
bash
fdisk /dev/vdb
进去之后,操作很简单,就是用 n
新建分区,然后一路回车,使用默认的设置,让这个分区占满整块硬盘。最后用 w
保存退出。这之后,系统里就多了一个叫 /dev/vdb1
的分区了。
可以用 lsblk
命令看看,确认一下分区是不是建好了。
2. 格式化分区
分区好了,就要格式化,相当于给房间铺上地砖。CentOS 7 默认推荐用 XFS 文件系统,性能不错。
bash
mkfs.xfs /dev/vdb1
这个命令跑完,分区就有了自己的文件系统。
3. 挂载硬盘
现在,要把这个准备好的分区,挂到系统的一个目录上,我们才能访问它。我打算把它挂载到 /data
目录。
先创建这个目录:
bash
mkdir /data
然后挂载上去:
bash
mount /dev/vdb1 /data
用 df -h
看一下,如果列表里出现了 /data
目录,并且对应的是 /dev/vdb1
,那就说明成功了。
但这样只是临时挂载,服务器重启后就没了。所以要把它写进开机启动项里。
先用 blkid
命令查一下新分区的 UUID,这是一串唯一的识别码,比设备名 /dev/vdb1
更可靠。
bash
blkid /dev/vdb1
复制下那串 UUID
的值,然后编辑 /etc/fstab
文件。
bash
vim /etc/fstab
在文件最后加上一行:
ini
UUID=刚才复制的那串字符 /data xfs defaults 0 0
保存退出。这样,新硬盘的"新家"就彻底安顿好了。
无感迁移数据
硬盘准备好了,接下来就是最关键的一步:在不影响网站的情况下,把数据挪移
这里的核心工具是 rsync
和 ln -s
。
rsync
用来同步文件,它非常强大,能保持文件所有属性不变。ln -s
用来创建软链接,也就是我们用来"欺骗"程序的快捷方式。
1. 第一次数据同步
首先,要把 /www/wwwroot
的数据完整地复制一份到 /data
。因为网站文件可能很多,这个过程会比较慢,但它不影响线上运行。
在开始前,先给新目录设置好和老目录一样的权限。
bash
# 查看老目录的所有者,比如是 www
ls -ld /www/wwwroot
# 创建新目录
mkdir /data/wwwroot
# 设置和老目录一样的所有者和权限
chown www:www /data/wwwroot
chmod --reference=/www/wwwroot /data/wwwroot
然后开始同步:
bash
rsync -avz --delete /www/wwwroot/ /data/wwwroot/
这个命令会把 /www/wwwroot/
目录下的所有内容,原封不动地同步到 /data/wwwroot/
。-a
参数保证了权限、时间戳这些信息都不变。--delete
确保目标目录和源目录完全一致。
这个过程耗时十几分钟,耐心等着就行。网站依然在老地方正常服务。
2. 闪电切换
第一次同步完成后,新旧目录的数据基本一样了。但同步期间,网站可能又产生了新数据,比如用户上传了图片。所以,我们需要在切换前,再进行一次极快的增量同步。
操作非常快,需要连续敲两个命令:
bash
# 1. 再次快速同步,只同步差异文件,几秒钟就完事
rsync -avz --delete /www/wwwroot/ /data/wwwroot/
# 2. 把老目录改个名,这个操作是瞬间完成的, 然后立刻创建软链接,指向新目录
mv /www/wwwroot /www/wwwroot_old && ln -s /data/wwwroot /www/wwwroot
这两步操作的间隔是毫秒级的。对于 Nginx 来说,它访问 /www/wwwroot
时,系统会告诉它:"哦,这个地方指向 /data/wwwroot
",然后 Nginx 就自动跑去新硬盘上读数据了。整个过程对它来说是透明的,所以服务不会中断。
检查和收尾
切换完成了,但工作还没结束。
首先,马上去点点网站,到处访问一下,看看有没有任何问题。
然后,检查一下链接是否正确:
bash
ls -l /www/
应该能看到 wwwroot -> /data/wwwroot
这样的箭头。
再用 df -h
确认一下,新硬盘 /data
的使用量上去了,老硬盘的空间被释放出来了。
最后,那个被改名的 /www/wwwroot_old
目录,先不要删! 这是你的后悔药。让网站在新位置上稳定运行一两天,确认万无一失之后,再执行删除。
bash
# 确认一切正常后,再删除备份
rm -rf /www/wwwroot_old
至此,整个无缝扩容就完成了。网站没停,配置没改,数据也安全。