尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Linux磁盘扩容实战:从挂载新盘到LVM在线扩容

Linux磁盘扩容实战:从挂载新盘到LVM在线扩容 后台经常会收到这类提问“服务器根目录满了怎么办”“某个数据目录容量不够能不能加一块盘直接顶上”这类问题在Linux运维里实在太常见了。很多刚接触Linux的朋友一看到df -h里/的使用率冲到100%就开始慌以为只能重装系统或者删库跑路。其实不用这么紧张Linux的目录挂载机制本身就是为这种场景设计的你可以随时加一块新磁盘把它挂载到根目录或者某个指定目录上让那个目录直接使用新盘的空间应用路径完全不用改。这篇文章就是我整理的一份完整实操记录围绕“挂载磁盘扩容”这个主题把从磁盘诊断、分区格式化、临时/永久挂载到根目录替换和LVM在线扩容的整套流程都过一遍配合我实际踩过的坑希望能给同样被磁盘空间卡住的朋友一条清晰的解决路径。1. 扩容前的诊断目录是真的不够还是垃圾文件太多1.1 三个命令快速定位磁盘现状遇到磁盘告警我会先做三件事基本上三分钟就能判断出问题的大致范围。第一个是df -h看整体使用率。重点关注/、/var、/home这类大型目录所在分区的使用百分比。如果某个分区达到90%以上基本可以判断目前确实处于空间紧张状态。第二个是lsblk看系统里有没有“新盘未挂载”的情况。很多云服务器或者虚拟机加盘之后并不会自动挂载盘已经在系统里了只是还没被使用。lsblk输出里如果看到一个没有挂载点的磁盘比如/dev/sdb或/dev/vdb那说明系统里其实有可用资源只是还没有纳入文件系统管理。第三个是du找出到底是哪个目录在疯狂吃空间。我会用这条命令快速定位du -h --max-depth1 / 2/dev/null | sort -hr | head -20这条命令会把根目录下各个一级子目录按占用空间从大到小排列。运行完你通常能看到两种结果一种是某个业务目录比如/data、/var/lib/mysql、/www特别大另一种是/usr或者/var这类系统目录异常膨胀。两种情况对应的扩容策略是完全不同的先定位再动手能少走很多弯路。1.2 先清理再扩容避免“一满就加盘”的冲动说句实在话我处理过的磁盘告警里至少有三分之一靠清理就能解决根本不需要动到磁盘挂载这种层面。常见的大户有这么几类systemd 日志。很多服务器默认的 journal 日志积累起来非常惊人一条命令就能限制体积journalctl --vacuum-size200M这条命令会把 journal 日志压缩/清理到 200MB 以内。如果是长期运行的服务器建议再加一条永久限制修改/etc/systemd/journald.conf里的SystemMaxUse200M防止日志再次膨胀。Docker 相关的资源。如果机器上用 Docker/var/lib/docker很容易吃满磁盘。容器日志、悬空镜像、构建缓存都会堆积。可以先看docker system df然后用docker system prune清理悬空资源并限制容器日志大小。比如在/etc/docker/daemon.json里加上{ log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 } }包管理器缓存。yum 或 apt 的缓存文件也会占掉好几个G。分别用yum clean all和apt-get clean清掉安安静静地就腾出空间了。临时文件和旧的压缩包。很多人把下载的安装包、备份包直接扔在/tmp或者/root下时间一长非常占地方。find / -xdev -size 500M -exec ls -lh {} \;这条命令能快速找出超过500MB的大文件看看有哪些是可以删掉的。这里要提醒一句清理要有度。数据库文件、业务日志、用户上传数据这些属于业务数据别轻易删。我们要清理的是“确定无用”的系统垃圾。如果清理完空间依然吃紧或者你明确知道某个目录会因为业务增长持续膨胀那才进入下一步挂载新盘。2. 理解挂载机制为什么目录空间不够加一块盘就能解决2.1 挂载的本质目录只是文件系统树上的一个接入点想理解“挂载磁盘扩容”这件事必须先理解Linux里“一切皆文件”的底层设计。在Linux的视角里磁盘不是一个一个的盘符而是一个统一的目录树。一块物理磁盘要被使用需要经过“分区 - 格式化 - 挂载”三个步骤而“挂载”这个动作本质上就是把一个设备上的文件系统“接入”到目录树的某个节点上。这个节点就是挂载点。挂载点本身只是一个普通的目录可以是空目录也可以是已经有数据的目录。一旦某个分区被挂载到目录/data上所有写入/data的数据就都会落到这个分区的存储空间里。目录本身不占固定的磁盘空间真正的空间量取决于挂载在这个目录上的分区有多大。用一句通俗的话来类比分区相当于一个仓库目录相当于门牌号。挂载就是把仓库和门牌号绑定在一起。当/data这个门牌号背后的仓库满了你不需要把仓库里的东西都搬出来只需要把一个新的、更大的仓库挂到同一个门牌号下这个门牌号背后的可用空间就变大了。这就是挂载扩容最核心的逻辑。2.2 三种扩容路径的取舍针对“某个目录空间不足”的场景实际操作中通常有三条路径直接将新盘挂载到一个空目录。适合新增业务、新开一个存储目录操作最简单不需要动任何旧数据。将新盘挂载到已有数据的目录需要先把旧数据迁移到新盘再完成挂载替换。适合/data、/www这类已有大量业务数据的目录。通过LVM逻辑卷在线扩容。如果系统安装时采用了LVM方案根分区和部分大目录本身就是逻辑卷可以做到几乎不中断服务就完成在线扩容这种方式最优雅。这三条路径的使用场景差异很大我整理了一张对比表方案适用场景是否需要停机操作复杂度数据安全性新盘挂载到空目录新增目录、新业务存储不需要低无旧数据风险新盘挂载到已有数据的目录业务目录空间不足需要短暂停写中等迁移数据时有风险LVM在线扩容根目录、系统盘扩容基本不需要中高相对安全选定方案之后就可以动手实操了。下面两章我会分别演示“挂载到指定目录”和“挂载根目录/系统盘扩容”的完整流程。3. 实操一把新盘挂载到指定目录给业务目录扩容3.1 识别新磁盘并完成分区初始化假设你要给/data目录扩容这块目录目前挂在旧分区上空间见底。你现在插入了一块新盘在物理机上是新硬盘在虚拟机上就是新增一块虚拟磁盘。第一步是让系统识别到它。lsblk执行后能看到类似这样的输出NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 100G 0 disk ├─sda1 8:1 0 1G 0 part /boot └─sda2 8:2 0 99G 0 part / sdb 8:16 0 200G 0 disksdb就是新加的磁盘容量200G目前没有任何分区和挂载点。接下来的操作要十分小心确认目标磁盘是/dev/sdb千万不要搞错盘符把系统盘给格式化了。在虚拟机上通常新盘是/dev/vdb或者/dev/sdb在物理机上可以用lsscsi或lsblk -d -o name,size,model进一步确认。然后对/dev/sdb进行分区fdisk /dev/sdb进入交互界面后依次输入n # 新建分区 p # 主分区 1 # 分区编号 回车 # 起始扇区默认 回车 # 结束扇区默认使用整块盘 w # 保存并退出完成后用lsblk查看应该能看到sdb1这个分区了。这里解释一下为什么要分区分区本质上是给整块盘建立一层“索引”以后你可以基于这个分区做格式化、扩容、备份等操作如果整块盘直接格式化也不报错但后续管理会很不方便。对于超过2TB的大容量磁盘fdisk默认的MBR分区表支持不了需要用parted工具创建GPT分区表parted /dev/sdb mklabel gpt mkpart primary 0% 100% quit分区做完之后就是格式化。Linux原生的文件系统通常选ext4或xfs。我个人偏好ext4原因是它成熟、稳定、兼容性好而且支持在线扩容命令resize2fs。如果存储的是超大文件、高吞吐场景xfs更合适。格式化命令mkfs.ext4 /dev/sdb1执行后系统会输出文件系统相关的信息这一步会把新分区变成Linux可以识别的文件系统。3.2 临时挂载并迁移旧数据新盘格式化之后目前还是一张“空表”。如果/data目录里已经有业务数据不能直接把新盘挂载到/data上否则旧数据会被“隐藏”起来。正确流程是先临时挂载到别的目录把旧数据完整复制过去再完成挂载替换。先把新分区临时挂载到/mnt/data_newmkdir -p /mnt/data_new mount /dev/sdb1 /mnt/data_new然后同步旧数据。推荐用rsync它比cp快而且支持断点续传、实时显示进度更适合大批量数据迁移rsync -avzh --infoprogress2 /data/ /mnt/data_new/注意命令里的斜杠位置/data/结尾带斜杠表示复制目录里的所有内容而不是把data这个目录本身嵌套进去目标/mnt/data_new/同样带斜杠表示直接放在该目录下。如果路径不带斜杠复制出来就会变成/mnt/data_new/data/...导致目录层级错乱。迁移数据这个环节最怕的是业务还在不停写入。如果条件允许最好先停掉对应业务或者至少保持数据不会写入的状态。如果实在不能停业务建议先做一次rsync同步然后短暂停服几秒钟再做一次增量同步rsync -avzh --delete /data/ /mnt/data_new/加了--delete参数后会把源目录已经删除的文件同步删除掉保证目标目录和源目录完全一致。数据同步完在卸载旧目录之前最好做一次对比验证du -sh /data/ /mnt/data_new/两边容量一致基本可以放心进入下一步。3.3 永久挂载用UUID写入fstab数据同步完把临时挂载的新分区卸载然后正式挂载到/dataumount /mnt/data_new mount /dev/sdb1 /data此时再执行df -h /data应该能看到/data已经使用新分区的空间了原来的数据也都还在通过刚才的rsync复制过来的。不过到这里只完成了一半重启之后挂载关系会失效还需要把它写进/etc/fstab实现开机自动挂载。先获取新分区的UUIDblkid /dev/sdb1输出里会有一串类似UUIDa1b2c3d4-...的字符串。接下来编辑/etc/fstab在文件末尾加一行UUIDa1b2c3d4-... /data ext4 defaults 0 2这行配置有6个字段我先解释清楚第一个字段是设备标识这里用UUID比直接写/dev/sdb1更可靠第二个是挂载点/data第三个是文件系统类型ext4第四个defaults是挂载选项包含rw、suid、dev、exec、auto、nouser、async等默认参数第五个0表示dump备份标记一般填0第六个2表示开机时文件系统检查顺序根分区填1其他挂载点填2填0表示不检查。改完/etc/fstab后千万别急着重启先跑一条测试命令mount -a这条命令会按照/etc/fstab重新挂载所有尚未挂载的条目。如果配置有误它会直接报错你可以当场修改。如果没报错再用df -h /data确认挂载正常此时重启也不会出问题。3.4 挂载后的验证与权限处理挂载替换完成不代表万事大吉还有几个细节等着处理。一个是权限。新格式化的分区挂载后目录所有者默认是root。如果/data原来属于某个业务账号比如www、mysql业务可能读取不了文件。需要用chown修正chown -R www:www /data另一个是测试写入。在业务正式恢复前手动创建和删除一个测试文件确认读写正常touch /data/.test rm /data/.test如果这两个命令都顺利执行说明挂载目录可写、可删没有权限问题。最后重启一次服务器验证整个流程没有遗漏开机后df -h /data依然显示新分区的容量这次扩容就算真正完成了。4. 实操二挂载新盘替换根目录给系统盘扩容4.1 为什么根目录不能在线直接替换比“指定目录扩容”更棘手的场景是根目录本身满了。很多人会想既然普通目录可以挂载新盘替换那根目录/是不是也能直接卸载再挂新盘答案是不行。根目录是整棵目录树的地基内核、systemd、各种服务进程无时无刻不在读写它。你一旦尝试umount /系统会直接卡死甚至内核崩溃这在生产环境是不可接受的。所以根目录扩容的现实路径只有两条要么在系统运行期间通过LVM逻辑卷在线扩展根分区所在的空间要么借助外部介质比如救援模式、U盘启动盘把根文件系统整体迁移到新的大容量磁盘上再用新盘作为系统盘启动。前者是把空间“扩”出来后者是把系统“挪”过去。4.2 方法一整盘迁移法替换根目录整盘迁移法适用于“系统盘整体太小想换一块更大的盘”的场景比如虚拟机原盘20G爆满想换成100G的新盘。这个操作步骤比较多我在这里给出完整流程但务必强调一定要在虚拟机或测试环境先演练生产环境请先做整机备份。准备阶段。新盘假设/dev/sdb先完成分区和格式化方法和上一章一样。然后把新盘挂载到临时目录mkdir -p /mnt/newroot mount /dev/sdb1 /mnt/newroot同步根文件系统。执行rsync把当前根目录的所有内容复制到新盘的挂载点同时要排除掉那些运行时虚拟目录rsync -axHAWXS --numeric-ids --infoprogress2 \ --exclude{/proc/*,/sys/*,/dev/*,/run/*,/tmp/*,/mnt/*,/media/*,/lostfound} \ / /mnt/newroot/命令里的-a是归档模式-x表示不跨越文件系统边界避免复制到其他挂载点-H保留硬链接-A保留ACL权限-W整文件复制-X保留扩展属性-S稀疏文件优化。这些参数组合在一起能最大程度保证复制出来的系统文件属性与原系统一致。--numeric-ids保证用户和组的ID不变避免迁移后文件所有者错乱。安装引导并修改fstab。同步完成后需要进入新系统的环境把引导程序安装到新盘上mount --bind /dev /mnt/newroot/dev mount --bind /proc /mnt/newroot/proc mount --bind /sys /mnt/newroot/sys chroot /mnt/newroot进入chroot环境后首先执行grub-install /dev/sdb update-grub同时要编辑新盘上的/etc/fstab把根分区的UUID改成新盘的UUID否则重启后会找不到根文件系统。用blkid /dev/sdb1获取新UUID然后修改/mnt/newroot/etc/fstab里根目录那一行。退出chroot卸载所有绑定的目录最后重启并在BIOS/虚拟机启动菜单里选择从新盘启动。这个流程操作起来很容易出错一旦grub-install没跑成功或者fstab写错新系统大概率起不来。所以我个人的建议是如果只是想解决根目录空间不足整盘迁移不是首选优先考虑LVM方案或者把/var、/home这类消耗大户单独挂载到新盘上变相给根目录减压。4.3 方法二LVM在线扩容根目录扩容的优雅解法LVMLogical Volume Manager是Linux里一套逻辑卷管理机制它把物理磁盘、分区和文件系统的关系从“一对一”解耦成“物理卷 - 卷组 - 逻辑卷”三层结构。理解起来可以这样类比物理卷PV相当于一块块砖头卷组VG相当于把这些砖头砌成的一个大水池逻辑卷LV相当于从水池里接出来的一根水管。当你觉得根目录这根水管出水不够时只需要往水池里添加新砖头新磁盘然后把这部分容量划给根目录对应的水管就行整个过程不需要断水也就是不需要卸载根目录、不需要停机。现在越来越多的发行版在安装系统时就默认使用LVM布局。可以用lsblk查看如果发现类似/dev/mapper/centos-root、/dev/mapper/ubuntu--vg-ubuntu--lv这样的名称说明你的根分区就是逻辑卷可以直接走LVM扩容。需要扩容时先创建物理卷pvcreate /dev/sdb1然后把新物理卷加入现有的卷组。卷组名称可以通过vgs查看假设叫centos有些系统叫vg0或ubuntu-vgvgextend centos /dev/sdb1此时水池的容量已经扩大接下来把新增容量全部划给根目录对应的逻辑卷。根目录逻辑卷名称用lvdisplay或lsblk确认通常是/dev/mapper/centos-rootlvextend -l 100%FREE /dev/mapper/centos-root这是最关键的一步逻辑卷已经变大了但文件系统还不知道。如果是ext4文件系统执行resize2fs /dev/mapper/centos-root如果是xfs文件系统要改用xfs_growfs /注意这两种文件系统的扩容命令完全不同。ext4用resize2fs指定逻辑卷设备xfs用xfs_growfs指定挂载点。曾经遇到过有人给xfs的根分区跑resize2fs结果报错不说差点以为自己把系统搞坏了。最后执行df -h你会看到根目录容量已经变成新盘扩展后的完整大小全程系统没有重启业务没有中断。LVM这套机制一旦用熟了磁盘扩容就从一个“高风险操作”变成了“日常小操作”。如果你现在正要重装系统强烈建议在安装阶段采用LVM布局给未来留足灵活性。5. 高频踩坑记录这些细节不注意扩容容易变灾难5.1 fstab写错导致系统无法启动这是挂载操作里翻车率最高的问题。症状很典型重启后系统进不了正常界面卡在“emergency mode”或“maintenance mode”提示找不到某个设备或挂载失败。原因多数是fstab里UUID抄错、挂载点目录不存在、或者文件系统类型写错。处理办法在紧急模式界面输入root密码重新挂载根目录为可写状态mount -o remount,rw /然后编辑/etc/fstab把刚才加的那行注释掉或者修正错误。改完执行reboot系统就能正常启动。要避免这个问题最好的习惯是每次改完fstab都执行一次mount -a测试。配置正确时没有任何输出配置错误时当场报错当场修正不要拿生产服务器的重启来赌。5.2 挂载后原目录里的文件“消失”了很多新手会遇到这种情况把新盘挂载到/data后发现原来/data里的文件全都不见了然后以为数据丢了急得满头大汗。其实数据没有丢。Linux的目录挂载逻辑是一旦某个分区被挂载到目录A目录A原本的内容就会被“遮挡”住就像你往一个抽屉里塞进另一个抽屉原来的文件还在只是从当前视角看不到了。要找回原来的文件也很简单先卸载新盘旧数据就重新出现了。正确流程应该是先把旧数据同步到新盘再完成挂载替换。如果你已经忘了同步就直接挂载了也不用慌卸载新盘、把旧数据rsync到临时挂载的新盘目录、再挂载回去就行。千万注意在挂载状态下直接对/data目录执行rm -rf删的是新盘里的数据旧数据还在下面埋着但如果你把挂载点目录本身删掉操作就复杂了。5.3 设备名不可靠要用UUID而不是/dev/sdX有人习惯在fstab里写/dev/sdb1这在单盘环境下通常没问题但一旦服务器有多块磁盘或者磁盘被重新插拔过设备名就可能发生漂移原来的/dev/sdb变成/dev/sdc导致系统启动时找不到正确的盘。UUID是文件系统创建时生成的一个全球唯一标识不会因为设备名变化而改变。所以fstab里统一使用UUIDxxx的写法是最稳妥的。查看UUID的命令就是前面用过的blkid /dev/sdb1。另外对新格式化完的盘blkid可能因为系统缓存没刷新而看不到UUID这时候先partprobe /dev/sdb让内核重新读取分区表然后重试。5.4 挂载后的权限问题导致应用报错挂载本身成功了但业务应用连不上目录数据读写不了。这类问题很多时候不是挂载的问题而是权限的问题。新分区格式化之后挂载点的属主、属组默认是root如果你原来的目录属于mysql用户挂载之后应用就会因为没有权限而报错。解决方式很简单挂载完成之后执行一遍chown把所有文件归属到对应的用户和组或者根据实际场景在fstab里配置uid/gid挂载选项。顺带提一句如果新盘是从Windows那边拿来的NTFS或exFAT格式Linux虽然能通过ntfs-3g等方式读取但性能和权限表现都不够好不建议在Linux服务器上使用这类文件系统。原生ext4或xfs才是正确选择。最后分享一点实用心得用Linux这么多年我最大的体会是磁盘挂载本身不难难的是对挂载概念的理解和对数据的敬畏。每次扩容前做好备份操作时确认盘符无误改完fstab执行mount -a验证这“三板斧”能挡掉绝大多数翻车场景。另外如果条件允许从装系统开始就选择LVM布局后面遇到根目录不够用就是几条命令的事完全不需要经历数据迁移和重启引导的惊悚过程。希望这篇记录能帮你少踩一些我踩过的坑让磁盘扩容这件事不再是运维里的“高危动作”。
返回列表