缩减Azure上Linux虚拟机系统盘容量

【话在前头】

这么些年微软 Azure 创建虚拟机一直不能修改系统盘大小,但很多时候实际又用不了这么大的操作系统磁盘。微软自己甚至还针对 Windows 服务器镜像推出一个 smalldisk 的镜像版本(https://azure.microsoft.com/en-us/blog/new-smaller-windows-server-iaas-image/),在原有 127GB 的镜像外提供一个 32GB 版本的操作系统镜像,可以根据自己的需要进行扩容。但是 Azure 提供的 Linux 服务器镜像却都是 30GB 的版本,网上其他人的解决办法通常是下载磁盘 vhd 文件,然后本地打开后用 Hyper-V 进行缩小后再上传,或者直接用 Azure 的存储账户进行在线编辑 vhd 文件(见相关链接12)。本文通过创建小容量磁盘,直接复制磁盘分区的方式来解决这个问题。

 

【文章索引】

  1. 缩减操作系统分区容量
  2. 复制分区到小容量磁盘
  3. 修改小容量磁盘配置
  4. 相关链接

 

【一、缩减操作系统分区容量】

Azure 支持修改托管磁盘的容量,但是只支持扩大,不支持缩小,如果调整磁盘大小时设置了比之前更小的容量,则会提示下图所示的内容。

首先,与其他方案相同,需要先准备一份已缩减分区容量的系统盘。Linux 不像 Windows 提供了磁盘管理工具,可以在线缩减系统盘容量,需要创建一个当前操作系统磁盘的副本并挂载到系统上进行调整。这里先对当前系统盘创建一份快照,如下图。

然后对这个快照创建磁盘,如下图。

完成后就可以将创建好的系统盘副本附加到虚拟机中,同时再附加一个小容量的空磁盘用于创建最终的小容量系统盘。

由于复制后的磁盘分区的Uuid与之前的磁盘分区完全一样,所以如果在虚拟机启动前附加的磁盘,虚拟机启动后根目录(/)挂载点会被后附加的这块磁盘挂载,所以如果要缩减分区需要对第一块磁盘(/dev/sda)进行操作;反之如果是虚拟机启动后附加的磁盘,根目录挂载点还是第一块磁盘(/dev/sda1),如果要缩减分区需要对后挂载的磁盘(/dev/sdc 或 /dev/sdd)进行操作。

这里以启动后附加磁盘为例,小容量空磁盘是 /dev/sdc,操作系统副本磁盘是 /dev/sdd。首先需要缩减文件系统容量,分别执行“e2fsck”和“resize2fs”,其中“resize2fs”设置的大小不能大于后续分区的大小,如果不确认后续使用的各个工具的单位,这里也可以故意设置小一些,如下

root@xxx-vm:/tmp# e2fsck -f /dev/sdd1
e2fsck 1.44.5 (15-Dec-2018)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sdd1: 26148/1957888 files (0.2% non-contiguous), 365215/7831547 blocks
root@xxx-vm:/tmp# resize2fs /dev/sdd1 3G
resize2fs 1.44.5 (15-Dec-2018)
Resizing the filesystem on /dev/sdd1 to 786432 (4k) blocks.
The filesystem on /dev/sdd1 is now 786432 (4k) blocks long.

然后可以使用 parted 或 fdisk 进行分区的调整,个人觉得 parted 更简单一些,一条命令即可修改,不像 fdisk 需要还需要先删除再创建,如下

root@xxx-vm:/tmp# parted /dev/sdd
GNU Parted 3.2
Using /dev/sdd
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Warning: Not all of the space available to /dev/sdd appears to be used, you can fix the GPT to use all of the space (an extra 4194304 blocks) or continue with the current setting?
Fix/Ignore? Ignore
Model: Msft Virtual Disk (scsi)
Disk /dev/sdd: 34.4GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name  Flags
14      1049kB  4194kB  3146kB                     bios_grub
15      4194kB  134MB   130MB   fat16              boot, esp
 1      134MB   32.2GB  32.1GB  ext4

(parted) resizepart 1 4G
Warning: Shrinking a partition can cause data loss, are you sure you want to continue?
Yes/No? Yes
(parted)
Information: You may need to update /etc/fstab.

完成后可以用 mount 挂载一下分区进行验证,看看是否能进行正常挂载以及文件系统容量是否符合预期。

 

【二、复制分区到小容量磁盘】

在第一步确认没问题后可以将上述磁盘内的内容复制到小容量磁盘中,这里使用 fdisk 把调小分区容量的磁盘分区表备份下来,如下

root@xxx-vm:/tmp# fdisk /dev/sdd

Welcome to fdisk (util-linux 2.33.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

The backup GPT table is not on the end of the device. This problem will be corrected by write.

Command (m for help): O

Enter script file name: os-disk-pt

Script successfully saved.

Command (m for help): q

然后修改分区表备份文件 os-disk-pt 文件中 last-lba 的值为小容量磁盘的最后一个扇区和分区表备份文件中的磁盘路径,然后用 fdisk 对小容量磁盘导入该分区表即可,如下

root@xxx-vm:/tmp# fdisk /dev/sdc

Welcome to fdisk (util-linux 2.33.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x99a32e79.

Command (m for help): I

Enter script file name: os-disk-pt

Created a new GPT disklabel (GUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX).
Created a new partition 1 of type 'Linux filesystem' and of size 3.6 GiB.
Created a new partition 14 of type 'BIOS boot' and of size 3 MiB.
Created a new partition 15 of type 'EFI System' and of size 124 MiB.
Script successfully applied.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

完成后分别对所有分区使用 dd 命令复制即可,如下

root@xxx-vm:/tmp# dd if=/dev/sdd1 of=/dev/sdc1 bs=1M
3686+1 records in
3686+1 records out
3865782784 bytes (3.9 GB, 3.6 GiB) copied, 179.995 s, 21.5 MB/s
root@xxx-vm:/tmp# dd if=/dev/sdd14 of=/dev/sdc14 bs=1M
3+0 records in
3+0 records out
3145728 bytes (3.1 MB, 3.0 MiB) copied, 0.147453 s, 21.3 MB/s
root@xxx-vm:/tmp# dd if=/dev/sdd15 of=/dev/sdc15 bs=1M
124+0 records in
124+0 records out
130023424 bytes (130 MB, 124 MiB) copied, 5.775 s, 22.5 MB/s

完成后也可以用 mount 挂载一下新的分区进行验证,没问题后即可关闭该虚拟机。

 

【三、修改小容量磁盘配置】

通过界面创建的磁盘是不带有操作系统类型的,也没法让虚拟机将该磁盘作为系统盘进行启动,这里需要使用 Azure 的命令行,例如使用 Azure Powershell,可以参考相关链接3进行安装。

然后打开 Powershell,输入 “Connect-AzAccount”,即可弹出登录 Azure 的对话框,并进行确认,完成后会显示账户的所有订阅,如下图

然后输入下列命令设置以下几个环境变量

$DiskID = "磁盘资源ID"
$VMName = "虚拟机名称"
$AzSubscription = "订阅名"

其中“磁盘资源ID”需要进入磁盘页面,并在“属性”页面中找到“资源ID”即为该内容,类似 “/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/xxxxxxxx/providers/Microsoft.Compute/disks/xxxxxxxx”,如下图

然后再执行下列命令即可

# 指定订阅
Select-AzSubscription -Subscription $AzSubscription

# 获取虚拟机信息
$VM = Get-AzVm | ? Name -eq $VMName

# 获取磁盘信息
$Disk = Get-AzDisk | ? Id -eq $DiskID

# 修改磁盘操作系统类型
$Disk.OsType = "Linux"

# 修改磁盘 Hyper-V 代数(宿主机为V2时需要手动设置)
$Disk.HyperVGeneration = "V2"

# 更新磁盘设置
Update-AzDisk -ResourceGroupName $VM.ResourceGroupName -DiskName $Disk.Name -Disk $Disk

完成后即可在虚拟机页面中,选择“磁盘” -> “交换 OS 磁盘”,刚刚创建的小容量磁盘即会出现在这个页面中,确定后启动虚拟机即可。

 

【四、相关链接】

  1. How to shrink a managed disk:https://devblogs.microsoft.com/premier-developer/how-to-shrink-a-managed-disk/
  2. Shrink an Azure VMs OS Managed Disk using PowerShell:https://jrudlin.github.io/2019-08-27-shrink-azure-vm-osdisk/
  3. Install the Azure Az PowerShell module:https://docs.microsoft.com/en-us/powershell/azure/install-az-ps
posted @ 2021-08-09 09:11  大魔王mAysWINd  阅读(1045)  评论(1编辑  收藏  举报