共计 4463 个字符,预计需要花费 12 分钟才能阅读完成。
背景
云服务器的磁盘扩容是常见的运维场景,已经操作过很多次。
公有云厂商对于云服务器的磁盘,通常都支持热扩容,在 Linux 操作系统下,一般的操作流程是:
- 公有云扩容硬盘容量规格
- 操作系统内扩容
今天遇到一起非典型场景(单硬盘多分区),之前执行的操作系统内扩容流程失败了,下文会介绍。
场景
我们常见的分区实践方式,是单硬盘单分区,这次遇到的场景是单硬盘多分区,下面分别介绍。
非 LVM
公有云 和 传统IDC 不同。云的一大好处是 弹性
。
在公有云上,云服务器磁盘一般以 ebs 的方式提供,即网络硬盘。单盘容量上限极大,而且可以很方便的进行热扩容、快照等。
所以在云上使用传统分区管理磁盘更合适。LVM 会增加管理的复杂度,核心的动态变更优势基本无法体现。
单分区
单分区的实践很简单,不同云厂对于硬盘的规格变更,此处不进行赘述,只简单介绍如何在操作系统下执行扩容。
详实步骤参考链接:华为云 – 磁盘扩容
单分区示例如下:
磁盘映射路径:/dev/vda
分区:/dev/vda1
文件系统:ext4
扩容分区
# growpart -h
growpart磁盘分区
重写分区表,使分区占用它能占用的所有空间
options:
-h | --help 打印使用和退出
--fudge F 如果部分可以调整大小,但改变会小于'F',不要调整大小(默认值:20480)
-N | --dry-run 只报告将要执行的操作,并显示新的'sfdisk -d'
-v | --verbose 增加详细信息/调试
-u | --update R 增长后更新内核分区表信息
这需要内核支持 and 'partx --update'
R is one of:
- 'auto' : [default] 尽可能更新分区
- 'force' : 尽管进行了健全检查,仍然尝试(每次失败都失败)
- 'off' : 不要尝试
- 'on' : 如果完整性检查表明不支持,则失败
Example:
- growpart /dev/sda 1 在/dev/sda上调整分区1的大小
# 调整分区大小
# growpart /dev/vda 1
扩容文件系统
常用的文件系统有 ext4
和 xfs
,可分别执行如下命令扩容:
ext4
# resize2fs /dev/vda1
xfs
# xfs_growfs /dev/vda1
至此已经调整完毕。
多分区
这次遇到的问题,就是单硬盘多分区下无法成功执行第一个分区的扩容。
多分区示例如下:
磁盘:/dev/nvme1n1
分区1:/dev/nvme1n1p1
分区2:/dev/nvme1n1p2
文件系统:ext4
[root@ip-10-76-47-100 ~]# df -h|grep nvme1n
/dev/nvme1n1p1 30G 45M 28G 1% /disk-test-1
/dev/nvme1n1p2 30G 45M 28G 1% /disk-test-2
当我们在云厂上调整磁盘规格后,执行分区1扩容,会报错,而执行分区2扩容可以成功:
[root@ip-10-76-47-100 ~]# growpart /dev/nvme1n1 1
NOCHANGE: partition 1 is size 62914560. it cannot be grown
[root@ip-10-76-47-100 ~]# growpart /dev/nvme1n1 2
CHANGED: partition=2 start=62916608 old: size=62914560 end=125831168 new: size=146798559,end=209715167
原因是 growpart
操作的是将新增容量扩展至磁盘的尾部分区,对于非尾部分区,将不能执行成功。
所以如果我们想扩容首个分区时,需要移除尾部的其他分区才可以执行成功,流程如下:
- 移除分区是高危操作,请先在云厂进行磁盘备份后再进行后续具体实施。
- 确保被移除的分区
/dev/nvme1n1p2
,没有被任何进程和用户所占用 - 将
/dev/nvme1n1p2
分区数据全量备份至其他分区或其他硬盘 -
umount
卸载/dev/nvme1n1p2
分区,将备份的数据回滚到挂载点/disk-test-2
。 - 删除
/dev/nvme1n1p2
分区。# fdisk 删除分区 [root@ip-10-76-47-100 ~]# fdisk /dev/nvme1n1 Welcome to fdisk (util-linux 2.23.2). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): p Disk /dev/nvme1n1: 107.4 GB, 107374182400 bytes, 209715200 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes Disk label type: dos Disk identifier: 0x03cb1dc0 Device Boot Start End Blocks Id System /dev/nvme1n1p1 2048 62916607 31457280 83 Linux /dev/nvme1n1p2 62916608 209715166 73399279+ 83 Linux Command (m for help): d Partition number (1,2, default 2): 2 Partition 2 is deleted Command (m for help): p Disk /dev/nvme1n1: 107.4 GB, 107374182400 bytes, 209715200 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes Disk label type: dos Disk identifier: 0x03cb1dc0 Device Boot Start End Blocks Id System /dev/nvme1n1p1 2048 62916607 31457280 83 Linux Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table. WARNING: Re-reading the partition table failed with error 16: Device or resource busy. The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8) Syncing disks. # lsblk 查看分区,此时尚未被完全删除 [root@ip-10-76-47-100 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT nvme0n1 259:0 0 50G 0 disk └─nvme0n1p1 259:1 0 50G 0 part / nvme1n1 259:2 0 100G 0 disk ├─nvme1n1p2 259:5 0 70G 0 part └─nvme1n1p1 259:3 0 30G 0 part /disk-test-1 # partprobe 重新加载分区表 [root@ip-10-76-47-100 ~]# partprobe # 再次查看分区 [root@ip-10-76-47-100 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT nvme0n1 259:0 0 50G 0 disk └─nvme0n1p1 259:1 0 50G 0 part / nvme1n1 259:2 0 100G 0 disk └─nvme1n1p1 259:3 0 30G 0 part /disk-test-1
- 执行首个分区扩容和文件系统扩容。
# 分区扩容 [root@ip-10-76-47-100 ~]# growpart /dev/nvme1n1 1 CHANGED: partition=1 start=2048 old: size=62914560 end=62916608 new: size=209713119,end=209715167 # 文件系统扩容 [root@ip-10-76-47-100 ~]# resize2fs /dev/nvme1n1p1 resize2fs 1.42.9 (28-Dec-2013) Filesystem at /dev/nvme1n1p1 is mounted on /disk-test-1; on-line resizing required old_desc_blocks = 4, new_desc_blocks = 13 The filesystem on /dev/nvme1n1p1 is now 26214139 blocks long. # 查看分区状态 [root@ip-10-76-47-100 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT nvme0n1 259:0 0 50G 0 disk └─nvme0n1p1 259:1 0 50G 0 part / nvme1n1 259:2 0 100G 0 disk └─nvme1n1p1 259:3 0 100G 0 part /disk-test-1 # 查看挂载状态 [root@ip-10-76-47-100 ~]# df -h|grep disk-test-1 /dev/nvme1n1p1 99G 60M 94G 1% /disk-test-1
LVM
单分区
单分区的扩容对比 非lvm方式
,只需要在 growpart
分区扩容后,额外执行 物理卷
和 逻辑卷
扩容。最后再执行文件系统扩容。
磁盘示例如下:
磁盘:/dev/vda
分区:/dev/vda1
逻辑卷:/dev/mapper/centos-root
文件系统:ext4
物理卷扩容
# pvresize /dev/vda1
逻辑卷扩容
# 添加物理机所有剩余可用空间
# lvextend -l +100%FREE /dev/mapper/centos-root
# 添加 指定大小 可用空间
# lvextend -L +10G /dev/mapper/centos-root
文件系统扩容
参考上文。
多分区
LVM 单硬盘多分区的场景暂时未遇到,不花费时间展开实验。
总结
- 分区扩容和文件系统扩容的命令,理论上不存在破坏数据的风险。
- 移除分区是高风险操作,执行前务必先备份硬盘。
- 云已经提供了弹性,所以没有必要单盘多分区或使用 lvm 来增加复杂度。最佳实践是单盘单分区方式管理硬盘。如果有多分区需求,请用多硬盘来实现,而不是在单一盘上绣花。
- 初始设计很重要,设计不当事后变更非常痛苦。所以多总结多思考,形成最佳实践规范。